diff --git a/.github/workflows/build-submit-android.yml b/.github/workflows/build-submit-android.yml index 051e951510..8cbd90984c 100644 --- a/.github/workflows/build-submit-android.yml +++ b/.github/workflows/build-submit-android.yml @@ -26,9 +26,9 @@ jobs: uses: actions/checkout@v4 - name: šŸ”§ Setup Node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: - node-version: 18.x + node-version-file: .nvmrc cache: yarn - name: šŸ”Ø Setup EAS @@ -49,10 +49,14 @@ jobs: - name: āš™ļø Install dependencies run: yarn install + - name: šŸ”¤ Compile translations + run: yarn intl:build + - name: āœļø Write environment variables run: | + export json='${{ secrets.GOOGLE_SERVICES_TOKEN }}' echo "${{ secrets.ENV_TOKEN }}" > .env - echo "${{ secrets.GOOGLE_SERVICES_TOKEN }}" > google-services.json + echo "$json" > google-services.json - name: šŸ—ļø EAS Build run: yarn use-build-number eas build -p android --profile production --local --output build.aab --non-interactive diff --git a/.github/workflows/build-submit-ios.yml b/.github/workflows/build-submit-ios.yml index 0fd691bb92..f5188b4b4b 100644 --- a/.github/workflows/build-submit-ios.yml +++ b/.github/workflows/build-submit-ios.yml @@ -28,9 +28,9 @@ jobs: uses: actions/checkout@v4 - name: šŸ”§ Setup Node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: - node-version: 18.x + node-version-file: .nvmrc cache: yarn - name: šŸ”Ø Setup EAS @@ -60,6 +60,9 @@ jobs: # change unless the yarn version changes as well. key: ${{ runner.os }}-pods-${{ hashFiles('yarn.lock') }} + - name: šŸ”¤ Compile translations + run: yarn intl:build + - name: āœļø Write environment variables run: | echo "${{ secrets.ENV_TOKEN }}" > .env diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 508da536b5..9aa55ca07a 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -32,12 +32,12 @@ jobs: name: Run tests runs-on: ubuntu-latest steps: - - name: Install node 18 - uses: actions/setup-node@v4 - with: - node-version: 18 - name: Check out Git repository uses: actions/checkout@v3 + - name: Install node + uses: actions/setup-node@v4 + with: + node-version-file: .nvmrc - name: Yarn install uses: Wandalen/wretry.action@master with: diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000000..3c032078a4 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +18 diff --git a/Dockerfile b/Dockerfile index 47afa61a36..3ad05b6ec6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,7 +23,7 @@ COPY . . RUN mkdir --parents $NVM_DIR && \ wget \ --output-document=/tmp/nvm-install.sh \ - https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh && \ + https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh && \ bash /tmp/nvm-install.sh RUN \. "$NVM_DIR/nvm.sh" && \ @@ -31,7 +31,7 @@ RUN \. "$NVM_DIR/nvm.sh" && \ nvm use $NODE_VERSION && \ npm install --global yarn && \ yarn && \ - yarn intl:compile && \ + yarn intl:build && \ yarn build-web # DEBUG diff --git a/README.md b/README.md index 0cbfe77377..49c4b016ff 100644 --- a/README.md +++ b/README.md @@ -65,8 +65,6 @@ If you discover any security issues, please send an email to security@bsky.app. Bluesky is an open social network built on the AT Protocol, a flexible technology that will never lock developers out of the ecosystems that they help build. With atproto, third-party can be as seamless as first-party through custom feeds, federated services, clients, and more. -If you're a developer interested in building on atproto, we'd love to email you a Bluesky invite code. Simply share your GitHub (or similar) profile with us via [this form](https://forms.gle/BF21oxVNZiDjDhXF9). - ## License (MIT) See [./LICENSE](./LICENSE) for the full license. diff --git a/app.config.js b/app.config.js index e710420b09..2552d34897 100644 --- a/app.config.js +++ b/app.config.js @@ -11,6 +11,17 @@ const DARK_SPLASH_CONFIG = { resizeMode: 'cover', } +const SPLASH_CONFIG_ANDROID = { + backgroundColor: '#0c7cff', + image: './assets/splash.png', + resizeMode: 'cover', +} +const DARK_SPLASH_CONFIG_ANDROID = { + backgroundColor: '#0f141b', + image: './assets/splash-dark.png', + resizeMode: 'cover', +} + module.exports = function (config) { /** * App version number. Should be incremented as part of a release cycle. @@ -65,10 +76,13 @@ module.exports = function (config) { ...SPLASH_CONFIG, dark: DARK_SPLASH_CONFIG, }, + entitlements: { + 'com.apple.security.application-groups': 'group.app.bsky', + }, }, androidStatusBar: { - barStyle: 'dark-content', - backgroundColor: '#ffffff', + barStyle: 'light-content', + backgroundColor: '#00000000', }, android: { icon: './assets/icon.png', @@ -89,13 +103,17 @@ module.exports = function (config) { scheme: 'https', host: 'bsky.app', }, + { + scheme: 'http', + host: 'localhost:19006', + }, ], category: ['BROWSABLE', 'DEFAULT'], }, ], splash: { - ...SPLASH_CONFIG, - dark: DARK_SPLASH_CONFIG, + ...SPLASH_CONFIG_ANDROID, + dark: DARK_SPLASH_CONFIG_ANDROID, }, }, web: { @@ -114,12 +132,14 @@ module.exports = function (config) { { ios: { deploymentTarget: '13.4', + newArchEnabled: false, }, android: { compileSdkVersion: 34, targetSdkVersion: 34, buildToolsVersion: '34.0.0', kotlinVersion: '1.8.0', + newArchEnabled: false, }, }, ], @@ -133,13 +153,33 @@ module.exports = function (config) { 'expo-notifications', { icon: './assets/icon-android-notification.png', - color: '#ffffff', + color: '#1185fe', }, ], './plugins/withAndroidManifestPlugin.js', + './plugins/withAndroidManifestFCMIconPlugin.js', + './plugins/withAndroidStylesWindowBackgroundPlugin.js', + './plugins/shareExtension/withShareExtensions.js', ].filter(Boolean), extra: { eas: { + build: { + experimental: { + ios: { + appExtensions: [ + { + targetName: 'Share-with-Bluesky', + bundleIdentifier: 'xyz.blueskyweb.app.Share-with-Bluesky', + entitlements: { + 'com.apple.security.application-groups': [ + 'group.app.bsky', + ], + }, + }, + ], + }, + }, + }, projectId: '55bd077a-d905-4184-9c7f-94789ba0f302', }, }, diff --git a/assets/icons/checkThick_stroke2_corner0_rounded.svg b/assets/icons/checkThick_stroke2_corner0_rounded.svg new file mode 100644 index 0000000000..54af3e8598 --- /dev/null +++ b/assets/icons/checkThick_stroke2_corner0_rounded.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/clipboard_stroke2_corner2_rounded.svg b/assets/icons/clipboard_stroke2_corner2_rounded.svg new file mode 100644 index 0000000000..f403cfb929 --- /dev/null +++ b/assets/icons/clipboard_stroke2_corner2_rounded.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/magnifyingGlass2_stroke2_corner0_rounded.svg b/assets/icons/magnifyingGlass2_stroke2_corner0_rounded.svg new file mode 100644 index 0000000000..2759aaf2cc --- /dev/null +++ b/assets/icons/magnifyingGlass2_stroke2_corner0_rounded.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/mute_stroke2_corner0_rounded.svg b/assets/icons/mute_stroke2_corner0_rounded.svg new file mode 100644 index 0000000000..8ebecb3920 --- /dev/null +++ b/assets/icons/mute_stroke2_corner0_rounded.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/pageText_stroke2_corner0_rounded.svg b/assets/icons/pageText_stroke2_corner0_rounded.svg new file mode 100644 index 0000000000..826a36cd7e --- /dev/null +++ b/assets/icons/pageText_stroke2_corner0_rounded.svg @@ -0,0 +1 @@ + diff --git a/bskyweb/README.md b/bskyweb/README.md index c8efe04482..640c30f4ad 100644 --- a/bskyweb/README.md +++ b/bskyweb/README.md @@ -6,9 +6,9 @@ To build the SPA bundle (`bundle.web.js`), first get a JavaScript development environment set up. Either follow the top-level README, or something quick like: - # install nodejs 18 (specifically) - nvm install 18 - nvm use 18 + # install nodejs + nvm install + nvm use npm install --global yarn # setup tools and deps (in top level of this repo) diff --git a/bskyweb/cmd/bskyweb/mailmodo.go b/bskyweb/cmd/bskyweb/mailmodo.go deleted file mode 100644 index e892971f9c..0000000000 --- a/bskyweb/cmd/bskyweb/mailmodo.go +++ /dev/null @@ -1,70 +0,0 @@ -package main - -import ( - "bytes" - "context" - "crypto/sha256" - "encoding/json" - "fmt" - "net/http" - "time" -) - -type Mailmodo struct { - httpClient *http.Client - APIKey string - BaseURL string - ListName string -} - -func NewMailmodo(apiKey, listName string) *Mailmodo { - return &Mailmodo{ - APIKey: apiKey, - BaseURL: "https://api.mailmodo.com/api/v1", - httpClient: &http.Client{}, - ListName: listName, - } -} - -func (m *Mailmodo) request(ctx context.Context, httpMethod string, apiMethod string, data any) error { - endpoint := fmt.Sprintf("%s/%s", m.BaseURL, apiMethod) - js, err := json.Marshal(data) - if err != nil { - return fmt.Errorf("Mailmodo JSON encoding failed: %w", err) - } - req, err := http.NewRequestWithContext(ctx, httpMethod, endpoint, bytes.NewBuffer(js)) - if err != nil { - return fmt.Errorf("Mailmodo HTTP creating request %s %s failed: %w", httpMethod, apiMethod, err) - } - req.Header.Set("mmApiKey", m.APIKey) - req.Header.Set("Content-Type", "application/json") - - res, err := m.httpClient.Do(req) - if err != nil { - return fmt.Errorf("Mailmodo HTTP making request %s %s failed: %w", httpMethod, apiMethod, err) - } - defer res.Body.Close() - - status := struct { - Success bool `json:"success"` - Message string `json:"message"` - }{} - if err := json.NewDecoder(res.Body).Decode(&status); err != nil { - return fmt.Errorf("Mailmodo HTTP parsing response %s %s failed: %w", httpMethod, apiMethod, err) - } - if !status.Success { - return fmt.Errorf("Mailmodo API response %s %s failed: %s", httpMethod, apiMethod, status.Message) - } - return nil -} - -func (m *Mailmodo) AddToList(ctx context.Context, email string) error { - return m.request(ctx, "POST", "addToList", map[string]any{ - "listName": m.ListName, - "email": email, - "data": map[string]any{ - "email_hashed": fmt.Sprintf("%x", sha256.Sum256([]byte(email))), - }, - "created_at": time.Now().UTC().Format(time.RFC3339), - }) -} diff --git a/bskyweb/cmd/bskyweb/main.go b/bskyweb/cmd/bskyweb/main.go index a2952cae2b..5185ff573a 100644 --- a/bskyweb/cmd/bskyweb/main.go +++ b/bskyweb/cmd/bskyweb/main.go @@ -40,18 +40,6 @@ func run(args []string) { // retain old PDS env var for easy transition EnvVars: []string{"ATP_APPVIEW_HOST", "ATP_PDS_HOST"}, }, - &cli.StringFlag{ - Name: "mailmodo-api-key", - Usage: "Mailmodo API key", - Required: false, - EnvVars: []string{"MAILMODO_API_KEY"}, - }, - &cli.StringFlag{ - Name: "mailmodo-list-name", - Usage: "Mailmodo contact list to add email addresses to", - Required: false, - EnvVars: []string{"MAILMODO_LIST_NAME"}, - }, &cli.StringFlag{ Name: "http-address", Usage: "Specify the local IP/port to bind to", diff --git a/bskyweb/cmd/bskyweb/server.go b/bskyweb/cmd/bskyweb/server.go index 4b1a824935..d30781b9ce 100644 --- a/bskyweb/cmd/bskyweb/server.go +++ b/bskyweb/cmd/bskyweb/server.go @@ -2,11 +2,9 @@ package main import ( "context" - "encoding/json" "errors" "fmt" "io/fs" - "io/ioutil" "net/http" "os" "os/signal" @@ -29,25 +27,19 @@ import ( ) type Server struct { - echo *echo.Echo - httpd *http.Server - mailmodo *Mailmodo - xrpcc *xrpc.Client + echo *echo.Echo + httpd *http.Server + xrpcc *xrpc.Client } func serve(cctx *cli.Context) error { debug := cctx.Bool("debug") httpAddress := cctx.String("http-address") appviewHost := cctx.String("appview-host") - mailmodoAPIKey := cctx.String("mailmodo-api-key") - mailmodoListName := cctx.String("mailmodo-list-name") // Echo e := echo.New() - // Mailmodo client. - mailmodo := NewMailmodo(mailmodoAPIKey, mailmodoListName) - // create a new session (no auth) xrpcc := &xrpc.Client{ Client: cliutil.NewHttpClient(), @@ -77,9 +69,8 @@ func serve(cctx *cli.Context) error { // server // server := &Server{ - echo: e, - mailmodo: mailmodo, - xrpcc: xrpcc, + echo: e, + xrpcc: xrpcc, } // Create the HTTP server. @@ -180,6 +171,7 @@ func serve(cctx *cli.Context) error { e.GET("/", server.WebHome) // generic routes + e.GET("/hashtag/:tag", server.WebGeneric) e.GET("/search", server.WebGeneric) e.GET("/feeds", server.WebGeneric) e.GET("/notifications", server.WebGeneric) @@ -203,6 +195,7 @@ func serve(cctx *cli.Context) error { e.GET("/support/tos", server.WebGeneric) e.GET("/support/community-guidelines", server.WebGeneric) e.GET("/support/copyright", server.WebGeneric) + e.GET("/intent/compose", server.WebGeneric) // profile endpoints; only first populates info e.GET("/profile/:handleOrDID", server.WebProfile) @@ -220,9 +213,6 @@ func serve(cctx *cli.Context) error { e.GET("/profile/:handleOrDID/post/:rkey/liked-by", server.WebGeneric) e.GET("/profile/:handleOrDID/post/:rkey/reposted-by", server.WebGeneric) - // Mailmodo - e.POST("/api/waitlist", server.apiWaitlist) - // Start the server. log.Infof("starting server address=%s", httpAddress) go func() { @@ -397,36 +387,3 @@ func (srv *Server) WebProfile(c echo.Context) error { data["requestHost"] = req.Host return c.Render(http.StatusOK, "profile.html", data) } - -func (srv *Server) apiWaitlist(c echo.Context) error { - type jsonError struct { - Error string `json:"error"` - } - - // Read the API request. - type apiRequest struct { - Email string `json:"email"` - } - - bodyReader := http.MaxBytesReader(c.Response(), c.Request().Body, 16*1024) - payload, err := ioutil.ReadAll(bodyReader) - if err != nil { - return err - } - var req apiRequest - if err := json.Unmarshal(payload, &req); err != nil { - return c.JSON(http.StatusBadRequest, jsonError{Error: "Invalid API request"}) - } - - if req.Email == "" { - return c.JSON(http.StatusBadRequest, jsonError{Error: "Please enter a valid email address."}) - } - - if err := srv.mailmodo.AddToList(c.Request().Context(), req.Email); err != nil { - log.Errorf("adding email to waitlist failed: %s", err) - return c.JSON(http.StatusBadRequest, jsonError{ - Error: "Storing email in waitlist failed. Please enter a valid email address.", - }) - } - return c.JSON(http.StatusOK, map[string]bool{"success": true}) -} diff --git a/bskyweb/templates/base.html b/bskyweb/templates/base.html index e29e4032bb..55447552ea 100644 --- a/bskyweb/templates/base.html +++ b/bskyweb/templates/base.html @@ -44,6 +44,12 @@ scrollbar-gutter: stable both-edges; } + /* Buttons and inputs have a font set by UA, so we'll have to reset that */ + button, input, textarea { + font: inherit; + line-height: inherit; + } + /* Color theming */ /* Default will always be white */ :root { @@ -205,6 +211,12 @@ [data-tooltip]:hover::before { display:block; } + + /* NativeDropdown component */ + .radix-dropdown-item:focus, + .nativeDropdown-item:focus { + outline: none; + } {% include "scripts.html" %} diff --git a/index.web.js b/index.web.js index 4dee831cda..9623734512 100644 --- a/index.web.js +++ b/index.web.js @@ -1,3 +1,5 @@ +import '#/platform/markBundleStartTime' + import '#/platform/polyfills' import {registerRootComponent} from 'expo' import {doPolyfill} from '#/lib/api/api-polyfill' diff --git a/modules/Share-with-Bluesky/Info.plist b/modules/Share-with-Bluesky/Info.plist new file mode 100644 index 0000000000..90fe923455 --- /dev/null +++ b/modules/Share-with-Bluesky/Info.plist @@ -0,0 +1,41 @@ + + + + + NSExtension + + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).ShareViewController + NSExtensionAttributes + + NSExtensionActivationRule + + NSExtensionActivationSupportsText + + NSExtensionActivationSupportsWebURLWithMaxCount + 1 + NSExtensionActivationSupportsImageWithMaxCount + 10 + + + NSExtensionPointIdentifier + com.apple.share-services + + MainAppScheme + bluesky + CFBundleName + $(PRODUCT_NAME) + CFBundleDisplayName + Extension + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + $(MARKETING_VERSION) + + diff --git a/modules/Share-with-Bluesky/Share-with-Bluesky.entitlements b/modules/Share-with-Bluesky/Share-with-Bluesky.entitlements new file mode 100644 index 0000000000..d2253d31f8 --- /dev/null +++ b/modules/Share-with-Bluesky/Share-with-Bluesky.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.application-groups + + group.app.bsky + + + diff --git a/modules/Share-with-Bluesky/ShareViewController.swift b/modules/Share-with-Bluesky/ShareViewController.swift new file mode 100644 index 0000000000..4c1d635ce3 --- /dev/null +++ b/modules/Share-with-Bluesky/ShareViewController.swift @@ -0,0 +1,153 @@ +import UIKit + +class ShareViewController: UIViewController { + // This allows other forks to use this extension while also changing their + // scheme. + let appScheme = Bundle.main.object(forInfoDictionaryKey: "MainAppScheme") as? String ?? "bluesky" + + // + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + guard let extensionItem = extensionContext?.inputItems.first as? NSExtensionItem, + let attachments = extensionItem.attachments, + let firstAttachment = extensionItem.attachments?.first + else { + self.completeRequest() + return + } + + Task { + if firstAttachment.hasItemConformingToTypeIdentifier("public.text") { + await self.handleText(item: firstAttachment) + } else if firstAttachment.hasItemConformingToTypeIdentifier("public.url") { + await self.handleUrl(item: firstAttachment) + } else if firstAttachment.hasItemConformingToTypeIdentifier("public.image") { + await self.handleImages(items: attachments) + } else { + self.completeRequest() + } + } + } + + private func handleText(item: NSItemProvider) async -> Void { + do { + if let data = try await item.loadItem(forTypeIdentifier: "public.text") as? String { + if let encoded = data.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed), + let url = URL(string: "\(self.appScheme)://intent/compose?text=\(encoded)") + { + _ = self.openURL(url) + } + } + self.completeRequest() + } catch { + self.completeRequest() + } + } + + private func handleUrl(item: NSItemProvider) async -> Void { + do { + if let data = try await item.loadItem(forTypeIdentifier: "public.url") as? URL { + if let encoded = data.absoluteString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed), + let url = URL(string: "\(self.appScheme)://intent/compose?text=\(encoded)") + { + _ = self.openURL(url) + } + } + self.completeRequest() + } catch { + self.completeRequest() + } + } + + private func handleImages(items: [NSItemProvider]) async -> Void { + let firstFourItems: [NSItemProvider] + if items.count < 4 { + firstFourItems = items + } else { + firstFourItems = Array(items[0...3]) + } + + var valid = true + var imageUris = "" + + for (index, item) in firstFourItems.enumerated() { + var imageUriInfo: String? = nil + + do { + if let dataUri = try await item.loadItem(forTypeIdentifier: "public.image") as? URL { + // We need to duplicate this image, since we don't have access to the outgoing temp directory + // We also will get the image dimensions here, sinze RN makes it difficult to get those dimensions for local files + let data = try Data(contentsOf: dataUri) + let image = UIImage(data: data) + imageUriInfo = self.saveImageWithInfo(image) + } else if let image = try await item.loadItem(forTypeIdentifier: "public.image") as? UIImage { + imageUriInfo = self.saveImageWithInfo(image) + } + } catch { + valid = false + } + + if let imageUriInfo = imageUriInfo { + imageUris.append(imageUriInfo) + if index < items.count - 1 { + imageUris.append(",") + } + } else { + valid = false + } + } + + if valid, + let encoded = imageUris.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed), + let url = URL(string: "\(self.appScheme)://intent/compose?imageUris=\(encoded)") + { + _ = self.openURL(url) + } + + self.completeRequest() + } + + private func saveImageWithInfo(_ image: UIImage?) -> String? { + guard let image = image else { + return nil + } + + do { + // Saving this file to the bundle group's directory lets us access it from + // inside of the app. Otherwise, we wouldn't have access even though the + // extension does. + if let dir = FileManager() + .containerURL( + forSecurityApplicationGroupIdentifier: "group.app.bsky") + { + let filePath = "\(dir.absoluteString)\(ProcessInfo.processInfo.globallyUniqueString).jpeg" + + if let newUri = URL(string: filePath), + let jpegData = image.jpegData(compressionQuality: 1) + { + try jpegData.write(to: newUri) + return "\(newUri.absoluteString)|\(image.size.width)|\(image.size.height)" + } + } + return nil + } catch { + return nil + } + } + + private func completeRequest() -> Void { + self.extensionContext?.completeRequest(returningItems: nil) + } + + @objc func openURL(_ url: URL) -> Bool { + var responder: UIResponder? = self + while responder != nil { + if let application = responder as? UIApplication { + return application.perform(#selector(openURL(_:)), with: url) != nil + } + responder = responder?.next + } + return false + } +} diff --git a/modules/expo-receive-android-intents/README.md b/modules/expo-receive-android-intents/README.md new file mode 100644 index 0000000000..7e8506860c --- /dev/null +++ b/modules/expo-receive-android-intents/README.md @@ -0,0 +1,8 @@ +# Expo Receive Android Intents + +This module handles incoming intents on Android. Handled intents are `text/plain` and `image/*` (single or multiple). +The module handles saving images to the app's filesystem for access within the app, limiting the selection of images +to a max of four, and handling intent types. No JS code is required for this module, and it is no-op on non-android +platforms. + +No installation is required. Gradle will automatically add this module on build. diff --git a/modules/expo-receive-android-intents/android/.gitignore b/modules/expo-receive-android-intents/android/.gitignore new file mode 100644 index 0000000000..877b87e9a5 --- /dev/null +++ b/modules/expo-receive-android-intents/android/.gitignore @@ -0,0 +1,15 @@ +# OSX +# +.DS_Store + +# Android/IntelliJ +# +build/ +.idea +.gradle +local.properties +*.iml +*.hprof + +# Bundle artifacts +*.jsbundle diff --git a/modules/expo-receive-android-intents/android/build.gradle b/modules/expo-receive-android-intents/android/build.gradle new file mode 100644 index 0000000000..3712dda40f --- /dev/null +++ b/modules/expo-receive-android-intents/android/build.gradle @@ -0,0 +1,92 @@ +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' +apply plugin: 'maven-publish' + +group = 'xyz.blueskyweb.app.exporeceiveandroidintents' +version = '0.4.1' + +buildscript { + def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle") + if (expoModulesCorePlugin.exists()) { + apply from: expoModulesCorePlugin + applyKotlinExpoModulesCorePlugin() + } + + // Simple helper that allows the root project to override versions declared by this library. + ext.safeExtGet = { prop, fallback -> + rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback + } + + // Ensures backward compatibility + ext.getKotlinVersion = { + if (ext.has("kotlinVersion")) { + ext.kotlinVersion() + } else { + ext.safeExtGet("kotlinVersion", "1.8.10") + } + } + + repositories { + mavenCentral() + } + + dependencies { + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${getKotlinVersion()}") + } +} + +afterEvaluate { + publishing { + publications { + release(MavenPublication) { + from components.release + } + } + repositories { + maven { + url = mavenLocal().url + } + } + } +} + +android { + compileSdkVersion safeExtGet("compileSdkVersion", 33) + + def agpVersion = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION + if (agpVersion.tokenize('.')[0].toInteger() < 8) { + compileOptions { + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_11.majorVersion + } + } + + namespace "xyz.blueskyweb.app.exporeceiveandroidintents" + defaultConfig { + minSdkVersion safeExtGet("minSdkVersion", 21) + targetSdkVersion safeExtGet("targetSdkVersion", 34) + versionCode 1 + versionName "0.4.1" + } + lintOptions { + abortOnError false + } + publishing { + singleVariant("release") { + withSourcesJar() + } + } +} + +repositories { + mavenCentral() +} + +dependencies { + implementation project(':expo-modules-core') + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}" +} diff --git a/modules/expo-receive-android-intents/android/src/main/AndroidManifest.xml b/modules/expo-receive-android-intents/android/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..bdae66c8f5 --- /dev/null +++ b/modules/expo-receive-android-intents/android/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + diff --git a/modules/expo-receive-android-intents/android/src/main/java/xyz/blueskyweb/app/exporeceiveandroidintents/ExpoReceiveAndroidIntentsModule.kt b/modules/expo-receive-android-intents/android/src/main/java/xyz/blueskyweb/app/exporeceiveandroidintents/ExpoReceiveAndroidIntentsModule.kt new file mode 100644 index 0000000000..c2e17fb80a --- /dev/null +++ b/modules/expo-receive-android-intents/android/src/main/java/xyz/blueskyweb/app/exporeceiveandroidintents/ExpoReceiveAndroidIntentsModule.kt @@ -0,0 +1,119 @@ +package xyz.blueskyweb.app.exporeceiveandroidintents + +import android.content.Intent +import android.graphics.Bitmap +import android.net.Uri +import android.os.Build +import android.provider.MediaStore +import androidx.core.net.toUri +import expo.modules.kotlin.modules.Module +import expo.modules.kotlin.modules.ModuleDefinition +import java.io.File +import java.io.FileOutputStream +import java.net.URLEncoder + +class ExpoReceiveAndroidIntentsModule : Module() { + override fun definition() = ModuleDefinition { + Name("ExpoReceiveAndroidIntents") + + OnNewIntent { + handleIntent(it) + } + } + + private fun handleIntent(intent: Intent?) { + if(appContext.currentActivity == null || intent == null) return + + if (intent.action == Intent.ACTION_SEND) { + if (intent.type == "text/plain") { + handleTextIntent(intent) + } else if (intent.type.toString().startsWith("image/")) { + handleImageIntent(intent) + } + } else if (intent.action == Intent.ACTION_SEND_MULTIPLE) { + if (intent.type.toString().startsWith("image/")) { + handleImagesIntent(intent) + } + } + } + + private fun handleTextIntent(intent: Intent) { + intent.getStringExtra(Intent.EXTRA_TEXT)?.let { + val encoded = URLEncoder.encode(it, "UTF-8") + "bluesky://intent/compose?text=${encoded}".toUri().let { uri -> + val newIntent = Intent(Intent.ACTION_VIEW, uri) + appContext.currentActivity?.startActivity(newIntent) + } + } + } + + private fun handleImageIntent(intent: Intent) { + val uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + intent.getParcelableExtra(Intent.EXTRA_STREAM, Uri::class.java) + } else { + intent.getParcelableExtra(Intent.EXTRA_STREAM) + } + if (uri == null) return + + handleImageIntents(listOf(uri)) + } + + private fun handleImagesIntent(intent: Intent) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM, Uri::class.java)?.let { + handleImageIntents(it.filterIsInstance().take(4)) + } + } else { + intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM)?.let { + handleImageIntents(it.filterIsInstance().take(4)) + } + } + } + + private fun handleImageIntents(uris: List) { + var allParams = "" + + uris.forEachIndexed { index, uri -> + val info = getImageInfo(uri) + val params = buildUriData(info) + allParams = "${allParams}${params}" + + if (index < uris.count() - 1) { + allParams = "${allParams}," + } + } + + val encoded = URLEncoder.encode(allParams, "UTF-8") + + "bluesky://intent/compose?imageUris=${encoded}".toUri().let { + val newIntent = Intent(Intent.ACTION_VIEW, it) + appContext.currentActivity?.startActivity(newIntent) + } + } + + private fun getImageInfo(uri: Uri): Map { + val bitmap = MediaStore.Images.Media.getBitmap(appContext.currentActivity?.contentResolver, uri) + // We have to save this so that we can access it later when uploading the image. + // createTempFile will automatically place a unique string between "img" and "temp.jpeg" + val file = File.createTempFile("img", "temp.jpeg", appContext.currentActivity?.cacheDir) + val out = FileOutputStream(file) + bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out) + out.flush() + out.close() + + return mapOf( + "width" to bitmap.width, + "height" to bitmap.height, + "path" to file.path.toString() + ) + } + + // We will pas the width and height to the app here, since getting measurements + // on the RN side is a bit more involved, and we already have them here anyway. + private fun buildUriData(info: Map): String { + val path = info.getValue("path") + val width = info.getValue("width") + val height = info.getValue("height") + return "file://${path}|${width}|${height}" + } +} diff --git a/modules/expo-receive-android-intents/expo-module.config.json b/modules/expo-receive-android-intents/expo-module.config.json new file mode 100644 index 0000000000..8f01fb6c9f --- /dev/null +++ b/modules/expo-receive-android-intents/expo-module.config.json @@ -0,0 +1,6 @@ +{ + "platforms": ["android"], + "android": { + "modules": ["xyz.blueskyweb.app.exporeceiveandroidintents.ExpoReceiveAndroidIntentsModule"] + } +} diff --git a/modules/react-native-ui-text-view/ios/RNUITextView.swift b/modules/react-native-ui-text-view/ios/RNUITextView.swift index 9c21d45b5e..3fb55873dc 100644 --- a/modules/react-native-ui-text-view/ios/RNUITextView.swift +++ b/modules/react-native-ui-text-view/ios/RNUITextView.swift @@ -108,14 +108,26 @@ class RNUITextView: UIView { fractionOfDistanceBetweenInsertionPoints: nil ) + var lastUpperBound: String.Index? = nil for child in self.reactSubviews() { if let child = child as? RNUITextViewChild, let childText = child.text { let fullText = self.textView.attributedText.string - let range = fullText.range(of: childText) - + + // We want to skip over the children we have already checked, otherwise we could run into + // collisions of similar strings (i.e. links that get shortened to the same hostname but + // different paths) + let range = fullText.range(of: childText, options: [], range: (lastUpperBound ?? String.Index(utf16Offset: 0, in: fullText) )..= lowerBound.utf16Offset(in: fullText) && charIndex <= upperBound.utf16Offset(in: fullText) { + let lowerOffset = lowerBound.utf16Offset(in: fullText) + let upperOffset = upperBound.utf16Offset(in: fullText) + + if charIndex >= lowerOffset, + charIndex <= upperOffset + { return child + } else { + lastUpperBound = upperBound } } } diff --git a/package.json b/package.json index 14b1e2f908..bb3aaca372 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bsky.app", - "version": "1.69.0", + "version": "1.72.0", "private": true, "engines": { "node": ">=18" @@ -36,14 +36,15 @@ "perf:test:measure": "NODE_ENV=test flashlight test --bundleId xyz.blueskyweb.app --testCommand 'yarn perf:test' --duration 150000 --resultsFilePath .perf/results.json", "perf:test:results": "NODE_ENV=test flashlight report .perf/results.json", "perf:measure": "NODE_ENV=test flashlight measure", - "intl:build": "yarn intl:check && yarn intl:compile", + "intl:build": "yarn intl:extract && yarn intl:compile", "intl:check": "yarn intl:extract && git diff-index -G'(^[^\\*# /])|(^#\\w)|(^\\s+[^\\*#/])' HEAD || (echo '\nāš ļø i18n detected un-extracted translations\n' && exit 1)", "intl:extract": "lingui extract", "intl:compile": "lingui compile", - "nuke": "rm -rf ./node_modules && rm -rf ./ios && rm -rf ./android" + "nuke": "rm -rf ./node_modules && rm -rf ./ios && rm -rf ./android", + "update-extensions": "scripts/updateExtensions.sh" }, "dependencies": { - "@atproto/api": "^0.9.5", + "@atproto/api": "^0.10.5", "@bam.tech/react-native-image-resizer": "^3.0.4", "@braintree/sanitize-url": "^6.0.2", "@emoji-mart/react": "^1.1.1", @@ -57,11 +58,11 @@ "@lingui/react": "^4.5.0", "@mattermost/react-native-paste-input": "^0.6.4", "@miblanchard/react-native-slider": "^2.3.1", + "@radix-ui/react-dropdown-menu": "^2.0.6", "@react-native-async-storage/async-storage": "1.21.0", "@react-native-camera-roll/camera-roll": "^5.2.2", "@react-native-clipboard/clipboard": "^1.10.0", "@react-native-community/blur": "^4.3.0", - "@react-native-community/datetimepicker": "7.6.1", "@react-native-masked-view/masked-view": "0.3.0", "@react-native-menu/menu": "^0.8.0", "@react-native-picker/picker": "2.6.1", @@ -111,6 +112,7 @@ "expo-image": "~1.10.3", "expo-image-manipulator": "^11.8.0", "expo-image-picker": "~14.7.1", + "expo-linking": "^6.2.2", "expo-localization": "~14.8.2", "expo-media-library": "~15.9.1", "expo-notifications": "~0.27.3", @@ -148,8 +150,10 @@ "react-avatar-editor": "^13.0.0", "react-circular-progressbar": "^2.1.0", "react-dom": "^18.2.0", + "react-keyed-flatten-children": "^3.0.0", "react-native": "0.73.2", "react-native-appstate-hook": "^1.0.6", + "react-native-date-picker": "^4.4.0", "react-native-drawer-layout": "^4.0.0-alpha.3", "react-native-fs": "^2.20.0", "react-native-gesture-handler": "~2.14.0", @@ -177,6 +181,8 @@ "react-responsive": "^9.0.2", "rn-fetch-blob": "^0.12.0", "sentry-expo": "~7.0.1", + "statsig-react": "^1.36.0", + "statsig-react-native-expo": "^4.6.1", "tippy.js": "^6.3.7", "tlds": "^1.234.0", "use-deep-compare": "^1.1.0", diff --git a/plugins/shareExtension/README.md b/plugins/shareExtension/README.md new file mode 100644 index 0000000000..2b57e624ae --- /dev/null +++ b/plugins/shareExtension/README.md @@ -0,0 +1,22 @@ +# Share extension plugin for Expo + +This plugin handles moving the necessary files into their respective iOS and Android targets and updating the build +phases, plists, manifests, etc. + +## Steps + +### ios + +1. Update entitlements +2. Set the app group to group. +3. Add the extension plist +4. Add the view controller +5. Update the xcode project's build phases + +### android + +1. Update the manifest with the intents the app can receive + +## Credits + +Adapted from https://github.com/andrew-levy/react-native-safari-extension and https://github.com/timedtext/expo-config-plugin-ios-share-extension/blob/master/src/withShareExtensionXcodeTarget.ts diff --git a/plugins/shareExtension/withAppEntitlements.js b/plugins/shareExtension/withAppEntitlements.js new file mode 100644 index 0000000000..4ce81ea611 --- /dev/null +++ b/plugins/shareExtension/withAppEntitlements.js @@ -0,0 +1,13 @@ +const {withEntitlementsPlist} = require('@expo/config-plugins') + +const withAppEntitlements = config => { + // eslint-disable-next-line no-shadow + return withEntitlementsPlist(config, async config => { + config.modResults['com.apple.security.application-groups'] = [ + `group.app.bsky`, + ] + return config + }) +} + +module.exports = {withAppEntitlements} diff --git a/plugins/shareExtension/withExtensionEntitlements.js b/plugins/shareExtension/withExtensionEntitlements.js new file mode 100644 index 0000000000..7bee79d1a6 --- /dev/null +++ b/plugins/shareExtension/withExtensionEntitlements.js @@ -0,0 +1,31 @@ +const {withInfoPlist} = require('@expo/config-plugins') +const plist = require('@expo/plist') +const path = require('path') +const fs = require('fs') + +const withExtensionEntitlements = (config, {extensionName}) => { + // eslint-disable-next-line no-shadow + return withInfoPlist(config, config => { + const extensionEntitlementsPath = path.join( + config.modRequest.platformProjectRoot, + extensionName, + `${extensionName}.entitlements`, + ) + + const shareExtensionEntitlements = { + 'com.apple.security.application-groups': [`group.app.bsky`], + } + + fs.mkdirSync(path.dirname(extensionEntitlementsPath), { + recursive: true, + }) + fs.writeFileSync( + extensionEntitlementsPath, + plist.default.build(shareExtensionEntitlements), + ) + + return config + }) +} + +module.exports = {withExtensionEntitlements} diff --git a/plugins/shareExtension/withExtensionInfoPlist.js b/plugins/shareExtension/withExtensionInfoPlist.js new file mode 100644 index 0000000000..9afc4d5f92 --- /dev/null +++ b/plugins/shareExtension/withExtensionInfoPlist.js @@ -0,0 +1,39 @@ +const {withInfoPlist} = require('@expo/config-plugins') +const plist = require('@expo/plist') +const path = require('path') +const fs = require('fs') + +const withExtensionInfoPlist = (config, {extensionName}) => { + // eslint-disable-next-line no-shadow + return withInfoPlist(config, config => { + const plistPath = path.join( + config.modRequest.projectRoot, + 'modules', + extensionName, + 'Info.plist', + ) + const targetPath = path.join( + config.modRequest.platformProjectRoot, + extensionName, + 'Info.plist', + ) + + const extPlist = plist.default.parse(fs.readFileSync(plistPath).toString()) + + extPlist.MainAppScheme = config.scheme + extPlist.CFBundleName = '$(PRODUCT_NAME)' + extPlist.CFBundleDisplayName = 'Extension' + extPlist.CFBundleIdentifier = '$(PRODUCT_BUNDLE_IDENTIFIER)' + extPlist.CFBundleVersion = '$(CURRENT_PROJECT_VERSION)' + extPlist.CFBundleExecutable = '$(EXECUTABLE_NAME)' + extPlist.CFBundlePackageType = '$(PRODUCT_BUNDLE_PACKAGE_TYPE)' + extPlist.CFBundleShortVersionString = '$(MARKETING_VERSION)' + + fs.mkdirSync(path.dirname(targetPath), {recursive: true}) + fs.writeFileSync(targetPath, plist.default.build(extPlist)) + + return config + }) +} + +module.exports = {withExtensionInfoPlist} diff --git a/plugins/shareExtension/withExtensionViewController.js b/plugins/shareExtension/withExtensionViewController.js new file mode 100644 index 0000000000..cd29bea7da --- /dev/null +++ b/plugins/shareExtension/withExtensionViewController.js @@ -0,0 +1,31 @@ +const {withXcodeProject} = require('@expo/config-plugins') +const path = require('path') +const fs = require('fs') + +const withExtensionViewController = ( + config, + {controllerName, extensionName}, +) => { + // eslint-disable-next-line no-shadow + return withXcodeProject(config, config => { + const controllerPath = path.join( + config.modRequest.projectRoot, + 'modules', + extensionName, + `${controllerName}.swift`, + ) + + const targetPath = path.join( + config.modRequest.platformProjectRoot, + extensionName, + `${controllerName}.swift`, + ) + + fs.mkdirSync(path.dirname(targetPath), {recursive: true}) + fs.copyFileSync(controllerPath, targetPath) + + return config + }) +} + +module.exports = {withExtensionViewController} diff --git a/plugins/shareExtension/withIntentFilters.js b/plugins/shareExtension/withIntentFilters.js new file mode 100644 index 0000000000..605fcfd052 --- /dev/null +++ b/plugins/shareExtension/withIntentFilters.js @@ -0,0 +1,89 @@ +const {withAndroidManifest} = require('@expo/config-plugins') + +const withIntentFilters = config => { + // eslint-disable-next-line no-shadow + return withAndroidManifest(config, config => { + const intents = [ + { + action: [ + { + $: { + 'android:name': 'android.intent.action.SEND', + }, + }, + ], + category: [ + { + $: { + 'android:name': 'android.intent.category.DEFAULT', + }, + }, + ], + data: [ + { + $: { + 'android:mimeType': 'image/*', + }, + }, + ], + }, + { + action: [ + { + $: { + 'android:name': 'android.intent.action.SEND', + }, + }, + ], + category: [ + { + $: { + 'android:name': 'android.intent.category.DEFAULT', + }, + }, + ], + data: [ + { + $: { + 'android:mimeType': 'text/plain', + }, + }, + ], + }, + { + action: [ + { + $: { + 'android:name': 'android.intent.action.SEND_MULTIPLE', + }, + }, + ], + category: [ + { + $: { + 'android:name': 'android.intent.category.DEFAULT', + }, + }, + ], + data: [ + { + $: { + 'android:mimeType': 'image/*', + }, + }, + ], + }, + ] + + const intentFilter = + config.modResults.manifest.application?.[0].activity?.[0]['intent-filter'] + + if (intentFilter) { + intentFilter.push(...intents) + } + + return config + }) +} + +module.exports = {withIntentFilters} diff --git a/plugins/shareExtension/withShareExtensions.js b/plugins/shareExtension/withShareExtensions.js new file mode 100644 index 0000000000..55a26c75eb --- /dev/null +++ b/plugins/shareExtension/withShareExtensions.js @@ -0,0 +1,47 @@ +const {withPlugins} = require('@expo/config-plugins') +const {withAppEntitlements} = require('./withAppEntitlements') +const {withXcodeTarget} = require('./withXcodeTarget') +const {withExtensionEntitlements} = require('./withExtensionEntitlements') +const {withExtensionInfoPlist} = require('./withExtensionInfoPlist') +const {withExtensionViewController} = require('./withExtensionViewController') +const {withIntentFilters} = require('./withIntentFilters') + +const SHARE_EXTENSION_NAME = 'Share-with-Bluesky' +const SHARE_EXTENSION_CONTROLLER_NAME = 'ShareViewController' + +const withShareExtensions = config => { + return withPlugins(config, [ + // IOS + withAppEntitlements, + [ + withExtensionEntitlements, + { + extensionName: SHARE_EXTENSION_NAME, + }, + ], + [ + withExtensionInfoPlist, + { + extensionName: SHARE_EXTENSION_NAME, + }, + ], + [ + withExtensionViewController, + { + extensionName: SHARE_EXTENSION_NAME, + controllerName: SHARE_EXTENSION_CONTROLLER_NAME, + }, + ], + [ + withXcodeTarget, + { + extensionName: SHARE_EXTENSION_NAME, + controllerName: SHARE_EXTENSION_CONTROLLER_NAME, + }, + ], + // Android + withIntentFilters, + ]) +} + +module.exports = withShareExtensions diff --git a/plugins/shareExtension/withXcodeTarget.js b/plugins/shareExtension/withXcodeTarget.js new file mode 100644 index 0000000000..ce70b392d4 --- /dev/null +++ b/plugins/shareExtension/withXcodeTarget.js @@ -0,0 +1,63 @@ +const {withXcodeProject} = require('@expo/config-plugins') + +const withXcodeTarget = (config, {extensionName, controllerName}) => { + // eslint-disable-next-line no-shadow + return withXcodeProject(config, config => { + const pbxProject = config.modResults + + const target = pbxProject.addTarget( + extensionName, + 'app_extension', + extensionName, + ) + pbxProject.addBuildPhase([], 'PBXSourcesBuildPhase', 'Sources', target.uuid) + pbxProject.addBuildPhase( + [], + 'PBXResourcesBuildPhase', + 'Resources', + target.uuid, + ) + const pbxGroupKey = pbxProject.pbxCreateGroup(extensionName, extensionName) + pbxProject.addFile(`${extensionName}/Info.plist`, pbxGroupKey) + pbxProject.addSourceFile( + `${extensionName}/${controllerName}.swift`, + {target: target.uuid}, + pbxGroupKey, + ) + + var configurations = pbxProject.pbxXCBuildConfigurationSection() + for (var key in configurations) { + if (typeof configurations[key].buildSettings !== 'undefined') { + var buildSettingsObj = configurations[key].buildSettings + if ( + typeof buildSettingsObj.PRODUCT_NAME !== 'undefined' && + buildSettingsObj.PRODUCT_NAME === `"${extensionName}"` + ) { + buildSettingsObj.CLANG_ENABLE_MODULES = 'YES' + buildSettingsObj.INFOPLIST_FILE = `"${extensionName}/Info.plist"` + buildSettingsObj.CODE_SIGN_ENTITLEMENTS = `"${extensionName}/${extensionName}.entitlements"` + buildSettingsObj.CODE_SIGN_STYLE = 'Automatic' + buildSettingsObj.CURRENT_PROJECT_VERSION = `"${config.ios?.buildNumber}"` + buildSettingsObj.GENERATE_INFOPLIST_FILE = 'YES' + buildSettingsObj.MARKETING_VERSION = `"${config.version}"` + buildSettingsObj.PRODUCT_BUNDLE_IDENTIFIER = `"${config.ios?.bundleIdentifier}.${extensionName}"` + buildSettingsObj.SWIFT_EMIT_LOC_STRINGS = 'YES' + buildSettingsObj.SWIFT_VERSION = '5.0' + buildSettingsObj.TARGETED_DEVICE_FAMILY = `"1,2"` + buildSettingsObj.DEVELOPMENT_TEAM = 'B3LX46C5HS' + } + } + } + + pbxProject.addTargetAttribute( + 'DevelopmentTeam', + 'B3LX46C5HS', + extensionName, + ) + pbxProject.addTargetAttribute('DevelopmentTeam', 'B3LX46C5HS') + + return config + }) +} + +module.exports = {withXcodeTarget} diff --git a/plugins/withAndroidManifestFCMIconPlugin.js b/plugins/withAndroidManifestFCMIconPlugin.js new file mode 100644 index 0000000000..066a975d87 --- /dev/null +++ b/plugins/withAndroidManifestFCMIconPlugin.js @@ -0,0 +1,37 @@ +const {withAndroidManifest} = require('expo/config-plugins') + +module.exports = function withAndroidManifestFCMIconPlugin(appConfig) { + return withAndroidManifest(appConfig, function (decoratedAppConfig) { + try { + function addOrModifyMetaData(metaData, name, resource) { + const elem = metaData.find(elem => elem.$['android:name'] === name) + if (elem === undefined) { + metaData.push({ + $: { + 'android:name': name, + 'android:resource': resource, + }, + }) + } else { + elem.$['android:resource'] = resource + } + } + const androidManifest = decoratedAppConfig.modResults.manifest + const metaData = androidManifest.application[0]['meta-data'] + addOrModifyMetaData( + metaData, + 'com.google.firebase.messaging.default_notification_color', + '@color/notification_icon_color', + ) + addOrModifyMetaData( + metaData, + 'com.google.firebase.messaging.default_notification_icon', + '@drawable/notification_icon', + ) + return decoratedAppConfig + } catch (e) { + console.error(`withAndroidManifestFCMIconPlugin failed`, e) + } + return decoratedAppConfig + }) +} diff --git a/plugins/withAndroidStylesWindowBackgroundPlugin.js b/plugins/withAndroidStylesWindowBackgroundPlugin.js new file mode 100644 index 0000000000..427f43df07 --- /dev/null +++ b/plugins/withAndroidStylesWindowBackgroundPlugin.js @@ -0,0 +1,20 @@ +const {withAndroidStyles, AndroidConfig} = require('@expo/config-plugins') + +module.exports = function withAndroidStylesWindowBackgroundPlugin(appConfig) { + return withAndroidStyles(appConfig, function (decoratedAppConfig) { + try { + decoratedAppConfig.modResults = AndroidConfig.Styles.assignStylesValue( + decoratedAppConfig.modResults, + { + add: true, + parent: AndroidConfig.Styles.getAppThemeLightNoActionBarGroup(), + name: 'android:windowBackground', + value: '@drawable/splashscreen', + }, + ) + } catch (e) { + console.error(`withAndroidStylesWindowBackgroundPlugin failed`, e) + } + return decoratedAppConfig + }) +} diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 0000000000..99d6236f90 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,5 @@ +# Tool Scripts + +## updateExtensions.sh + +Updates the extensions in `/modules` with the current iOS/Android project changes. diff --git a/scripts/updateExtensions.sh b/scripts/updateExtensions.sh new file mode 100755 index 0000000000..f4e462b744 --- /dev/null +++ b/scripts/updateExtensions.sh @@ -0,0 +1,10 @@ +#!/bin/bash +IOS_SHARE_EXTENSION_DIRECTORY="./ios/Share-with-Bluesky" +MODULES_DIRECTORY="./modules" + +if [ ! -d $IOS_SHARE_EXTENSION_DIRECTORY ]; then + echo "$IOS_SHARE_EXTENSION_DIRECTORY not found inside of your iOS project." + exit 1 +else + cp -R $IOS_SHARE_EXTENSION_DIRECTORY $MODULES_DIRECTORY +fi diff --git a/src/App.native.tsx b/src/App.native.tsx index c79088cebd..44b2cba156 100644 --- a/src/App.native.tsx +++ b/src/App.native.tsx @@ -47,8 +47,12 @@ import {Provider as UnreadNotifsProvider} from 'state/queries/notifications/unre import * as persisted from '#/state/persisted' import {Splash} from '#/Splash' import {Provider as PortalProvider} from '#/components/Portal' +import {Provider as StatsigProvider} from '#/lib/statsig/statsig' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' +import {useIntentHandler} from 'lib/hooks/useIntentHandler' +import {StatusBar} from 'expo-status-bar' +import {isAndroid} from 'platform/detection' SplashScreen.preventAutoHideAsync() @@ -57,6 +61,7 @@ function InnerApp() { const {resumeSession} = useSessionApi() const theme = useColorModeTheme() const {_} = useLingui() + useIntentHandler() // init useEffect(() => { @@ -71,26 +76,29 @@ function InnerApp() { return ( + {isAndroid && } - - - - - {/* All components should be within this provider */} - - - - - - - - - - + + + + + + {/* All components should be within this provider */} + + + + + + + + + + + diff --git a/src/App.web.tsx b/src/App.web.tsx index e2f1f07ff4..b0d5f12662 100644 --- a/src/App.web.tsx +++ b/src/App.web.tsx @@ -36,11 +36,14 @@ import { import {Provider as UnreadNotifsProvider} from 'state/queries/notifications/unread' import * as persisted from '#/state/persisted' import {Provider as PortalProvider} from '#/components/Portal' +import {Provider as StatsigProvider} from '#/lib/statsig/statsig' +import {useIntentHandler} from 'lib/hooks/useIntentHandler' function InnerApp() { const {isInitialLoad, currentAccount} = useSession() const {resumeSession} = useSessionApi() const theme = useColorModeTheme() + useIntentHandler() // init useEffect(() => { @@ -56,21 +59,23 @@ function InnerApp() { - - - - - {/* All components should be within this provider */} - - - - - - - - - - + + + + + + {/* All components should be within this provider */} + + + + + + + + + + + ) diff --git a/src/Navigation.tsx b/src/Navigation.tsx index 728930a81b..b535b7a9aa 100644 --- a/src/Navigation.tsx +++ b/src/Navigation.tsx @@ -78,6 +78,8 @@ import {PreferencesExternalEmbeds} from '#/view/screens/PreferencesExternalEmbed import {createNativeStackNavigatorWithAuth} from './view/shell/createNativeStackNavigatorWithAuth' import {msg} from '@lingui/macro' import {i18n, MessageDescriptor} from '@lingui/core' +import HashtagScreen from '#/screens/Hashtag' +import {logEvent} from './lib/statsig/statsig' const navigationRef = createNavigationContainerRef() @@ -268,6 +270,11 @@ function commonScreens(Stack: typeof HomeTab, unreadCountLabel?: string) { requireAuth: true, }} /> + HashtagScreen} + options={{title: title(msg`Hashtag`)}} + /> ) } @@ -466,7 +473,8 @@ const FlatNavigator = () => { */ const LINKING = { - prefixes: ['bsky://', 'https://bsky.app'], + // TODO figure out what we are going to use + prefixes: ['bsky://', 'bluesky://', 'https://bsky.app'], getPathFromState(state: State) { // find the current node in the navigation tree @@ -485,6 +493,18 @@ const LINKING = { getStateFromPath(path: string) { const [name, params] = router.matchPath(path) + + // Any time we receive a url that starts with `intent/` we want to ignore it here. It will be handled in the + // intent handler hook. We should check for the trailing slash, because if there isn't one then it isn't a valid + // intent + // On web, there is no route state that's created by default, so we should initialize it as the home route. On + // native, since the home tab and the home screen are defined as initial routes, we don't need to return a state + // since it will be created by react-navigation. + if (path.includes('intent/')) { + if (isNative) return + return buildStateObject('Flat', 'Home', params) + } + if (isNative) { if (name === 'Search') { return buildStateObject('SearchTab', 'Search', params) @@ -503,7 +523,8 @@ const LINKING = { }, ]) } else { - return buildStateObject('Flat', name, params) + const res = buildStateObject('Flat', name, params) + return res } }, } @@ -635,11 +656,14 @@ function logModuleInitTime() { return } didInit = true + const initMs = Math.round( // @ts-ignore Emitted by Metro in the bundle prelude performance.now() - global.__BUNDLE_START_TIME__, ) console.log(`Time to first paint: ${initMs} ms`) + logEvent('init', initMs) + if (__DEV__) { // This log is noisy, so keep false committed const shouldLog = false diff --git a/src/Splash.tsx b/src/Splash.tsx index b2381f9232..42a21c0839 100644 --- a/src/Splash.tsx +++ b/src/Splash.tsx @@ -181,6 +181,8 @@ export function Splash(props: React.PropsWithChildren) { const logoAnimations = reduceMotion === true ? reducedLogoAnimation : logoAnimation + // special off-spec color for dark mode + const logoBg = isDarkMode ? '#0F1824' : '#fff' return ( @@ -232,7 +234,7 @@ export function Splash(props: React.PropsWithChildren) { }, ]}> @@ -253,7 +255,7 @@ export function Splash(props: React.PropsWithChildren) { transform: [{translateY: -(insets.top / 2)}, {scale: 0.1}], // scale from 1000px to 100px }, ]}> - + }> {!isAnimationComplete && ( @@ -261,10 +263,7 @@ export function Splash(props: React.PropsWithChildren) { style={[ StyleSheet.absoluteFillObject, { - backgroundColor: isDarkMode - ? // special off-spec color for dark mode - '#0F1824' - : '#fff', + backgroundColor: logoBg, }, ]} /> diff --git a/src/alf/atoms.ts b/src/alf/atoms.ts index b849010039..8a79a90294 100644 --- a/src/alf/atoms.ts +++ b/src/alf/atoms.ts @@ -1,3 +1,4 @@ +import {web, native} from '#/alf/util/platform' import * as tokens from '#/alf/tokens' export const atoms = { @@ -113,6 +114,9 @@ export const atoms = { flex_wrap: { flexWrap: 'wrap', }, + flex_0: { + flex: web('0 0 auto') || (native(0) as number), + }, flex_1: { flex: 1, }, diff --git a/src/alf/index.tsx b/src/alf/index.tsx index 06d6ebf01c..27738e91de 100644 --- a/src/alf/index.tsx +++ b/src/alf/index.tsx @@ -17,7 +17,7 @@ const breakpoints: { [key: string]: number } = { gtMobile: 800, - gtTablet: 1200, + gtTablet: 1300, } function getActiveBreakpoints({width}: {width: number}) { const active: (keyof typeof breakpoints)[] = Object.keys(breakpoints).filter( diff --git a/src/alf/themes.ts b/src/alf/themes.ts index da96f6eff6..0c95a459ed 100644 --- a/src/alf/themes.ts +++ b/src/alf/themes.ts @@ -1,6 +1,7 @@ import * as tokens from '#/alf/tokens' import type {Mutable} from '#/alf/types' import {atoms} from '#/alf/atoms' +import {BLUE_HUE, GREEN_HUE, RED_HUE} from '#/alf/util/colorGeneration' export type ThemeName = 'light' | 'dim' | 'dark' export type ReadonlyTheme = typeof light @@ -73,19 +74,19 @@ export const darkPalette: Palette = { white: tokens.color.gray_0, black: tokens.color.trueBlack, - contrast_25: `hsl(211, 28%, 8%)`, - contrast_50: `hsl(211, 28%, 11%)`, - contrast_100: `hsl(211, 28%, 16%)`, - contrast_200: `hsl(211, 28%, 24%)`, - contrast_300: `hsl(211, 24%, 31%)`, - contrast_400: `hsl(211, 24%, 38%)`, - contrast_500: `hsl(211, 20%, 44%)`, - contrast_600: `hsl(211, 20%, 55%)`, - contrast_700: `hsl(211, 20%, 63%)`, - contrast_800: `hsl(211, 20%, 71%)`, - contrast_900: `hsl(211, 20%, 79%)`, - contrast_950: `hsl(211, 20%, 87%)`, - contrast_975: `hsl(211, 20%, 95%)`, + contrast_25: tokens.color.gray_1000, + contrast_50: tokens.color.gray_975, + contrast_100: tokens.color.gray_950, + contrast_200: tokens.color.gray_900, + contrast_300: tokens.color.gray_800, + contrast_400: tokens.color.gray_700, + contrast_500: tokens.color.gray_600, + contrast_600: tokens.color.gray_500, + contrast_700: tokens.color.gray_400, + contrast_800: tokens.color.gray_300, + contrast_900: tokens.color.gray_200, + contrast_950: tokens.color.gray_100, + contrast_975: tokens.color.gray_50, primary_25: tokens.color.blue_25, primary_50: tokens.color.blue_50, @@ -132,28 +133,63 @@ export const darkPalette: Palette = { export const dimPalette: Palette = { ...darkPalette, - black: `hsl(211, 28%, 12%)`, + black: `hsl(${BLUE_HUE}, 28%, ${tokens.dimScale[0]}%)`, - contrast_25: `hsl(211, 28%, 15%)`, - contrast_50: `hsl(211, 28%, 18%)`, - contrast_100: `hsl(211, 28%, 24%)`, - contrast_200: `hsl(211, 28%, 27%)`, - contrast_300: `hsl(211, 24%, 34%)`, - contrast_400: `hsl(211, 24%, 41%)`, - contrast_500: `hsl(211, 20%, 52%)`, - contrast_600: `hsl(211, 20%, 55%)`, - contrast_700: `hsl(211, 20%, 67%)`, - contrast_800: `hsl(211, 20%, 71%)`, - contrast_900: `hsl(211, 20%, 79%)`, - contrast_950: `hsl(211, 20%, 87%)`, - contrast_975: `hsl(211, 20%, 95%)`, + contrast_25: `hsl(${BLUE_HUE}, 28%, ${tokens.dimScale[1]}%)`, + contrast_50: `hsl(${BLUE_HUE}, 28%, ${tokens.dimScale[2]}%)`, + contrast_100: `hsl(${BLUE_HUE}, 28%, ${tokens.dimScale[3]}%)`, + contrast_200: `hsl(${BLUE_HUE}, 28%, ${tokens.dimScale[4]}%)`, + contrast_300: `hsl(${BLUE_HUE}, 24%, ${tokens.dimScale[5]}%)`, + contrast_400: `hsl(${BLUE_HUE}, 24%, ${tokens.dimScale[6]}%)`, + contrast_500: `hsl(${BLUE_HUE}, 20%, ${tokens.dimScale[7]}%)`, + contrast_600: `hsl(${BLUE_HUE}, 20%, ${tokens.dimScale[8]}%)`, + contrast_700: `hsl(${BLUE_HUE}, 20%, ${tokens.dimScale[9]}%)`, + contrast_800: `hsl(${BLUE_HUE}, 20%, ${tokens.dimScale[10]}%)`, + contrast_900: `hsl(${BLUE_HUE}, 20%, ${tokens.dimScale[11]}%)`, + contrast_950: `hsl(${BLUE_HUE}, 20%, ${tokens.dimScale[12]}%)`, + contrast_975: `hsl(${BLUE_HUE}, 20%, ${tokens.dimScale[13]}%)`, - primary_600: `hsl(211, 95%, 39%)`, - primary_700: `hsl(211, 90%, 30%)`, - primary_800: `hsl(211, 90%, 23%)`, - primary_900: `hsl(211, 80%, 16%)`, - primary_950: `hsl(211, 80%, 13%)`, - primary_975: `hsl(211, 80%, 10%)`, + primary_25: `hsl(${BLUE_HUE}, 99%, ${tokens.dimScale[13]}%)`, + primary_50: `hsl(${BLUE_HUE}, 99%, ${tokens.dimScale[12]}%)`, + primary_100: `hsl(${BLUE_HUE}, 99%, ${tokens.dimScale[11]}%)`, + primary_200: `hsl(${BLUE_HUE}, 99%, ${tokens.dimScale[10]}%)`, + primary_300: `hsl(${BLUE_HUE}, 99%, ${tokens.dimScale[9]}%)`, + primary_400: `hsl(${BLUE_HUE}, 99%, ${tokens.dimScale[8]}%)`, + primary_500: `hsl(${BLUE_HUE}, 99%, ${tokens.dimScale[7]}%)`, + primary_600: `hsl(${BLUE_HUE}, 95%, ${tokens.dimScale[6]}%)`, + primary_700: `hsl(${BLUE_HUE}, 90%, ${tokens.dimScale[5]}%)`, + primary_800: `hsl(${BLUE_HUE}, 82%, ${tokens.dimScale[4]}%)`, + primary_900: `hsl(${BLUE_HUE}, 70%, ${tokens.dimScale[3]}%)`, + primary_950: `hsl(${BLUE_HUE}, 60%, ${tokens.dimScale[2]}%)`, + primary_975: `hsl(${BLUE_HUE}, 50%, ${tokens.dimScale[1]}%)`, + + positive_25: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[13]}%)`, + positive_50: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[12]}%)`, + positive_100: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[11]}%)`, + positive_200: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[10]}%)`, + positive_300: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[9]}%)`, + positive_400: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[8]}%)`, + positive_500: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[7]}%)`, + positive_600: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[6]}%)`, + positive_700: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[5]}%)`, + positive_800: `hsl(${GREEN_HUE}, 82%, ${tokens.dimScale[4]}%)`, + positive_900: `hsl(${GREEN_HUE}, 70%, ${tokens.dimScale[3]}%)`, + positive_950: `hsl(${GREEN_HUE}, 60%, ${tokens.dimScale[2]}%)`, + positive_975: `hsl(${GREEN_HUE}, 50%, ${tokens.dimScale[1]}%)`, + + negative_25: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[13]}%)`, + negative_50: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[12]}%)`, + negative_100: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[11]}%)`, + negative_200: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[10]}%)`, + negative_300: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[9]}%)`, + negative_400: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[8]}%)`, + negative_500: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[7]}%)`, + negative_600: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[6]}%)`, + negative_700: `hsl(${RED_HUE}, 91%, ${tokens.dimScale[5]}%)`, + negative_800: `hsl(${RED_HUE}, 88%, ${tokens.dimScale[4]}%)`, + negative_900: `hsl(${RED_HUE}, 84%, ${tokens.dimScale[3]}%)`, + negative_950: `hsl(${RED_HUE}, 80%, ${tokens.dimScale[2]}%)`, + negative_975: `hsl(${RED_HUE}, 70%, ${tokens.dimScale[1]}%)`, } as const export const light = { @@ -404,17 +440,17 @@ export const dim: Theme = { shadow_sm: { ...atoms.shadow_sm, shadowOpacity: 0.7, - shadowColor: `hsl(211, 28%, 3%)`, + shadowColor: `hsl(${BLUE_HUE}, 28%, 6%)`, }, shadow_md: { ...atoms.shadow_md, shadowOpacity: 0.7, - shadowColor: `hsl(211, 28%, 3%)`, + shadowColor: `hsl(${BLUE_HUE}, 28%, 6%)`, }, shadow_lg: { ...atoms.shadow_lg, shadowOpacity: 0.7, - shadowColor: `hsl(211, 28%, 3%)`, + shadowColor: `hsl(${BLUE_HUE}, 28%, 6%)`, }, }, } diff --git a/src/alf/tokens.ts b/src/alf/tokens.ts index f0b8c7c692..b1468f461d 100644 --- a/src/alf/tokens.ts +++ b/src/alf/tokens.ts @@ -1,25 +1,32 @@ -const BLUE_HUE = 211 -const RED_HUE = 346 -const GREEN_HUE = 152 +import { + BLUE_HUE, + RED_HUE, + GREEN_HUE, + generateScale, +} from '#/alf/util/colorGeneration' + +export const scale = generateScale(6, 100) +// dim shifted 6% lighter +export const dimScale = generateScale(12, 100) export const color = { trueBlack: '#000000', - gray_0: `hsl(${BLUE_HUE}, 20%, 100%)`, - gray_25: `hsl(${BLUE_HUE}, 20%, 97%)`, - gray_50: `hsl(${BLUE_HUE}, 20%, 95%)`, - gray_100: `hsl(${BLUE_HUE}, 20%, 90%)`, - gray_200: `hsl(${BLUE_HUE}, 20%, 80%)`, - gray_300: `hsl(${BLUE_HUE}, 20%, 70%)`, - gray_400: `hsl(${BLUE_HUE}, 20%, 60%)`, - gray_500: `hsl(${BLUE_HUE}, 20%, 50%)`, - gray_600: `hsl(${BLUE_HUE}, 24%, 42%)`, - gray_700: `hsl(${BLUE_HUE}, 24%, 34%)`, - gray_800: `hsl(${BLUE_HUE}, 28%, 26%)`, - gray_900: `hsl(${BLUE_HUE}, 28%, 18%)`, - gray_950: `hsl(${BLUE_HUE}, 28%, 10%)`, - gray_975: `hsl(${BLUE_HUE}, 28%, 7%)`, - gray_1000: `hsl(${BLUE_HUE}, 28%, 4%)`, + gray_0: `hsl(${BLUE_HUE}, 20%, ${scale[14]}%)`, + gray_25: `hsl(${BLUE_HUE}, 20%, ${scale[13]}%)`, + gray_50: `hsl(${BLUE_HUE}, 20%, ${scale[12]}%)`, + gray_100: `hsl(${BLUE_HUE}, 20%, ${scale[11]}%)`, + gray_200: `hsl(${BLUE_HUE}, 20%, ${scale[10]}%)`, + gray_300: `hsl(${BLUE_HUE}, 20%, ${scale[9]}%)`, + gray_400: `hsl(${BLUE_HUE}, 20%, ${scale[8]}%)`, + gray_500: `hsl(${BLUE_HUE}, 20%, ${scale[7]}%)`, + gray_600: `hsl(${BLUE_HUE}, 24%, ${scale[6]}%)`, + gray_700: `hsl(${BLUE_HUE}, 24%, ${scale[5]}%)`, + gray_800: `hsl(${BLUE_HUE}, 28%, ${scale[4]}%)`, + gray_900: `hsl(${BLUE_HUE}, 28%, ${scale[3]}%)`, + gray_950: `hsl(${BLUE_HUE}, 28%, ${scale[2]}%)`, + gray_975: `hsl(${BLUE_HUE}, 28%, ${scale[1]}%)`, + gray_1000: `hsl(${BLUE_HUE}, 28%, ${scale[0]}%)`, blue_25: `hsl(${BLUE_HUE}, 99%, 97%)`, blue_50: `hsl(${BLUE_HUE}, 99%, 95%)`, diff --git a/src/alf/util/colorGeneration.ts b/src/alf/util/colorGeneration.ts new file mode 100644 index 0000000000..929a01d3a7 --- /dev/null +++ b/src/alf/util/colorGeneration.ts @@ -0,0 +1,17 @@ +export const BLUE_HUE = 211 +export const RED_HUE = 346 +export const GREEN_HUE = 152 + +/** + * Smooth progression of lightness "stops" for generating HSL colors. + */ +export const COLOR_STOPS = [ + 0, 0.05, 0.1, 0.15, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.85, 0.9, 0.95, 1, +] + +export function generateScale(start: number, end: number) { + const range = end - start + return COLOR_STOPS.map(stop => { + return start + range * stop + }) +} diff --git a/src/alf/util/platform.ts b/src/alf/util/platform.ts index 544f5480b6..294e08a8b0 100644 --- a/src/alf/util/platform.ts +++ b/src/alf/util/platform.ts @@ -1,25 +1,25 @@ -import {Platform} from 'react-native' +import {isAndroid, isIOS, isNative, isWeb} from 'platform/detection' export function web(value: any) { - return Platform.select({ - web: value, - }) + if (isWeb) { + return value + } } export function ios(value: any) { - return Platform.select({ - ios: value, - }) + if (isIOS) { + return value + } } export function android(value: any) { - return Platform.select({ - android: value, - }) + if (isAndroid) { + return value + } } export function native(value: any) { - return Platform.select({ - native: value, - }) + if (isNative) { + return value + } } diff --git a/src/components/Button.tsx b/src/components/Button.tsx index 4addd28a3b..2d65b56834 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -165,7 +165,7 @@ export function Button({ if (!disabled) { baseStyles.push(a.border, { - borderColor: tokens.color.blue_500, + borderColor: t.palette.primary_500, }) hoverStyles.push(a.border, { backgroundColor: light @@ -174,7 +174,7 @@ export function Button({ }) } else { baseStyles.push(a.border, { - borderColor: light ? tokens.color.blue_200 : tokens.color.blue_900, + borderColor: light ? t.palette.primary_200 : t.palette.primary_900, }) } } else if (variant === 'ghost') { @@ -191,20 +191,14 @@ export function Button({ if (variant === 'solid') { if (!disabled) { baseStyles.push({ - backgroundColor: light - ? tokens.color.gray_50 - : tokens.color.gray_900, + backgroundColor: t.palette.contrast_50, }) hoverStyles.push({ - backgroundColor: light - ? tokens.color.gray_100 - : tokens.color.gray_950, + backgroundColor: t.palette.contrast_100, }) } else { baseStyles.push({ - backgroundColor: light - ? tokens.color.gray_200 - : tokens.color.gray_950, + backgroundColor: t.palette.contrast_200, }) } } else if (variant === 'outline') { @@ -214,21 +208,19 @@ export function Button({ if (!disabled) { baseStyles.push(a.border, { - borderColor: light ? tokens.color.gray_300 : tokens.color.gray_700, + borderColor: t.palette.contrast_300, }) - hoverStyles.push(a.border, t.atoms.bg_contrast_50) + hoverStyles.push(t.atoms.bg_contrast_50) } else { baseStyles.push(a.border, { - borderColor: light ? tokens.color.gray_200 : tokens.color.gray_800, + borderColor: t.palette.contrast_200, }) } } else if (variant === 'ghost') { if (!disabled) { baseStyles.push(t.atoms.bg) hoverStyles.push({ - backgroundColor: light - ? tokens.color.gray_100 - : tokens.color.gray_900, + backgroundColor: t.palette.contrast_100, }) } } @@ -236,14 +228,14 @@ export function Button({ if (variant === 'solid') { if (!disabled) { baseStyles.push({ - backgroundColor: t.palette.negative_400, + backgroundColor: t.palette.negative_500, }) hoverStyles.push({ - backgroundColor: t.palette.negative_500, + backgroundColor: t.palette.negative_600, }) } else { baseStyles.push({ - backgroundColor: t.palette.negative_600, + backgroundColor: t.palette.negative_700, }) } } else if (variant === 'outline') { @@ -253,7 +245,7 @@ export function Button({ if (!disabled) { baseStyles.push(a.border, { - borderColor: t.palette.negative_400, + borderColor: t.palette.negative_500, }) hoverStyles.push(a.border, { backgroundColor: light @@ -273,7 +265,7 @@ export function Button({ hoverStyles.push({ backgroundColor: light ? t.palette.negative_100 - : t.palette.negative_950, + : t.palette.negative_975, }) } } @@ -460,31 +452,31 @@ export function useSharedButtonTextStyles() { if (variant === 'solid' || variant === 'gradient') { if (!disabled) { baseStyles.push({ - color: light ? tokens.color.gray_700 : tokens.color.gray_100, + color: t.palette.contrast_700, }) } else { baseStyles.push({ - color: light ? tokens.color.gray_400 : tokens.color.gray_700, + color: t.palette.contrast_400, }) } } else if (variant === 'outline') { if (!disabled) { baseStyles.push({ - color: light ? tokens.color.gray_600 : tokens.color.gray_300, + color: t.palette.contrast_600, }) } else { baseStyles.push({ - color: light ? tokens.color.gray_400 : tokens.color.gray_700, + color: t.palette.contrast_300, }) } } else if (variant === 'ghost') { if (!disabled) { baseStyles.push({ - color: light ? tokens.color.gray_600 : tokens.color.gray_300, + color: t.palette.contrast_600, }) } else { baseStyles.push({ - color: light ? tokens.color.gray_400 : tokens.color.gray_600, + color: t.palette.contrast_300, }) } } diff --git a/src/components/Dialog/context.ts b/src/components/Dialog/context.ts index f0c7c983a9..9b571e8e9c 100644 --- a/src/components/Dialog/context.ts +++ b/src/components/Dialog/context.ts @@ -3,7 +3,7 @@ import React from 'react' import {useDialogStateContext} from '#/state/dialogs' import { DialogContextProps, - DialogControlProps, + DialogControlRefProps, DialogOuterProps, } from '#/components/Dialog/types' @@ -17,11 +17,12 @@ export function useDialogContext() { export function useDialogControl(): DialogOuterProps['control'] { const id = React.useId() - const control = React.useRef({ + const control = React.useRef({ open: () => {}, close: () => {}, }) - const {activeDialogs} = useDialogStateContext() + const {activeDialogs, openDialogs} = useDialogStateContext() + const isOpen = openDialogs.includes(id) React.useEffect(() => { activeDialogs.current.set(id, control) @@ -31,9 +32,18 @@ export function useDialogControl(): DialogOuterProps['control'] { } }, [id, activeDialogs]) - return { - ref: control, - open: () => control.current.open(), - close: cb => control.current.close(cb), - } + return React.useMemo( + () => ({ + id, + ref: control, + isOpen, + open: () => { + control.current.open() + }, + close: cb => { + control.current.close(cb) + }, + }), + [id, control, isOpen], + ) } diff --git a/src/components/Dialog/index.tsx b/src/components/Dialog/index.tsx index 97c3340d3f..5d926f59f4 100644 --- a/src/components/Dialog/index.tsx +++ b/src/components/Dialog/index.tsx @@ -1,17 +1,22 @@ import React, {useImperativeHandle} from 'react' -import {View, Dimensions} from 'react-native' +import {View, Dimensions, Keyboard, Pressable} from 'react-native' import BottomSheet, { - BottomSheetBackdrop, BottomSheetFlatList, + BottomSheetBackdropProps, BottomSheetScrollView, BottomSheetTextInput, BottomSheetView, + useBottomSheet, + WINDOW_HEIGHT, } from '@gorhom/bottom-sheet' import {useSafeAreaInsets} from 'react-native-safe-area-context' +import Animated, {useAnimatedStyle} from 'react-native-reanimated' import {useTheme, atoms as a, flatten} from '#/alf' import {Portal} from '#/components/Portal' import {createInput} from '#/components/forms/TextField' +import {logger} from '#/logger' +import {useDialogStateControlContext} from '#/state/dialogs' import { DialogOuterProps, @@ -26,6 +31,47 @@ export * from '#/components/Dialog/types' export const Input = createInput(BottomSheetTextInput) export const FlatList = BottomSheetFlatList +function Backdrop(props: BottomSheetBackdropProps) { + const t = useTheme() + const bottomSheet = useBottomSheet() + + const animatedStyle = useAnimatedStyle(() => { + const opacity = + (Math.abs(WINDOW_HEIGHT - props.animatedPosition.value) - 50) / 1000 + + return { + opacity: Math.min(Math.max(opacity, 0), 0.55), + } + }) + + const onPress = React.useCallback(() => { + bottomSheet.close() + }, [bottomSheet]) + + return ( + + + + ) +} + export function Outer({ children, control, @@ -38,6 +84,7 @@ export function Outer({ const hasSnapPoints = !!sheetOptions.snapPoints const insets = useSafeAreaInsets() const closeCallback = React.useRef<() => void>() + const {setDialogIsOpen} = useDialogStateControlContext() /* * Used to manage open/closed, but index is otherwise handled internally by `BottomSheet` @@ -51,14 +98,15 @@ export function Outer({ const open = React.useCallback( ({index} = {}) => { + setDialogIsOpen(control.id, true) // can be set to any index of `snapPoints`, but `0` is the first i.e. "open" setOpenIndex(index || 0) }, - [setOpenIndex], + [setOpenIndex, setDialogIsOpen, control.id], ) const close = React.useCallback(cb => { - if (cb) { + if (cb && typeof cb === 'function') { closeCallback.current = cb } sheet.current?.close() @@ -73,63 +121,66 @@ export function Outer({ [open, close], ) - const onChange = React.useCallback( - (index: number) => { - if (index === -1) { - closeCallback.current?.() - closeCallback.current = undefined - onClose?.() - setOpenIndex(-1) - } - }, - [onClose, setOpenIndex], - ) + const onCloseInner = React.useCallback(() => { + Keyboard.dismiss() + try { + closeCallback.current?.() + } catch (e: any) { + logger.error(`Dialog closeCallback failed`, { + message: e.message, + }) + } finally { + closeCallback.current = undefined + } + setDialogIsOpen(control.id, false) + onClose?.() + setOpenIndex(-1) + }, [control.id, onClose, setDialogIsOpen]) const context = React.useMemo(() => ({close}), [close]) return ( isOpen && ( - ( - - )} - handleIndicatorStyle={{backgroundColor: t.palette.primary_500}} - handleStyle={{display: 'none'}} - onChange={onChange}> - - - {children} - - + + + + + {children} + + + ) ) @@ -179,8 +230,15 @@ export function ScrollableInner({children, style}: DialogInnerProps) { export function Handle() { const t = useTheme() + + const onTouchStart = React.useCallback(() => { + Keyboard.dismiss() + }, []) + return ( - + { setIsOpen(true) - }, [setIsOpen]) + setDialogIsOpen(control.id, true) + }, [setIsOpen, setDialogIsOpen, control.id]) const close = React.useCallback(async () => { setIsVisible(false) await new Promise(resolve => setTimeout(resolve, 150)) setIsOpen(false) setIsVisible(true) + setDialogIsOpen(control.id, false) onClose?.() - }, [onClose, setIsOpen]) + }, [onClose, setIsOpen, setDialogIsOpen, control.id]) useImperativeHandle( control.ref, @@ -189,9 +193,9 @@ export function Close() { diff --git a/src/components/Dialog/types.ts b/src/components/Dialog/types.ts index 75ba825ac9..fa9398fe05 100644 --- a/src/components/Dialog/types.ts +++ b/src/components/Dialog/types.ts @@ -6,8 +6,27 @@ import {ViewStyleProp} from '#/alf' type A11yProps = Required +/** + * Mutated by useImperativeHandle to provide a public API for controlling the + * dialog. The methods here will actually become the handlers defined within + * the `Dialog.Outer` component. + */ +export type DialogControlRefProps = { + open: (options?: DialogControlOpenOptions) => void + close: (callback?: () => void) => void +} + +/** + * The return type of the useDialogControl hook. + */ +export type DialogControlProps = DialogControlRefProps & { + id: string + ref: React.RefObject + isOpen: boolean +} + export type DialogContextProps = { - close: () => void + close: DialogControlProps['close'] } export type DialogControlOpenOptions = { @@ -20,15 +39,8 @@ export type DialogControlOpenOptions = { index?: number } -export type DialogControlProps = { - open: (options?: DialogControlOpenOptions) => void - close: (callback?: () => void) => void -} - export type DialogOuterProps = { - control: { - ref: React.RefObject - } & DialogControlProps + control: DialogControlProps onClose?: () => void nativeOptions?: { sheet?: Omit diff --git a/src/components/Link.tsx b/src/components/Link.tsx index 0a654fed28..8c963909be 100644 --- a/src/components/Link.tsx +++ b/src/components/Link.tsx @@ -49,7 +49,7 @@ type BaseLinkProps = Pick< * * Note: atm this only works for `InlineLink`s with a string child. */ - warnOnMismatchingTextChild?: boolean + disableMismatchWarning?: boolean /** * Callback for when the link is pressed. Prevent default and return `false` @@ -69,7 +69,7 @@ export function useLink({ to, displayText, action = 'push', - warnOnMismatchingTextChild, + disableMismatchWarning, onPress: outerOnPress, }: BaseLinkProps & { displayText: string @@ -90,7 +90,7 @@ export function useLink({ if (exitEarlyIfFalse === false) return const requiresWarning = Boolean( - warnOnMismatchingTextChild && + !disableMismatchWarning && displayText && isExternal && linkRequiresWarning(href, displayText), @@ -148,7 +148,7 @@ export function useLink({ }, [ outerOnPress, - warnOnMismatchingTextChild, + disableMismatchWarning, displayText, isExternal, href, @@ -167,7 +167,7 @@ export function useLink({ } } -export type LinkProps = Omit & +export type LinkProps = Omit & Omit /** @@ -226,7 +226,7 @@ export function InlineLink({ children, to, action = 'push', - warnOnMismatchingTextChild, + disableMismatchWarning, style, onPress: outerOnPress, download, @@ -239,7 +239,7 @@ export function InlineLink({ to, displayText: stringChildren ? children : '', action, - warnOnMismatchingTextChild, + disableMismatchWarning, onPress: outerOnPress, }) const { diff --git a/src/components/Lists.tsx b/src/components/Lists.tsx new file mode 100644 index 0000000000..58aa74b388 --- /dev/null +++ b/src/components/Lists.tsx @@ -0,0 +1,249 @@ +import React from 'react' +import {atoms as a, useBreakpoints, useTheme} from '#/alf' +import {View} from 'react-native' +import {CenteredView} from 'view/com/util/Views' +import {Loader} from '#/components/Loader' +import {Trans} from '@lingui/macro' +import {cleanError} from 'lib/strings/errors' +import {Button} from '#/components/Button' +import {Text} from '#/components/Typography' +import {StackActions} from '@react-navigation/native' +import {useNavigation} from '@react-navigation/core' +import {NavigationProp} from 'lib/routes/types' +import {router} from '#/routes' + +export function ListFooter({ + isFetching, + isError, + error, + onRetry, +}: { + isFetching: boolean + isError: boolean + error?: string + onRetry?: () => Promise +}) { + const t = useTheme() + + return ( + + {isFetching ? ( + + ) : ( + + )} + + ) +} + +function ListFooterMaybeError({ + isError, + error, + onRetry, +}: { + isError: boolean + error?: string + onRetry?: () => Promise +}) { + const t = useTheme() + + if (!isError) return null + + return ( + + + + {error ? ( + cleanError(error) + ) : ( + Oops, something went wrong! + )} + + + + + ) +} + +export function ListHeaderDesktop({ + title, + subtitle, +}: { + title: string + subtitle?: string +}) { + const {gtTablet} = useBreakpoints() + const t = useTheme() + + if (!gtTablet) return null + + return ( + + {title} + {subtitle ? ( + + {subtitle} + + ) : undefined} + + ) +} + +export function ListMaybePlaceholder({ + isLoading, + isEmpty, + isError, + empty, + error, + notFoundType = 'page', + onRetry, +}: { + isLoading: boolean + isEmpty: boolean + isError: boolean + empty?: string + error?: string + notFoundType?: 'page' | 'results' + onRetry?: () => Promise +}) { + const navigation = useNavigation() + const t = useTheme() + const {gtMobile, gtTablet} = useBreakpoints() + + const canGoBack = navigation.canGoBack() + const onGoBack = React.useCallback(() => { + if (canGoBack) { + navigation.goBack() + } else { + navigation.navigate('HomeTab') + + // Checking the state for routes ensures that web doesn't encounter errors while going back + if (navigation.getState()?.routes) { + navigation.dispatch(StackActions.push(...router.matchPath('/'))) + } else { + navigation.navigate('HomeTab') + navigation.dispatch(StackActions.popToTop()) + } + } + }, [navigation, canGoBack]) + + if (!isEmpty) return null + + return ( + + {isLoading ? ( + + + + ) : ( + <> + + + {isError ? ( + Oops! + ) : isEmpty ? ( + <> + {notFoundType === 'results' ? ( + No results found + ) : ( + Page not found + )} + + ) : undefined} + + + {isError ? ( + + {error ? error : Something went wrong!} + + ) : isEmpty ? ( + + {empty ? ( + empty + ) : ( + + We're sorry! We can't find the page you were looking for. + + )} + + ) : undefined} + + + {isError && onRetry && ( + + )} + + + + )} + + ) +} diff --git a/src/components/Menu/context.tsx b/src/components/Menu/context.tsx new file mode 100644 index 0000000000..9fc91f6815 --- /dev/null +++ b/src/components/Menu/context.tsx @@ -0,0 +1,8 @@ +import React from 'react' + +import type {ContextType} from '#/components/Menu/types' + +export const Context = React.createContext({ + // @ts-ignore + control: null, +}) diff --git a/src/components/Menu/index.tsx b/src/components/Menu/index.tsx new file mode 100644 index 0000000000..ee96a5667e --- /dev/null +++ b/src/components/Menu/index.tsx @@ -0,0 +1,190 @@ +import React from 'react' +import {View, Pressable} from 'react-native' +import flattenReactChildren from 'react-keyed-flatten-children' + +import {atoms as a, useTheme} from '#/alf' +import * as Dialog from '#/components/Dialog' +import {useInteractionState} from '#/components/hooks/useInteractionState' +import {Text} from '#/components/Typography' + +import {Context} from '#/components/Menu/context' +import { + ContextType, + TriggerProps, + ItemProps, + GroupProps, + ItemTextProps, + ItemIconProps, +} from '#/components/Menu/types' + +export {useDialogControl as useMenuControl} from '#/components/Dialog' + +export function useMemoControlContext() { + return React.useContext(Context) +} + +export function Root({ + children, + control, +}: React.PropsWithChildren<{ + control?: Dialog.DialogOuterProps['control'] +}>) { + const defaultControl = Dialog.useDialogControl() + const context = React.useMemo( + () => ({ + control: control || defaultControl, + }), + [control, defaultControl], + ) + + return {children} +} + +export function Trigger({children, label}: TriggerProps) { + const {control} = React.useContext(Context) + const {state: focused, onIn: onFocus, onOut: onBlur} = useInteractionState() + const { + state: pressed, + onIn: onPressIn, + onOut: onPressOut, + } = useInteractionState() + + return children({ + isNative: true, + control, + state: { + hovered: false, + focused, + pressed, + }, + props: { + onPress: control.open, + onFocus, + onBlur, + onPressIn, + onPressOut, + accessibilityLabel: label, + }, + }) +} + +export function Outer({children}: React.PropsWithChildren<{}>) { + const context = React.useContext(Context) + + return ( + + + + {/* Re-wrap with context since Dialogs are portal-ed to root */} + + + {children} + + + + + ) +} + +export function Item({children, label, style, onPress, ...rest}: ItemProps) { + const t = useTheme() + const {control} = React.useContext(Context) + const {state: focused, onIn: onFocus, onOut: onBlur} = useInteractionState() + const { + state: pressed, + onIn: onPressIn, + onOut: onPressOut, + } = useInteractionState() + + return ( + { + onPress(e) + + if (!e.defaultPrevented) { + control?.close() + } + }} + onFocus={onFocus} + onBlur={onBlur} + onPressIn={onPressIn} + onPressOut={onPressOut} + style={[ + a.flex_row, + a.align_center, + a.gap_sm, + a.px_md, + a.rounded_md, + a.border, + t.atoms.bg_contrast_25, + t.atoms.border_contrast_low, + {minHeight: 44, paddingVertical: 10}, + style, + (focused || pressed) && [t.atoms.bg_contrast_50], + ]}> + {children} + + ) +} + +export function ItemText({children, style}: ItemTextProps) { + const t = useTheme() + return ( + + {children} + + ) +} + +export function ItemIcon({icon: Comp}: ItemIconProps) { + const t = useTheme() + return +} + +export function Group({children, style}: GroupProps) { + const t = useTheme() + return ( + + {flattenReactChildren(children).map((child, i) => { + return React.isValidElement(child) && child.type === Item ? ( + + {i > 0 ? ( + + ) : null} + {React.cloneElement(child, { + // @ts-ignore + style: { + borderRadius: 0, + borderWidth: 0, + }, + })} + + ) : null + })} + + ) +} + +export function Divider() { + return null +} diff --git a/src/components/Menu/index.web.tsx b/src/components/Menu/index.web.tsx new file mode 100644 index 0000000000..ca2e40566d --- /dev/null +++ b/src/components/Menu/index.web.tsx @@ -0,0 +1,247 @@ +import React from 'react' +import {View, Pressable} from 'react-native' +import * as DropdownMenu from '@radix-ui/react-dropdown-menu' + +import * as Dialog from '#/components/Dialog' +import {useInteractionState} from '#/components/hooks/useInteractionState' +import {atoms as a, useTheme, flatten, web} from '#/alf' +import {Text} from '#/components/Typography' + +import { + ContextType, + TriggerProps, + ItemProps, + GroupProps, + ItemTextProps, + ItemIconProps, +} from '#/components/Menu/types' +import {Context} from '#/components/Menu/context' + +export function useMenuControl(): Dialog.DialogControlProps { + const id = React.useId() + const [isOpen, setIsOpen] = React.useState(false) + + return React.useMemo( + () => ({ + id, + ref: {current: null}, + isOpen, + open() { + setIsOpen(true) + }, + close() { + setIsOpen(false) + }, + }), + [id, isOpen, setIsOpen], + ) +} + +export function useMemoControlContext() { + return React.useContext(Context) +} + +export function Root({ + children, + control, +}: React.PropsWithChildren<{ + control?: Dialog.DialogOuterProps['control'] +}>) { + const defaultControl = useMenuControl() + const context = React.useMemo( + () => ({ + control: control || defaultControl, + }), + [control, defaultControl], + ) + const onOpenChange = React.useCallback( + (open: boolean) => { + if (context.control.isOpen && !open) { + context.control.close() + } else if (!context.control.isOpen && open) { + context.control.open() + } + }, + [context.control], + ) + + return ( + + + {children} + + + ) +} + +export function Trigger({children, label, style}: TriggerProps) { + const {control} = React.useContext(Context) + const { + state: hovered, + onIn: onMouseEnter, + onOut: onMouseLeave, + } = useInteractionState() + const {state: focused, onIn: onFocus, onOut: onBlur} = useInteractionState() + + return ( + + { + control.open() + }} + {...web({ + onMouseEnter, + onMouseLeave, + })}> + {children({ + isNative: false, + control, + state: { + hovered, + focused, + pressed: false, + }, + props: {}, + })} + + + ) +} + +export function Outer({children}: React.PropsWithChildren<{}>) { + const t = useTheme() + + return ( + + + + {children} + + + + + + ) +} + +export function Item({children, label, onPress, ...rest}: ItemProps) { + const t = useTheme() + const {control} = React.useContext(Context) + const { + state: hovered, + onIn: onMouseEnter, + onOut: onMouseLeave, + } = useInteractionState() + const {state: focused, onIn: onFocus, onOut: onBlur} = useInteractionState() + + return ( + + { + onPress(e) + + /** + * Ported forward from Radix + * @see https://www.radix-ui.com/primitives/docs/components/dropdown-menu#item + */ + if (!e.defaultPrevented) { + control.close() + } + }} + onFocus={onFocus} + onBlur={onBlur} + // need `flatten` here for Radix compat + style={flatten([ + a.flex_row, + a.align_center, + a.gap_sm, + a.py_sm, + a.rounded_xs, + {minHeight: 32, paddingHorizontal: 10}, + web({outline: 0}), + (hovered || focused) && [ + web({outline: '0 !important'}), + t.name === 'light' + ? t.atoms.bg_contrast_25 + : t.atoms.bg_contrast_50, + ], + ])} + {...web({ + onMouseEnter, + onMouseLeave, + })}> + {children} + + + ) +} + +export function ItemText({children, style}: ItemTextProps) { + const t = useTheme() + return ( + + {children} + + ) +} + +export function ItemIcon({icon: Comp, position = 'left'}: ItemIconProps) { + const t = useTheme() + return ( + + ) +} + +export function Group({children}: GroupProps) { + return children +} + +export function Divider() { + const t = useTheme() + return ( + + ) +} diff --git a/src/components/Menu/types.ts b/src/components/Menu/types.ts new file mode 100644 index 0000000000..2f52e63906 --- /dev/null +++ b/src/components/Menu/types.ts @@ -0,0 +1,72 @@ +import React from 'react' +import {GestureResponderEvent, PressableProps} from 'react-native' + +import {Props as SVGIconProps} from '#/components/icons/common' +import * as Dialog from '#/components/Dialog' +import {TextStyleProp, ViewStyleProp} from '#/alf' + +export type ContextType = { + control: Dialog.DialogOuterProps['control'] +} + +export type TriggerProps = ViewStyleProp & { + children(props: TriggerChildProps): React.ReactNode + label: string +} +export type TriggerChildProps = + | { + isNative: true + control: Dialog.DialogOuterProps['control'] + state: { + /** + * Web only, `false` on native + */ + hovered: false + focused: boolean + pressed: boolean + } + /** + * We don't necessarily know what these will be spread on to, so we + * should add props one-by-one. + * + * On web, these properties are applied to a parent `Pressable`, so this + * object is empty. + */ + props: { + onPress: () => void + onFocus: () => void + onBlur: () => void + onPressIn: () => void + onPressOut: () => void + accessibilityLabel: string + } + } + | { + isNative: false + control: Dialog.DialogOuterProps['control'] + state: { + hovered: boolean + focused: boolean + /** + * Native only, `false` on web + */ + pressed: false + } + props: {} + } + +export type ItemProps = React.PropsWithChildren< + Omit & + ViewStyleProp & { + label: string + onPress: (e: GestureResponderEvent) => void + } +> + +export type ItemTextProps = React.PropsWithChildren +export type ItemIconProps = React.PropsWithChildren<{ + icon: React.ComponentType + position?: 'left' | 'right' +}> + +export type GroupProps = React.PropsWithChildren diff --git a/src/components/Prompt.tsx b/src/components/Prompt.tsx index 411679102b..8e55bd8347 100644 --- a/src/components/Prompt.tsx +++ b/src/components/Prompt.tsx @@ -89,7 +89,7 @@ export function Cancel({ color="secondary" size="small" label={_(msg`Cancel`)} - onPress={close}> + onPress={() => close()}> {children} ) diff --git a/src/components/RichText.tsx b/src/components/RichText.tsx index c72fcabdd8..1a14415cf8 100644 --- a/src/components/RichText.tsx +++ b/src/components/RichText.tsx @@ -1,11 +1,15 @@ import React from 'react' import {RichText as RichTextAPI, AppBskyRichtextFacet} from '@atproto/api' +import {useLingui} from '@lingui/react' +import {msg} from '@lingui/macro' -import {atoms as a, TextStyleProp, flatten} from '#/alf' +import {atoms as a, TextStyleProp, flatten, useTheme, web, native} from '#/alf' import {InlineLink} from '#/components/Link' import {Text, TextProps} from '#/components/Typography' import {toShortUrl} from 'lib/strings/url-helpers' -import {getAgent} from '#/state/session' +import {TagMenu, useTagMenuControl} from '#/components/TagMenu' +import {isNative} from '#/platform/detection' +import {useInteractionState} from '#/components/hooks/useInteractionState' const WORD_WRAP = {wordWrap: 1} @@ -15,37 +19,25 @@ export function RichText({ style, numberOfLines, disableLinks, - resolveFacets = false, selectable, + enableTags = false, + authorHandle, }: TextStyleProp & Pick & { value: RichTextAPI | string testID?: string numberOfLines?: number disableLinks?: boolean - resolveFacets?: boolean + enableTags?: boolean + authorHandle?: string }) { - const detected = React.useRef(false) - const [richText, setRichText] = React.useState(() => - value instanceof RichTextAPI ? value : new RichTextAPI({text: value}), + const richText = React.useMemo( + () => + value instanceof RichTextAPI ? value : new RichTextAPI({text: value}), + [value], ) const styles = [a.leading_snug, flatten(style)] - React.useEffect(() => { - if (!resolveFacets) return - - async function detectFacets() { - const rt = new RichTextAPI({text: richText.text}) - await rt.detectFacets(getAgent()) - setRichText(rt) - } - - if (!detected.current) { - detected.current = true - detectFacets() - } - }, [richText, setRichText, resolveFacets]) - const {text, facets} = richText if (!facets?.length) { @@ -85,6 +77,7 @@ export function RichText({ for (const segment of richText.segments()) { const link = segment.link const mention = segment.mention + const tag = segment.tag if ( mention && AppBskyRichtextFacet.validateMention(mention).success && @@ -112,12 +105,27 @@ export function RichText({ to={link.uri} style={[...styles, {pointerEvents: 'auto'}]} // @ts-ignore TODO - dataSet={WORD_WRAP} - warnOnMismatchingLabel> + dataSet={WORD_WRAP}> {toShortUrl(segment.text)} , ) } + } else if ( + !disableLinks && + enableTags && + tag && + AppBskyRichtextFacet.validateTag(tag).success + ) { + els.push( + , + ) } else { els.push(segment.text) } @@ -136,3 +144,81 @@ export function RichText({ ) } + +function RichTextTag({ + text, + tag, + style, + selectable, + authorHandle, +}: { + text: string + tag: string + selectable?: boolean + authorHandle?: string +} & TextStyleProp) { + const t = useTheme() + const {_} = useLingui() + const control = useTagMenuControl() + const { + state: hovered, + onIn: onHoverIn, + onOut: onHoverOut, + } = useInteractionState() + const {state: focused, onIn: onFocus, onOut: onBlur} = useInteractionState() + const { + state: pressed, + onIn: onPressIn, + onOut: onPressOut, + } = useInteractionState() + + const open = React.useCallback(() => { + control.open() + }, [control]) + + /* + * N.B. On web, this is wrapped in another pressable comopnent with a11y + * labels, etc. That's why only some of these props are applied here. + */ + + return ( + + + + {text} + + + + ) +} diff --git a/src/components/TagMenu/index.tsx b/src/components/TagMenu/index.tsx new file mode 100644 index 0000000000..849a3f42d1 --- /dev/null +++ b/src/components/TagMenu/index.tsx @@ -0,0 +1,275 @@ +import React from 'react' +import {View} from 'react-native' +import {useNavigation} from '@react-navigation/native' +import {useLingui} from '@lingui/react' +import {msg, Trans} from '@lingui/macro' + +import {atoms as a, native, useTheme} from '#/alf' +import * as Dialog from '#/components/Dialog' +import {Text} from '#/components/Typography' +import {Button, ButtonText} from '#/components/Button' +import {MagnifyingGlass2_Stroke2_Corner0_Rounded as Search} from '#/components/icons/MagnifyingGlass2' +import {Person_Stroke2_Corner0_Rounded as Person} from '#/components/icons/Person' +import {Mute_Stroke2_Corner0_Rounded as Mute} from '#/components/icons/Mute' +import {Divider} from '#/components/Divider' +import {Link} from '#/components/Link' +import {makeSearchLink} from '#/lib/routes/links' +import {NavigationProp} from '#/lib/routes/types' +import { + usePreferencesQuery, + useUpsertMutedWordsMutation, + useRemoveMutedWordMutation, +} from '#/state/queries/preferences' +import {Loader} from '#/components/Loader' +import {isInvalidHandle} from '#/lib/strings/handles' + +export function useTagMenuControl() { + return Dialog.useDialogControl() +} + +export function TagMenu({ + children, + control, + tag, + authorHandle, +}: React.PropsWithChildren<{ + control: Dialog.DialogOuterProps['control'] + /** + * This should be the sanitized tag value from the facet itself, not the + * "display" value with a leading `#`. + */ + tag: string + authorHandle?: string +}>) { + const {_} = useLingui() + const t = useTheme() + const navigation = useNavigation() + const {isLoading: isPreferencesLoading, data: preferences} = + usePreferencesQuery() + const { + mutateAsync: upsertMutedWord, + variables: optimisticUpsert, + reset: resetUpsert, + } = useUpsertMutedWordsMutation() + const { + mutateAsync: removeMutedWord, + variables: optimisticRemove, + reset: resetRemove, + } = useRemoveMutedWordMutation() + const displayTag = '#' + tag + + const isMuted = Boolean( + (preferences?.mutedWords?.find( + m => m.value === tag && m.targets.includes('tag'), + ) ?? + optimisticUpsert?.find( + m => m.value === tag && m.targets.includes('tag'), + )) && + !(optimisticRemove?.value === tag), + ) + + return ( + <> + {children} + + + + + + {isPreferencesLoading ? ( + + + + ) : ( + <> + + { + e.preventDefault() + + control.close(() => { + navigation.push('Hashtag', { + tag: encodeURIComponent(tag), + }) + }) + + return false + }}> + + + + + See{' '} + + {displayTag} + {' '} + posts + + + + + + {authorHandle && !isInvalidHandle(authorHandle) && ( + <> + + + { + e.preventDefault() + + control.close(() => { + navigation.push('Hashtag', { + tag: encodeURIComponent(tag), + author: authorHandle, + }) + }) + + return false + }}> + + + + + See{' '} + + {displayTag} + {' '} + posts by this user + + + + + + )} + + {preferences ? ( + <> + + + + + ) : null} + + + + + )} + + + + ) +} diff --git a/src/components/TagMenu/index.web.tsx b/src/components/TagMenu/index.web.tsx new file mode 100644 index 0000000000..8245bd0191 --- /dev/null +++ b/src/components/TagMenu/index.web.tsx @@ -0,0 +1,149 @@ +import React from 'react' +import {msg} from '@lingui/macro' +import {useLingui} from '@lingui/react' +import {useNavigation} from '@react-navigation/native' + +import {isInvalidHandle} from '#/lib/strings/handles' +import {EventStopper} from '#/view/com/util/EventStopper' +import {NativeDropdown} from '#/view/com/util/forms/NativeDropdown' +import {NavigationProp} from '#/lib/routes/types' +import { + usePreferencesQuery, + useUpsertMutedWordsMutation, + useRemoveMutedWordMutation, +} from '#/state/queries/preferences' +import {enforceLen} from '#/lib/strings/helpers' +import {web} from '#/alf' +import * as Dialog from '#/components/Dialog' + +export function useTagMenuControl(): Dialog.DialogControlProps { + return { + id: '', + // @ts-ignore + ref: null, + open: () => { + throw new Error(`TagMenu controls are only available on native platforms`) + }, + close: () => { + throw new Error(`TagMenu controls are only available on native platforms`) + }, + } +} + +export function TagMenu({ + children, + tag, + authorHandle, +}: React.PropsWithChildren<{ + /** + * This should be the sanitized tag value from the facet itself, not the + * "display" value with a leading `#`. + */ + tag: string + authorHandle?: string +}>) { + const {_} = useLingui() + const navigation = useNavigation() + const {data: preferences} = usePreferencesQuery() + const {mutateAsync: upsertMutedWord, variables: optimisticUpsert} = + useUpsertMutedWordsMutation() + const {mutateAsync: removeMutedWord, variables: optimisticRemove} = + useRemoveMutedWordMutation() + const isMuted = Boolean( + (preferences?.mutedWords?.find( + m => m.value === tag && m.targets.includes('tag'), + ) ?? + optimisticUpsert?.find( + m => m.value === tag && m.targets.includes('tag'), + )) && + !(optimisticRemove?.value === tag), + ) + const truncatedTag = '#' + enforceLen(tag, 15, true, 'middle') + + const dropdownItems = React.useMemo(() => { + return [ + { + label: _(msg`See ${truncatedTag} posts`), + onPress() { + navigation.push('Hashtag', { + tag: encodeURIComponent(tag), + }) + }, + testID: 'tagMenuSearch', + icon: { + ios: { + name: 'magnifyingglass', + }, + android: '', + web: 'magnifying-glass', + }, + }, + authorHandle && + !isInvalidHandle(authorHandle) && { + label: _(msg`See ${truncatedTag} posts by user`), + onPress() { + navigation.push('Hashtag', { + tag: encodeURIComponent(tag), + author: authorHandle, + }) + }, + testID: 'tagMenuSeachByUser', + icon: { + ios: { + name: 'magnifyingglass', + }, + android: '', + web: ['far', 'user'], + }, + }, + preferences && { + label: 'separator', + }, + preferences && { + label: isMuted + ? _(msg`Unmute ${truncatedTag}`) + : _(msg`Mute ${truncatedTag}`), + onPress() { + if (isMuted) { + removeMutedWord({value: tag, targets: ['tag']}) + } else { + upsertMutedWord([{value: tag, targets: ['tag']}]) + } + }, + testID: 'tagMenuMute', + icon: { + ios: { + name: 'speaker.slash', + }, + android: 'ic_menu_sort_alphabetically', + web: isMuted ? 'eye' : ['far', 'eye-slash'], + }, + }, + ].filter(Boolean) + }, [ + _, + authorHandle, + isMuted, + navigation, + preferences, + tag, + truncatedTag, + upsertMutedWord, + removeMutedWord, + ]) + + return ( + + + {children} + + + ) +} diff --git a/src/components/dialogs/MutedWords.tsx b/src/components/dialogs/MutedWords.tsx new file mode 100644 index 0000000000..658ba2aae0 --- /dev/null +++ b/src/components/dialogs/MutedWords.tsx @@ -0,0 +1,389 @@ +import React from 'react' +import {Keyboard, View} from 'react-native' +import {msg, Trans} from '@lingui/macro' +import {useLingui} from '@lingui/react' +import {AppBskyActorDefs, sanitizeMutedWordValue} from '@atproto/api' + +import { + usePreferencesQuery, + useUpsertMutedWordsMutation, + useRemoveMutedWordMutation, +} from '#/state/queries/preferences' +import {isNative} from '#/platform/detection' +import { + atoms as a, + useTheme, + useBreakpoints, + ViewStyleProp, + web, + native, +} from '#/alf' +import {Text} from '#/components/Typography' +import {Button, ButtonIcon, ButtonText} from '#/components/Button' +import {PlusLarge_Stroke2_Corner0_Rounded as Plus} from '#/components/icons/Plus' +import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times' +import {Hashtag_Stroke2_Corner0_Rounded as Hashtag} from '#/components/icons/Hashtag' +import {PageText_Stroke2_Corner0_Rounded as PageText} from '#/components/icons/PageText' +import {Divider} from '#/components/Divider' +import {Loader} from '#/components/Loader' +import {logger} from '#/logger' +import * as Dialog from '#/components/Dialog' +import * as Toggle from '#/components/forms/Toggle' +import * as Prompt from '#/components/Prompt' + +import {useGlobalDialogsControlContext} from '#/components/dialogs/Context' + +export function MutedWordsDialog() { + const {mutedWordsDialogControl: control} = useGlobalDialogsControlContext() + return ( + + + + + ) +} + +function MutedWordsInner({}: {control: Dialog.DialogOuterProps['control']}) { + const t = useTheme() + const {_} = useLingui() + const {gtMobile} = useBreakpoints() + const { + isLoading: isPreferencesLoading, + data: preferences, + error: preferencesError, + } = usePreferencesQuery() + const {isPending, mutateAsync: addMutedWord} = useUpsertMutedWordsMutation() + const [field, setField] = React.useState('') + const [options, setOptions] = React.useState(['content']) + const [error, setError] = React.useState('') + + const submit = React.useCallback(async () => { + const sanitizedValue = sanitizeMutedWordValue(field) + const targets = ['tag', options.includes('content') && 'content'].filter( + Boolean, + ) as AppBskyActorDefs.MutedWord['targets'] + + if (!sanitizedValue || !targets.length) { + setField('') + setError(_(msg`Please enter a valid word, tag, or phrase to mute`)) + return + } + + try { + // send raw value and rely on SDK as sanitization source of truth + await addMutedWord([{value: field, targets}]) + setField('') + } catch (e: any) { + logger.error(`Failed to save muted word`, {message: e.message}) + setError(e.message) + } + }, [_, field, options, addMutedWord, setField]) + + return ( + + + + Add muted words and tags + + + + Posts can be muted based on their text, their tags, or both. + + + + + { + if (error) { + setError('') + } + setField(value) + }} + onSubmitEditing={submit} + /> + + + + + + + + + Mute in text & tags + + + + + + + + + + + + Mute in tags only + + + + + + + + + + + {error && ( + + + {error} + + + )} + + + + We recommend avoiding common words that appear in many posts, + since it can result in no posts being shown. + + + + + + + + + Your muted words + + + {isPreferencesLoading ? ( + + ) : preferencesError || !preferences ? ( + + + + We're sorry, but we weren't able to load your muted words at + this time. Please try again. + + + + ) : preferences.mutedWords.length ? ( + [...preferences.mutedWords] + .reverse() + .map((word, i) => ( + + )) + ) : ( + + + You haven't muted any words or tags yet + + + )} + + + {isNative && } + + + + + ) +} + +function MutedWordRow({ + style, + word, +}: ViewStyleProp & {word: AppBskyActorDefs.MutedWord}) { + const t = useTheme() + const {_} = useLingui() + const {isPending, mutateAsync: removeMutedWord} = useRemoveMutedWordMutation() + const control = Prompt.usePromptControl() + + const remove = React.useCallback(async () => { + control.close() + removeMutedWord(word) + }, [removeMutedWord, word, control]) + + return ( + <> + + + Are you sure? + + + + This will delete {word.value} from your muted words. You can always + add it back later. + + + + + + Nevermind + + + + + Remove + + + + + + + + {word.value} + + + + {word.targets.map(target => ( + + + {target === 'content' ? _(msg`text`) : _(msg`tag`)} + + + ))} + + + + + + ) +} + +function TargetToggle({children}: React.PropsWithChildren<{}>) { + const t = useTheme() + const ctx = Toggle.useItemContext() + const {gtMobile} = useBreakpoints() + return ( + + {children} + + ) +} diff --git a/src/components/forms/DateField/index.android.tsx b/src/components/forms/DateField/index.android.tsx index cddb643d61..451810a5ea 100644 --- a/src/components/forms/DateField/index.android.tsx +++ b/src/components/forms/DateField/index.android.tsx @@ -1,8 +1,5 @@ import React from 'react' import {View, Pressable} from 'react-native' -import DateTimePicker, { - BaseProps as DateTimePickerProps, -} from '@react-native-community/datetimepicker' import {useTheme, atoms} from '#/alf' import {Text} from '#/components/Typography' @@ -15,6 +12,8 @@ import { localizeDate, toSimpleDateString, } from '#/components/forms/DateField/utils' +import DatePicker from 'react-native-date-picker' +import {isAndroid} from 'platform/detection' export * as utils from '#/components/forms/DateField/utils' export const Label = TextField.Label @@ -38,20 +37,20 @@ export function DateField({ const {chromeFocus, chromeError, chromeErrorHover} = TextField.useSharedInputStyles() - const onChangeInternal = React.useCallback< - Required['onChange'] - >( - (_event, date) => { + const onChangeInternal = React.useCallback( + (date: Date) => { setOpen(false) - if (date) { - const formatted = toSimpleDateString(date) - onChangeDate(formatted) - } + const formatted = toSimpleDateString(date) + onChangeDate(formatted) }, [onChangeDate, setOpen], ) + const onCancel = React.useCallback(() => { + setOpen(false) + }, []) + return ( {open && ( - )} diff --git a/src/components/forms/DateField/index.tsx b/src/components/forms/DateField/index.tsx index e65936e0ea..49e47a01e3 100644 --- a/src/components/forms/DateField/index.tsx +++ b/src/components/forms/DateField/index.tsx @@ -1,13 +1,11 @@ import React from 'react' import {View} from 'react-native' -import DateTimePicker, { - DateTimePickerEvent, -} from '@react-native-community/datetimepicker' import {useTheme, atoms} from '#/alf' import * as TextField from '#/components/forms/TextField' import {toSimpleDateString} from '#/components/forms/DateField/utils' import {DateFieldProps} from '#/components/forms/DateField/types' +import DatePicker from 'react-native-date-picker' export * as utils from '#/components/forms/DateField/utils' export const Label = TextField.Label @@ -28,7 +26,7 @@ export function DateField({ const t = useTheme() const onChangeInternal = React.useCallback( - (event: DateTimePickerEvent, date: Date | undefined) => { + (date: Date | undefined) => { if (date) { const formatted = toSimpleDateString(date) onChangeDate(formatted) @@ -39,17 +37,15 @@ export function DateField({ return ( - ) diff --git a/src/components/forms/TextField.tsx b/src/components/forms/TextField.tsx index ebf2e47506..b37f4bfae9 100644 --- a/src/components/forms/TextField.tsx +++ b/src/components/forms/TextField.tsx @@ -10,7 +10,7 @@ import { } from 'react-native' import {HITSLOP_20} from 'lib/constants' -import {useTheme, atoms as a, web, tokens, android} from '#/alf' +import {useTheme, atoms as a, web, android} from '#/alf' import {Text} from '#/components/Typography' import {useInteractionState} from '#/components/hooks/useInteractionState' import {Props as SVGIconProps} from '#/components/icons/common' @@ -72,7 +72,7 @@ export function Root({children, isInvalid = false}: RootProps) { return ( inputRef.current?.focus(), onMouseOver: onHoverIn, @@ -110,7 +110,7 @@ export function useSharedInputStyles() { { backgroundColor: t.name === 'light' ? t.palette.negative_25 : t.palette.negative_900, - borderColor: tokens.color.red_500, + borderColor: t.palette.negative_500, }, ] diff --git a/src/components/forms/Toggle.tsx b/src/components/forms/Toggle.tsx index b83465dded..168639d6f8 100644 --- a/src/components/forms/Toggle.tsx +++ b/src/components/forms/Toggle.tsx @@ -13,6 +13,7 @@ import { } from '#/alf' import {Text} from '#/components/Typography' import {useInteractionState} from '#/components/hooks/useInteractionState' +import {CheckThick_Stroke2_Corner0_Rounded as Checkmark} from '#/components/icons/Check' export type ItemState = { name: string @@ -314,7 +315,7 @@ export function createSharedToggleStyles({ if (isInvalid) { base.push({ backgroundColor: - t.name === 'light' ? t.palette.negative_25 : t.palette.negative_900, + t.name === 'light' ? t.palette.negative_25 : t.palette.negative_975, borderColor: t.name === 'light' ? t.palette.negative_300 : t.palette.negative_800, }) @@ -323,7 +324,7 @@ export function createSharedToggleStyles({ baseHover.push({ backgroundColor: t.name === 'light' ? t.palette.negative_25 : t.palette.negative_900, - borderColor: t.palette.negative_500, + borderColor: t.palette.negative_600, }) } } @@ -345,15 +346,14 @@ export function createSharedToggleStyles({ export function Checkbox() { const t = useTheme() const {selected, hovered, focused, disabled, isInvalid} = useItemContext() - const {baseStyles, baseHoverStyles, indicatorStyles} = - createSharedToggleStyles({ - theme: t, - hovered, - focused, - selected, - disabled, - isInvalid, - }) + const {baseStyles, baseHoverStyles} = createSharedToggleStyles({ + theme: t, + hovered, + focused, + selected, + disabled, + isInvalid, + }) return ( - {selected ? ( - - ) : null} + {selected ? : null} ) } diff --git a/src/components/icons/Check.tsx b/src/components/icons/Check.tsx index 24316c7849..fe9883baf8 100644 --- a/src/components/icons/Check.tsx +++ b/src/components/icons/Check.tsx @@ -3,3 +3,7 @@ import {createSinglePathSVG} from './TEMPLATE' export const Check_Stroke2_Corner0_Rounded = createSinglePathSVG({ path: 'M21.59 3.193a1 1 0 0 1 .217 1.397l-11.706 16a1 1 0 0 1-1.429.193l-6.294-5a1 1 0 1 1 1.244-1.566l5.48 4.353 11.09-15.16a1 1 0 0 1 1.398-.217Z', }) + +export const CheckThick_Stroke2_Corner0_Rounded = createSinglePathSVG({ + path: 'M21.474 2.98a2.5 2.5 0 0 1 .545 3.494l-10.222 14a2.5 2.5 0 0 1-3.528.52L2.49 16.617a2.5 2.5 0 0 1 3.018-3.986l3.75 2.84L17.98 3.525a2.5 2.5 0 0 1 3.493-.545Z', +}) diff --git a/src/components/icons/Clipboard.tsx b/src/components/icons/Clipboard.tsx new file mode 100644 index 0000000000..0135992b4c --- /dev/null +++ b/src/components/icons/Clipboard.tsx @@ -0,0 +1,5 @@ +import {createSinglePathSVG} from './TEMPLATE' + +export const Clipboard_Stroke2_Corner2_Rounded = createSinglePathSVG({ + path: 'M8.17 4A3.001 3.001 0 0 1 11 2h2c1.306 0 2.418.835 2.83 2H17a3 3 0 0 1 3 3v12a3 3 0 0 1-3 3H7a3 3 0 0 1-3-3V7a3 3 0 0 1 3-3h1.17ZM8 6H7a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V7a1 1 0 0 0-1-1h-1v1a1 1 0 0 1-1 1H9a1 1 0 0 1-1-1V6Zm6 0V5a1 1 0 0 0-1-1h-2a1 1 0 0 0-1 1v1h4Z', +}) diff --git a/src/components/icons/MagnifyingGlass2.tsx b/src/components/icons/MagnifyingGlass2.tsx new file mode 100644 index 0000000000..3ca4034001 --- /dev/null +++ b/src/components/icons/MagnifyingGlass2.tsx @@ -0,0 +1,5 @@ +import {createSinglePathSVG} from './TEMPLATE' + +export const MagnifyingGlass2_Stroke2_Corner0_Rounded = createSinglePathSVG({ + path: 'M11 5a6 6 0 1 0 0 12 6 6 0 0 0 0-12Zm-8 6a8 8 0 1 1 14.32 4.906l3.387 3.387a1 1 0 0 1-1.414 1.414l-3.387-3.387A8 8 0 0 1 3 11Z', +}) diff --git a/src/components/icons/Mute.tsx b/src/components/icons/Mute.tsx new file mode 100644 index 0000000000..0065707870 --- /dev/null +++ b/src/components/icons/Mute.tsx @@ -0,0 +1,5 @@ +import {createSinglePathSVG} from './TEMPLATE' + +export const Mute_Stroke2_Corner0_Rounded = createSinglePathSVG({ + path: 'M20.707 3.293a1 1 0 0 1 0 1.414l-16 16a1 1 0 0 1-1.414-1.414l2.616-2.616A1.998 1.998 0 0 1 5 15V9a2 2 0 0 1 2-2h2.697l5.748-3.832A1 1 0 0 1 17 4v1.586l2.293-2.293a1 1 0 0 1 1.414 0ZM15 7.586 7.586 15H7V9h2.697a2 2 0 0 0 1.11-.336L15 5.87v1.717Zm2 3.657-2 2v4.888l-2.933-1.955-1.442 1.442 4.82 3.214A1 1 0 0 0 17 20v-8.757Z', +}) diff --git a/src/components/icons/PageText.tsx b/src/components/icons/PageText.tsx new file mode 100644 index 0000000000..25fbde3392 --- /dev/null +++ b/src/components/icons/PageText.tsx @@ -0,0 +1,5 @@ +import {createSinglePathSVG} from './TEMPLATE' + +export const PageText_Stroke2_Corner0_Rounded = createSinglePathSVG({ + path: 'M5 2a1 1 0 0 0-1 1v18a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H5Zm1 18V4h12v16H6Zm3-6a1 1 0 1 0 0 2h2a1 1 0 1 0 0-2H9Zm-1-3a1 1 0 0 1 1-1h6a1 1 0 1 1 0 2H9a1 1 0 0 1-1-1Zm1-5a1 1 0 0 0 0 2h6a1 1 0 1 0 0-2H9Z', +}) diff --git a/src/components/moderation/ModerationDetailsDialog.tsx b/src/components/moderation/ModerationDetailsDialog.tsx index 0f2eb53636..a0462e8573 100644 --- a/src/components/moderation/ModerationDetailsDialog.tsx +++ b/src/components/moderation/ModerationDetailsDialog.tsx @@ -94,6 +94,15 @@ function ModerationDetailsDialogInner({ name = _(msg`Account Muted`) description = _(msg`You have muted this user.`) } + // TODO + // } else if (cause.type === 'muted-word') { + // return { + // icon: EyeSlash, + // name: _(msg`Post hidden by muted word`), + // description: _( + // msg`You've chosen to hide a word or tag within this post.`, + // ), + // } } else if (modcause.type === 'label') { name = desc.name description = desc.description diff --git a/src/lib/__tests__/moderatePost_wrapped.test.ts b/src/lib/__tests__/moderatePost_wrapped.test.ts new file mode 100644 index 0000000000..45566281af --- /dev/null +++ b/src/lib/__tests__/moderatePost_wrapped.test.ts @@ -0,0 +1,692 @@ +import {describe, it, expect} from '@jest/globals' +import {RichText} from '@atproto/api' + +import {hasMutedWord} from '../moderatePost_wrapped' + +describe(`hasMutedWord`, () => { + describe(`tags`, () => { + it(`match: outline tag`, () => { + const rt = new RichText({ + text: `This is a post #inlineTag`, + }) + rt.detectFacetsWithoutResolution() + + const match = hasMutedWord({ + mutedWords: [{value: 'outlineTag', targets: ['tag']}], + text: rt.text, + facets: rt.facets, + outlineTags: ['outlineTag'], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + + it(`match: inline tag`, () => { + const rt = new RichText({ + text: `This is a post #inlineTag`, + }) + rt.detectFacetsWithoutResolution() + + const match = hasMutedWord({ + mutedWords: [{value: 'inlineTag', targets: ['tag']}], + text: rt.text, + facets: rt.facets, + outlineTags: ['outlineTag'], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + + it(`match: content target matches inline tag`, () => { + const rt = new RichText({ + text: `This is a post #inlineTag`, + }) + rt.detectFacetsWithoutResolution() + + const match = hasMutedWord({ + mutedWords: [{value: 'inlineTag', targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: ['outlineTag'], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + + it(`no match: only tag targets`, () => { + const rt = new RichText({ + text: `This is a post`, + }) + rt.detectFacetsWithoutResolution() + + const match = hasMutedWord({ + mutedWords: [{value: 'inlineTag', targets: ['tag']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(false) + }) + }) + + describe(`early exits`, () => { + it(`match: single character 希`, () => { + /** + * @see https://bsky.app/profile/mukuuji.bsky.social/post/3klji4fvsdk2c + */ + const rt = new RichText({ + text: `ę”¹å–„åøŒęœ›ć§ć™`, + }) + rt.detectFacetsWithoutResolution() + + const match = hasMutedWord({ + mutedWords: [{value: '希', targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + + it(`no match: long muted word, short post`, () => { + const rt = new RichText({ + text: `hey`, + }) + rt.detectFacetsWithoutResolution() + + const match = hasMutedWord({ + mutedWords: [{value: 'politics', targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(false) + }) + + it(`match: exact text`, () => { + const rt = new RichText({ + text: `javascript`, + }) + rt.detectFacetsWithoutResolution() + + const match = hasMutedWord({ + mutedWords: [{value: 'javascript', targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + }) + + describe(`general content`, () => { + it(`match: word within post`, () => { + const rt = new RichText({ + text: `This is a post about javascript`, + }) + rt.detectFacetsWithoutResolution() + + const match = hasMutedWord({ + mutedWords: [{value: 'javascript', targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + + it(`no match: partial word`, () => { + const rt = new RichText({ + text: `Use your brain, Eric`, + }) + rt.detectFacetsWithoutResolution() + + const match = hasMutedWord({ + mutedWords: [{value: 'ai', targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(false) + }) + + it(`match: multiline`, () => { + const rt = new RichText({ + text: `Use your\n\tbrain, Eric`, + }) + rt.detectFacetsWithoutResolution() + + const match = hasMutedWord({ + mutedWords: [{value: 'brain', targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + + it(`match: :)`, () => { + const rt = new RichText({ + text: `So happy :)`, + }) + rt.detectFacetsWithoutResolution() + + const match = hasMutedWord({ + mutedWords: [{value: `:)`, targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + }) + + describe(`punctuation semi-fuzzy`, () => { + describe(`yay!`, () => { + const rt = new RichText({ + text: `We're federating, yay!`, + }) + rt.detectFacetsWithoutResolution() + + it(`match: yay!`, () => { + const match = hasMutedWord({ + mutedWords: [{value: 'yay!', targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + + it(`match: yay`, () => { + const match = hasMutedWord({ + mutedWords: [{value: 'yay', targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + }) + + describe(`y!ppee!!`, () => { + const rt = new RichText({ + text: `We're federating, y!ppee!!`, + }) + rt.detectFacetsWithoutResolution() + + it(`match: y!ppee`, () => { + const match = hasMutedWord({ + mutedWords: [{value: 'y!ppee', targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + + // single exclamation point, source has double + it(`no match: y!ppee!`, () => { + const match = hasMutedWord({ + mutedWords: [{value: 'y!ppee!', targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + }) + + describe(`Why so S@assy?`, () => { + const rt = new RichText({ + text: `Why so S@assy?`, + }) + rt.detectFacetsWithoutResolution() + + it(`match: S@assy`, () => { + const match = hasMutedWord({ + mutedWords: [{value: 'S@assy', targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + + it(`match: s@assy`, () => { + const match = hasMutedWord({ + mutedWords: [{value: 's@assy', targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + }) + + describe(`New York Times`, () => { + const rt = new RichText({ + text: `New York Times`, + }) + rt.detectFacetsWithoutResolution() + + // case insensitive + it(`match: new york times`, () => { + const match = hasMutedWord({ + mutedWords: [{value: 'new york times', targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + }) + + describe(`!command`, () => { + const rt = new RichText({ + text: `Idk maybe a bot !command`, + }) + rt.detectFacetsWithoutResolution() + + it(`match: !command`, () => { + const match = hasMutedWord({ + mutedWords: [{value: `!command`, targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + + it(`match: command`, () => { + const match = hasMutedWord({ + mutedWords: [{value: `command`, targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + + it(`no match: !command`, () => { + const rt = new RichText({ + text: `Idk maybe a bot command`, + }) + rt.detectFacetsWithoutResolution() + + const match = hasMutedWord({ + mutedWords: [{value: `!command`, targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(false) + }) + }) + + describe(`e/acc`, () => { + const rt = new RichText({ + text: `I'm e/acc pilled`, + }) + rt.detectFacetsWithoutResolution() + + it(`match: e/acc`, () => { + const match = hasMutedWord({ + mutedWords: [{value: `e/acc`, targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + + it(`match: acc`, () => { + const match = hasMutedWord({ + mutedWords: [{value: `acc`, targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + }) + + describe(`super-bad`, () => { + const rt = new RichText({ + text: `I'm super-bad`, + }) + rt.detectFacetsWithoutResolution() + + it(`match: super-bad`, () => { + const match = hasMutedWord({ + mutedWords: [{value: `super-bad`, targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + + it(`match: super`, () => { + const match = hasMutedWord({ + mutedWords: [{value: `super`, targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + + it(`match: super bad`, () => { + const match = hasMutedWord({ + mutedWords: [{value: `super bad`, targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + + it(`match: superbad`, () => { + const match = hasMutedWord({ + mutedWords: [{value: `superbad`, targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(false) + }) + }) + + describe(`idk_what_this_would_be`, () => { + const rt = new RichText({ + text: `Weird post with idk_what_this_would_be`, + }) + rt.detectFacetsWithoutResolution() + + it(`match: idk what this would be`, () => { + const match = hasMutedWord({ + mutedWords: [{value: `idk what this would be`, targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + + it(`no match: idk what this would be for`, () => { + // extra word + const match = hasMutedWord({ + mutedWords: [ + {value: `idk what this would be for`, targets: ['content']}, + ], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(false) + }) + + it(`match: idk`, () => { + // extra word + const match = hasMutedWord({ + mutedWords: [{value: `idk`, targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + + it(`match: idkwhatthiswouldbe`, () => { + const match = hasMutedWord({ + mutedWords: [{value: `idkwhatthiswouldbe`, targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(false) + }) + }) + + describe(`parentheses`, () => { + const rt = new RichText({ + text: `Post with context(iykyk)`, + }) + rt.detectFacetsWithoutResolution() + + it(`match: context(iykyk)`, () => { + const match = hasMutedWord({ + mutedWords: [{value: `context(iykyk)`, targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + + it(`match: context`, () => { + const match = hasMutedWord({ + mutedWords: [{value: `context`, targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + + it(`match: iykyk`, () => { + const match = hasMutedWord({ + mutedWords: [{value: `iykyk`, targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + + it(`match: (iykyk)`, () => { + const match = hasMutedWord({ + mutedWords: [{value: `(iykyk)`, targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + }) + + describe(`šŸ¦‹`, () => { + const rt = new RichText({ + text: `Post with šŸ¦‹`, + }) + rt.detectFacetsWithoutResolution() + + it(`match: šŸ¦‹`, () => { + const match = hasMutedWord({ + mutedWords: [{value: `šŸ¦‹`, targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + }) + }) + + describe(`phrases`, () => { + describe(`I like turtles, or how I learned to stop worrying and love the internet.`, () => { + const rt = new RichText({ + text: `I like turtles, or how I learned to stop worrying and love the internet.`, + }) + rt.detectFacetsWithoutResolution() + + it(`match: stop worrying`, () => { + const match = hasMutedWord({ + mutedWords: [{value: 'stop worrying', targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + + it(`match: turtles, or how`, () => { + const match = hasMutedWord({ + mutedWords: [{value: 'turtles, or how', targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + }) + }) + + describe(`languages without spaces`, () => { + // I love turtles, or how I learned to stop worrying and love the internet + describe(`ē§ćÆć‚«ćƒ”ćŒå„½ćć§ć™ć€ć¾ćŸćÆć©ć®ć‚ˆć†ć«ć—ć¦åæƒé…ć™ć‚‹ć®ć‚’ć‚„ć‚ć¦ć‚¤ćƒ³ć‚æćƒ¼ćƒćƒƒćƒˆć‚’ę„›ć™ć‚‹ć‚ˆć†ć«ćŖć£ćŸć®ć‹`, () => { + const rt = new RichText({ + text: `ē§ćÆć‚«ćƒ”ćŒå„½ćć§ć™ć€ć¾ćŸćÆć©ć®ć‚ˆć†ć«ć—ć¦åæƒé…ć™ć‚‹ć®ć‚’ć‚„ć‚ć¦ć‚¤ćƒ³ć‚æćƒ¼ćƒćƒƒćƒˆć‚’ę„›ć™ć‚‹ć‚ˆć†ć«ćŖć£ćŸć®ć‹`, + }) + rt.detectFacetsWithoutResolution() + + // internet + it(`match: ć‚¤ćƒ³ć‚æćƒ¼ćƒćƒƒćƒˆ`, () => { + const match = hasMutedWord({ + mutedWords: [{value: 'ć‚¤ćƒ³ć‚æćƒ¼ćƒćƒƒćƒˆ', targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + languages: ['ja'], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + }) + }) + + describe(`doesn't mute own post`, () => { + it(`does mute if it isn't own post`, () => { + const rt = new RichText({ + text: `Mute words!`, + }) + + const match = hasMutedWord({ + mutedWords: [{value: 'words', targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: false, + }) + + expect(match).toBe(true) + }) + + it(`doesn't mute own post when muted word is in text`, () => { + const rt = new RichText({ + text: `Mute words!`, + }) + + const match = hasMutedWord({ + mutedWords: [{value: 'words', targets: ['content']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: true, + }) + + expect(match).toBe(false) + }) + + it(`doesn't mute own post when muted word is in tags`, () => { + const rt = new RichText({ + text: `Mute #words!`, + }) + + const match = hasMutedWord({ + mutedWords: [{value: 'words', targets: ['tags']}], + text: rt.text, + facets: rt.facets, + outlineTags: [], + isOwnPost: true, + }) + + expect(match).toBe(false) + }) + }) +}) diff --git a/src/lib/api/index.ts b/src/lib/api/index.ts index 440dfa5ee3..5fb7fe50e6 100644 --- a/src/lib/api/index.ts +++ b/src/lib/api/index.ts @@ -104,18 +104,18 @@ export async function post(agent: BskyAgent, opts: PostOpts) { // add image embed if present if (opts.images?.length) { - logger.info(`Uploading images`, { + logger.debug(`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`) + logger.debug(`Compressing image`) await image.compress() const path = image.compressed?.path ?? image.path const {width, height} = image.compressed || image - logger.info(`Uploading image`) + logger.debug(`Uploading image`) const res = await uploadBlob(agent, path, 'image/jpeg') images.push({ image: res.data.blob, diff --git a/src/lib/constants.ts b/src/lib/constants.ts index c8e5273d47..e868443950 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -75,3 +75,9 @@ export const HITSLOP_20 = createHitslop(20) export const HITSLOP_30 = createHitslop(30) export const BACK_HITSLOP = HITSLOP_30 export const MAX_POST_LINES = 25 + +export const BSKY_FEED_OWNER_DIDS = [ + 'did:plc:z72i7hdynmk6r22z27h6tvur', + 'did:plc:vpkhqolt662uhesyj6nxm7ys', + 'did:plc:q6gjnaw2blty4crticxkmujt', +] diff --git a/src/lib/hooks/useInitialNumToRender.ts b/src/lib/hooks/useInitialNumToRender.ts new file mode 100644 index 0000000000..942f0404ab --- /dev/null +++ b/src/lib/hooks/useInitialNumToRender.ts @@ -0,0 +1,11 @@ +import React from 'react' +import {Dimensions} from 'react-native' + +const MIN_POST_HEIGHT = 100 + +export function useInitialNumToRender(minItemHeight: number = MIN_POST_HEIGHT) { + return React.useMemo(() => { + const screenHeight = Dimensions.get('window').height + return Math.ceil(screenHeight / minItemHeight) + 1 + }, [minItemHeight]) +} diff --git a/src/lib/hooks/useIntentHandler.ts b/src/lib/hooks/useIntentHandler.ts new file mode 100644 index 0000000000..8741530b50 --- /dev/null +++ b/src/lib/hooks/useIntentHandler.ts @@ -0,0 +1,93 @@ +import React from 'react' +import * as Linking from 'expo-linking' +import {isNative} from 'platform/detection' +import {useComposerControls} from 'state/shell' +import {useSession} from 'state/session' +import {useCloseAllActiveElements} from 'state/util' + +type IntentType = 'compose' + +const VALID_IMAGE_REGEX = /^[\w.:\-_/]+\|\d+(\.\d+)?\|\d+(\.\d+)?$/ + +export function useIntentHandler() { + const incomingUrl = Linking.useURL() + const composeIntent = useComposeIntent() + + React.useEffect(() => { + const handleIncomingURL = (url: string) => { + // We want to be able to support bluesky:// deeplinks. It's unnatural for someone to use a deeplink with three + // slashes, like bluesky:///intent/follow. However, supporting just two slashes causes us to have to take care + // of two cases when parsing the url. If we ensure there is a third slash, we can always ensure the first + // path parameter is in pathname rather than in hostname. + if (url.startsWith('bluesky://') && !url.startsWith('bluesky:///')) { + url = url.replace('bluesky://', 'bluesky:///') + } + + const urlp = new URL(url) + const [_, intent, intentType] = urlp.pathname.split('/') + + // On native, our links look like bluesky://intent/SomeIntent, so we have to check the hostname for the + // intent check. On web, we have to check the first part of the path since we have an actual hostname + const isIntent = intent === 'intent' + const params = urlp.searchParams + + if (!isIntent) return + + switch (intentType as IntentType) { + case 'compose': { + composeIntent({ + text: params.get('text'), + imageUrisStr: params.get('imageUris'), + }) + } + } + } + + if (incomingUrl) handleIncomingURL(incomingUrl) + }, [incomingUrl, composeIntent]) +} + +function useComposeIntent() { + const closeAllActiveElements = useCloseAllActiveElements() + const {openComposer} = useComposerControls() + const {hasSession} = useSession() + + return React.useCallback( + ({ + text, + imageUrisStr, + }: { + text: string | null + imageUrisStr: string | null // unused for right now, will be used later with intents + }) => { + if (!hasSession) return + + closeAllActiveElements() + + const imageUris = imageUrisStr + ?.split(',') + .filter(part => { + // For some security, we're going to filter out any image uri that is external. We don't want someone to + // be able to provide some link like "bluesky://intent/compose?imageUris=https://IHaveYourIpNow.com/image.jpeg + // and we load that image + if (part.includes('https://') || part.includes('http://')) { + return false + } + // We also should just filter out cases that don't have all the info we need + return VALID_IMAGE_REGEX.test(part) + }) + .map(part => { + const [uri, width, height] = part.split('|') + return {uri, width: Number(width), height: Number(height)} + }) + + setTimeout(() => { + openComposer({ + text: text ?? undefined, + imageUris: isNative ? imageUris : undefined, + }) + }, 500) + }, + [hasSession, closeAllActiveElements, openComposer], + ) +} diff --git a/src/lib/moderatePost_wrapped.ts b/src/lib/moderatePost_wrapped.ts index 90581ff31c..0037d4a7a9 100644 --- a/src/lib/moderatePost_wrapped.ts +++ b/src/lib/moderatePost_wrapped.ts @@ -1,8 +1,144 @@ -import {moderatePost} from '@atproto/api' +import { + // AppBskyEmbedRecord, + // AppBskyEmbedRecordWithMedia, + moderatePost, + AppBskyActorDefs, + // AppBskyFeedPost, + AppBskyRichtextFacet, + // AppBskyEmbedImages, + // AppBskyEmbedExternal, +} from '@atproto/api' type ModeratePost = typeof moderatePost type Options = Parameters[1] & { hiddenPosts?: string[] + mutedWords?: AppBskyActorDefs.MutedWord[] +} + +const REGEX = { + LEADING_TRAILING_PUNCTUATION: /(?:^\p{P}+|\p{P}+$)/gu, + ESCAPE: /[[\]{}()*+?.\\^$|\s]/g, + SEPARATORS: /[\/\-\–\—\(\)\[\]\_]+/g, + WORD_BOUNDARY: /[\s\n\t\r\f\v]+?/g, +} + +/** + * List of 2-letter lang codes for languages that either don't use spaces, or + * don't use spaces in a way conducive to word-based filtering. + * + * For these, we use a simple `String.includes` to check for a match. + */ +const LANGUAGE_EXCEPTIONS = [ + 'ja', // Japanese + 'zh', // Chinese + 'ko', // Korean + 'th', // Thai + 'vi', // Vietnamese +] + +export function hasMutedWord({ + mutedWords, + text, + facets, + outlineTags, + languages, + isOwnPost, +}: { + mutedWords: AppBskyActorDefs.MutedWord[] + text: string + facets?: AppBskyRichtextFacet.Main[] + outlineTags?: string[] + languages?: string[] + isOwnPost: boolean +}) { + if (isOwnPost) return false + + const exception = LANGUAGE_EXCEPTIONS.includes(languages?.[0] || '') + const tags = ([] as string[]) + .concat(outlineTags || []) + .concat( + facets + ?.filter(facet => { + return facet.features.find(feature => + AppBskyRichtextFacet.isTag(feature), + ) + }) + .map(t => t.features[0].tag as string) || [], + ) + .map(t => t.toLowerCase()) + + for (const mute of mutedWords) { + const mutedWord = mute.value.toLowerCase() + const postText = text.toLowerCase() + + // `content` applies to tags as well + if (tags.includes(mutedWord)) return true + // rest of the checks are for `content` only + if (!mute.targets.includes('content')) continue + // single character or other exception, has to use includes + if ((mutedWord.length === 1 || exception) && postText.includes(mutedWord)) + return true + // too long + if (mutedWord.length > postText.length) continue + // exact match + if (mutedWord === postText) return true + // any muted phrase with space or punctuation + if (/(?:\s|\p{P})+?/u.test(mutedWord) && postText.includes(mutedWord)) + return true + + // check individual character groups + const words = postText.split(REGEX.WORD_BOUNDARY) + for (const word of words) { + if (word === mutedWord) return true + + // compare word without leading/trailing punctuation, but allow internal + // punctuation (such as `s@ssy`) + const wordTrimmedPunctuation = word.replace( + REGEX.LEADING_TRAILING_PUNCTUATION, + '', + ) + + if (mutedWord === wordTrimmedPunctuation) return true + if (mutedWord.length > wordTrimmedPunctuation.length) continue + + // handle hyphenated, slash separated words, etc + if (REGEX.SEPARATORS.test(wordTrimmedPunctuation)) { + // check against full normalized phrase + const wordNormalizedSeparators = wordTrimmedPunctuation.replace( + REGEX.SEPARATORS, + ' ', + ) + const mutedWordNormalizedSeparators = mutedWord.replace( + REGEX.SEPARATORS, + ' ', + ) + // hyphenated (or other sep) to spaced words + if (wordNormalizedSeparators === mutedWordNormalizedSeparators) + return true + + /* Disabled for now e.g. `super-cool` to `supercool` + const wordNormalizedCompressed = wordNormalizedSeparators.replace( + REGEX.WORD_BOUNDARY, + '', + ) + const mutedWordNormalizedCompressed = + mutedWordNormalizedSeparators.replace(/\s+?/g, '') + // hyphenated (or other sep) to non-hyphenated contiguous word + if (mutedWordNormalizedCompressed === wordNormalizedCompressed) + return true + */ + + // then individual parts of separated phrases/words + const wordParts = wordTrimmedPunctuation.split(REGEX.SEPARATORS) + for (const wp of wordParts) { + // still retain internal punctuation + if (wp === mutedWord) return true + } + } + } + } + + return false } export function moderatePost_wrapped( @@ -12,4 +148,238 @@ export function moderatePost_wrapped( const moderation = moderatePost(subject, opts) moderation.addHidden(opts.hiddenPosts?.includes(subject.uri) || false) return moderation + /* TODO + const {hiddenPosts = [], mutedWords = [], ...options} = opts + const moderations = moderatePost(subject, options) + const isOwnPost = subject.author.did === opts.userDid + + if (hiddenPosts.includes(subject.uri)) { + moderations.content.filter = true + moderations.content.blur = true + if (!moderations.content.cause) { + moderations.content.cause = { + // @ts-ignore Temporary extension to the moderation system -prf + type: 'post-hidden', + source: {type: 'user'}, + priority: 1, + } + } + } + + if (AppBskyFeedPost.isRecord(subject.record)) { + let muted = hasMutedWord({ + mutedWords, + text: subject.record.text, + facets: subject.record.facets || [], + outlineTags: subject.record.tags || [], + languages: subject.record.langs, + isOwnPost, + }) + + if ( + subject.record.embed && + AppBskyEmbedImages.isMain(subject.record.embed) + ) { + for (const image of subject.record.embed.images) { + muted = + muted || + hasMutedWord({ + mutedWords, + text: image.alt, + facets: [], + outlineTags: [], + languages: subject.record.langs, + isOwnPost, + }) + } + } + + if (muted) { + moderations.content.filter = true + moderations.content.blur = true + if (!moderations.content.cause) { + moderations.content.cause = { + // @ts-ignore Temporary extension to the moderation system -prf + type: 'muted-word', + source: {type: 'user'}, + priority: 1, + } + } + } + } + + if (subject.embed) { + let embedHidden = false + let embedMuted = false + let externalMuted = false + + if (AppBskyEmbedRecord.isViewRecord(subject.embed.record)) { + embedHidden = hiddenPosts.includes(subject.embed.record.uri) + } + if ( + AppBskyEmbedRecordWithMedia.isView(subject.embed) && + AppBskyEmbedRecord.isViewRecord(subject.embed.record.record) + ) { + embedHidden = hiddenPosts.includes(subject.embed.record.record.uri) + } + + if (AppBskyEmbedRecord.isViewRecord(subject.embed.record)) { + if (AppBskyFeedPost.isRecord(subject.embed.record.value)) { + const embeddedPost = subject.embed.record.value + + embedMuted = + embedMuted || + hasMutedWord({ + mutedWords, + text: embeddedPost.text, + facets: embeddedPost.facets, + outlineTags: embeddedPost.tags, + languages: embeddedPost.langs, + isOwnPost, + }) + + if (AppBskyEmbedImages.isMain(embeddedPost.embed)) { + for (const image of embeddedPost.embed.images) { + embedMuted = + embedMuted || + hasMutedWord({ + mutedWords, + text: image.alt, + facets: [], + outlineTags: [], + languages: embeddedPost.langs, + isOwnPost, + }) + } + } + + if (AppBskyEmbedExternal.isMain(embeddedPost.embed)) { + const {external} = embeddedPost.embed + + embedMuted = + embedMuted || + hasMutedWord({ + mutedWords, + text: external.title + ' ' + external.description, + facets: [], + outlineTags: [], + languages: [], + isOwnPost, + }) + } + + if (AppBskyEmbedRecordWithMedia.isMain(embeddedPost.embed)) { + if (AppBskyEmbedExternal.isMain(embeddedPost.embed.media)) { + const {external} = embeddedPost.embed.media + + embedMuted = + embedMuted || + hasMutedWord({ + mutedWords, + text: external.title + ' ' + external.description, + facets: [], + outlineTags: [], + languages: [], + isOwnPost, + }) + } + + if (AppBskyEmbedImages.isMain(embeddedPost.embed.media)) { + for (const image of embeddedPost.embed.media.images) { + embedMuted = + embedMuted || + hasMutedWord({ + mutedWords, + text: image.alt, + facets: [], + outlineTags: [], + languages: AppBskyFeedPost.isRecord(embeddedPost.record) + ? embeddedPost.langs + : [], + isOwnPost, + }) + } + } + } + } + } + + if (AppBskyEmbedExternal.isView(subject.embed)) { + const {external} = subject.embed + + externalMuted = + externalMuted || + hasMutedWord({ + mutedWords, + text: external.title + ' ' + external.description, + facets: [], + outlineTags: [], + languages: [], + isOwnPost, + }) + } + + if ( + AppBskyEmbedRecordWithMedia.isView(subject.embed) && + AppBskyEmbedRecord.isViewRecord(subject.embed.record.record) + ) { + if (AppBskyFeedPost.isRecord(subject.embed.record.record.value)) { + const post = subject.embed.record.record.value + embedMuted = + embedMuted || + hasMutedWord({ + mutedWords, + text: post.text, + facets: post.facets, + outlineTags: post.tags, + languages: post.langs, + isOwnPost, + }) + } + + if (AppBskyEmbedImages.isView(subject.embed.media)) { + for (const image of subject.embed.media.images) { + embedMuted = + embedMuted || + hasMutedWord({ + mutedWords, + text: image.alt, + facets: [], + outlineTags: [], + languages: AppBskyFeedPost.isRecord(subject.record) + ? subject.record.langs + : [], + isOwnPost, + }) + } + } + } + + if (embedHidden) { + moderations.embed.filter = true + moderations.embed.blur = true + if (!moderations.embed.cause) { + moderations.embed.cause = { + // @ts-ignore Temporary extension to the moderation system -prf + type: 'post-hidden', + source: {type: 'user'}, + priority: 1, + } + } + } else if (externalMuted || embedMuted) { + moderations.content.filter = true + moderations.content.blur = true + if (!moderations.content.cause) { + moderations.content.cause = { + // @ts-ignore Temporary extension to the moderation system -prf + type: 'muted-word', + source: {type: 'user'}, + priority: 1, + } + } + } + } + + return moderations + */ } diff --git a/src/lib/moderation/useModerationCauseDescription.ts b/src/lib/moderation/useModerationCauseDescription.ts index de2e9788f8..882480491c 100644 --- a/src/lib/moderation/useModerationCauseDescription.ts +++ b/src/lib/moderation/useModerationCauseDescription.ts @@ -84,6 +84,16 @@ export function useModerationCauseDescription( } } } + // TODO + // if (cause.type === 'muted-word') { + // return { + // icon: EyeSlash, + // name: _(msg`Post hidden by muted word`), + // description: _( + // msg`You've chosen to hide a word or tag within this post.`, + // ), + // } + // } // @ts-ignore Temporary extension to the moderation system -prf if (cause.type === 'hidden') { return { diff --git a/src/lib/routes/links.ts b/src/lib/routes/links.ts index 538f30cd31..9dfdab909b 100644 --- a/src/lib/routes/links.ts +++ b/src/lib/routes/links.ts @@ -25,3 +25,13 @@ export function makeCustomFeedLink( export function makeListLink(did: string, rkey: string, ...segments: string[]) { return [`/profile`, did, 'lists', rkey, ...segments].join('/') } + +export function makeTagLink(did: string) { + return `/search?q=${encodeURIComponent(did)}` +} + +export function makeSearchLink(props: {query: string; from?: 'me' | string}) { + return `/search?q=${encodeURIComponent( + props.query + (props.from ? ` from:${props.from}` : ''), + )}` +} diff --git a/src/lib/routes/types.ts b/src/lib/routes/types.ts index c4bf4dd0c2..59495401d5 100644 --- a/src/lib/routes/types.ts +++ b/src/lib/routes/types.ts @@ -34,6 +34,8 @@ export type CommonNavigatorParams = { PreferencesFollowingFeed: undefined PreferencesThreads: undefined PreferencesExternalEmbeds: undefined + Search: {q?: string} + Hashtag: {tag: string; author?: string} } export type BottomTabNavigatorParams = CommonNavigatorParams & { @@ -69,6 +71,7 @@ export type FlatNavigatorParams = CommonNavigatorParams & { Search: {q?: string} Feeds: undefined Notifications: undefined + Hashtag: {tag: string; author?: string} } export type AllNavigatorParams = CommonNavigatorParams & { @@ -81,6 +84,7 @@ export type AllNavigatorParams = CommonNavigatorParams & { NotificationsTab: undefined Notifications: undefined MyProfileTab: undefined + Hashtag: {tag: string; author?: string} } // NOTE diff --git a/src/lib/statsig/statsig.tsx b/src/lib/statsig/statsig.tsx new file mode 100644 index 0000000000..43822dda85 --- /dev/null +++ b/src/lib/statsig/statsig.tsx @@ -0,0 +1,63 @@ +import React from 'react' +import { + Statsig, + StatsigProvider, + useGate as useStatsigGate, +} from 'statsig-react-native-expo' +import {useSession} from '../../state/session' +import {sha256} from 'js-sha256' + +const statsigOptions = { + environment: { + tier: process.env.NODE_ENV === 'development' ? 'development' : 'production', + }, + // Don't block on waiting for network. The fetched config will kick in on next load. + // This ensures the UI is always consistent and doesn't update mid-session. + // Note this makes cold load (no local storage) and private mode return `false` for all gates. + initTimeoutMs: 1, +} + +export function logEvent( + eventName: string, + value?: string | number | null, + metadata?: Record | null, +) { + Statsig.logEvent(eventName, value, metadata) +} + +export function useGate(gateName: string) { + const {isLoading, value} = useStatsigGate(gateName) + if (isLoading) { + // This should not happen because of waitForInitialization={true}. + console.error('Did not expected isLoading to ever be true.') + } + return value +} + +function toStatsigUser(did: string | undefined) { + let userID: string | undefined + if (did) { + userID = sha256(did) + } + return {userID} +} + +export function Provider({children}: {children: React.ReactNode}) { + const {currentAccount} = useSession() + const currentStatsigUser = React.useMemo( + () => toStatsigUser(currentAccount?.did), + [currentAccount?.did], + ) + return ( + + {children} + + ) +} diff --git a/src/lib/statsig/statsig.web.tsx b/src/lib/statsig/statsig.web.tsx new file mode 100644 index 0000000000..fc66e8d9fd --- /dev/null +++ b/src/lib/statsig/statsig.web.tsx @@ -0,0 +1,63 @@ +import React from 'react' +import { + Statsig, + StatsigProvider, + useGate as useStatsigGate, +} from 'statsig-react' +import {useSession} from '../../state/session' +import {sha256} from 'js-sha256' + +const statsigOptions = { + environment: { + tier: process.env.NODE_ENV === 'development' ? 'development' : 'production', + }, + // Don't block on waiting for network. The fetched config will kick in on next load. + // This ensures the UI is always consistent and doesn't update mid-session. + // Note this makes cold load (no local storage) and private mode return `false` for all gates. + initTimeoutMs: 1, +} + +export function logEvent( + eventName: string, + value?: string | number | null, + metadata?: Record | null, +) { + Statsig.logEvent(eventName, value, metadata) +} + +export function useGate(gateName: string) { + const {isLoading, value} = useStatsigGate(gateName) + if (isLoading) { + // This should not happen because of waitForInitialization={true}. + console.error('Did not expected isLoading to ever be true.') + } + return value +} + +function toStatsigUser(did: string | undefined) { + let userID: string | undefined + if (did) { + userID = sha256(did) + } + return {userID} +} + +export function Provider({children}: {children: React.ReactNode}) { + const {currentAccount} = useSession() + const currentStatsigUser = React.useMemo( + () => toStatsigUser(currentAccount?.did), + [currentAccount?.did], + ) + return ( + + {children} + + ) +} diff --git a/src/lib/strings/helpers.ts b/src/lib/strings/helpers.ts index e2abe90195..de4562d2c8 100644 --- a/src/lib/strings/helpers.ts +++ b/src/lib/strings/helpers.ts @@ -8,10 +8,27 @@ export function pluralize(n: number, base: string, plural?: string): string { return base + 's' } -export function enforceLen(str: string, len: number, ellipsis = false): string { +export function enforceLen( + str: string, + len: number, + ellipsis = false, + mode: 'end' | 'middle' = 'end', +): string { str = str || '' if (str.length > len) { - return str.slice(0, len) + (ellipsis ? '...' : '') + if (ellipsis) { + if (mode === 'end') { + return str.slice(0, len) + '…' + } else if (mode === 'middle') { + const half = Math.floor(len / 2) + return str.slice(0, half) + '…' + str.slice(-half) + } else { + // fallback + return str.slice(0, len) + } + } else { + return str.slice(0, len) + } } return str } diff --git a/src/lib/strings/url-helpers.ts b/src/lib/strings/url-helpers.ts index ef341154df..7729e4a382 100644 --- a/src/lib/strings/url-helpers.ts +++ b/src/lib/strings/url-helpers.ts @@ -148,6 +148,11 @@ export function feedUriToHref(url: string): string { export function linkRequiresWarning(uri: string, label: string) { const labelDomain = labelToDomain(label) + // If the uri started with a / we know it is internal. + if (uri.startsWith('/')) { + return false + } + let urip try { urip = new URL(uri) @@ -156,18 +161,15 @@ export function linkRequiresWarning(uri: string, label: string) { } const host = urip.hostname.toLowerCase() - - if (host === 'bsky.app') { + // Hosts that end with bsky.app or bsky.social should be trusted by default. + if ( + host.endsWith('bsky.app') || + host.endsWith('bsky.social') || + host.endsWith('blueskyweb.xyz') + ) { // if this is a link to internal content, // warn if it represents itself as a URL to another app - if ( - labelDomain && - labelDomain !== 'bsky.app' && - isPossiblyAUrl(labelDomain) - ) { - return true - } - return false + return !!labelDomain && labelDomain !== host && isPossiblyAUrl(labelDomain) } else { // if this is a link to external content, // warn if the label doesnt match the target diff --git a/src/lib/themes.ts b/src/lib/themes.ts index 135d50ab66..bd75aabea6 100644 --- a/src/lib/themes.ts +++ b/src/lib/themes.ts @@ -357,8 +357,8 @@ export const dimTheme: Theme = { textVeryLight: dimPalette.contrast_400, replyLine: dimPalette.contrast_200, replyLineDot: dimPalette.contrast_200, - unreadNotifBg: `hsl(211, 48%, 17%)`, - unreadNotifBorder: `hsl(211, 48%, 30%)`, + unreadNotifBg: dimPalette.primary_975, + unreadNotifBorder: dimPalette.primary_900, postCtrl: dimPalette.contrast_500, brandText: dimPalette.primary_500, emptyStateIcon: dimPalette.contrast_300, diff --git a/src/locale/locales/ca/messages.po b/src/locale/locales/ca/messages.po index 9f7f853c59..927599ab43 100644 --- a/src/locale/locales/ca/messages.po +++ b/src/locale/locales/ca/messages.po @@ -91,7 +91,7 @@ msgid "A new version of the app is available. Please update to continue using th msgstr "Hi ha una nova versió d'aquesta aplicació. Actualitza-la per continuar." #: src/view/com/util/ViewHeader.tsx:83 -#: src/view/screens/Search/Search.tsx:624 +#: src/view/screens/Search/Search.tsx:647 msgid "Access navigation links and settings" msgstr "Accedeix als enllaƧos de navegació i configuració" @@ -142,6 +142,7 @@ msgstr "Compte desbloquejat" msgid "Account unmuted" msgstr "Compte no silenciat" +#: src/components/dialogs/MutedWords.tsx:147 #: src/view/com/auth/onboarding/RecommendedFeedsItem.tsx:150 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -183,14 +184,22 @@ msgstr "Afegeix detalls" msgid "Add details to report" msgstr "Afegeix detalls a l'informe" -#: src/view/com/composer/Composer.tsx:446 +#: src/view/com/composer/Composer.tsx:453 msgid "Add link card" msgstr "Afegeix una targeta a l'enllaƧ" -#: src/view/com/composer/Composer.tsx:451 +#: src/view/com/composer/Composer.tsx:458 msgid "Add link card:" msgstr "Afegeix una targeta a l'enllaƧ:" +#: src/components/dialogs/MutedWords.tsx:140 +msgid "Add mute word for configured settings" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:74 +msgid "Add muted words and tags" +msgstr "" + #: src/view/com/modals/ChangeHandle.tsx:417 msgid "Add the following DNS record to your domain:" msgstr "Afegeix el següent registre DNS al teu domini:" @@ -310,7 +319,7 @@ msgstr "Configuració de la contrasenya d'aplicació" msgid "App Passwords" msgstr "Contrasenyes de l'aplicació" -#: src/view/com/util/forms/PostDropdownBtn.tsx:279 +#: src/view/com/util/forms/PostDropdownBtn.tsx:295 msgid "Appeal content warning" msgstr "AdvertĆØncia d'apelĀ·lació sobre el contingut" @@ -337,15 +346,16 @@ msgstr "AparenƧa" msgid "Are you sure you want to delete the app password \"{name}\"?" msgstr "Confirmes que vols eliminar la contrasenya de l'aplicació \"{name}\"?" -#: src/view/com/composer/Composer.tsx:143 +#: src/view/com/composer/Composer.tsx:150 msgid "Are you sure you'd like to discard this draft?" msgstr "Confirmes que vols descartar aquest esborrany?" +#: src/components/dialogs/MutedWords.tsx:233 #: src/view/screens/ProfileList.tsx:365 msgid "Are you sure?" msgstr "Ho confirmes?" -#: src/view/com/util/forms/PostDropdownBtn.tsx:262 +#: src/view/com/util/forms/PostDropdownBtn.tsx:278 msgid "Are you sure? This cannot be undone." msgstr "Ho confirmes? Aquesta acció no es pot desfer." @@ -367,15 +377,15 @@ msgstr "Nuesa artĆ­stica o no eròtica." #: src/view/com/auth/login/LoginForm.tsx:259 #: src/view/com/auth/login/SetNewPasswordForm.tsx:179 #: src/view/com/modals/report/InputIssueDetails.tsx:46 -#: src/view/com/post-thread/PostThread.tsx:471 -#: src/view/com/post-thread/PostThread.tsx:521 -#: src/view/com/post-thread/PostThread.tsx:529 +#: src/view/com/post-thread/PostThread.tsx:472 +#: src/view/com/post-thread/PostThread.tsx:522 +#: src/view/com/post-thread/PostThread.tsx:530 #: src/view/com/profile/ProfileHeader.tsx:649 #: src/view/com/util/ViewHeader.tsx:81 msgid "Back" msgstr "Endarrere" -#: src/view/com/post-thread/PostThread.tsx:479 +#: src/view/com/post-thread/PostThread.tsx:480 msgctxt "action" msgid "Back" msgstr "Endarrere" @@ -423,7 +433,7 @@ msgstr "Bloqueja la llista" msgid "Blocked" msgstr "Bloquejada" -#: src/view/screens/Moderation.tsx:123 +#: src/view/screens/Moderation.tsx:142 msgid "Blocked accounts" msgstr "Comptes bloquejats" @@ -482,7 +492,7 @@ msgstr "Bluesky Ć©s pĆŗblic." msgid "Bluesky uses invites to build a healthier community. If you don't know anybody with an invite, you can sign up for the waitlist and we'll send one soon." msgstr "Bluesky utilitza les invitacions per construir una comunitat saludable. Si no coneixes ningĆŗ amb invitacions, pots apuntar-te a la llista d'espera i te n'enviarem una aviat." -#: src/view/screens/Moderation.tsx:226 +#: src/view/screens/Moderation.tsx:245 msgid "Bluesky will not show your profile and posts to logged-out users. Other apps may not honor this request. This does not make your account private." msgstr "Bluesky no mostrarĆ  el teu perfil ni les publicacions als usuaris que no estiguin registrats. Altres aplicacions poden no seguir aquesta demanda. Això no fa que el teu compte sigui privat." @@ -534,8 +544,8 @@ msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must msgstr "NomĆ©s pot tenir lletres, nĆŗmeros, espais, guions i guions baixos. Ha de tenir almenys 4 carĆ cters i no mĆ©s de 32." #: src/components/Prompt.tsx:91 -#: src/view/com/composer/Composer.tsx:300 -#: src/view/com/composer/Composer.tsx:305 +#: src/view/com/composer/Composer.tsx:307 +#: src/view/com/composer/Composer.tsx:312 #: src/view/com/modals/ChangeEmail.tsx:218 #: src/view/com/modals/ChangeEmail.tsx:220 #: src/view/com/modals/ChangePassword.tsx:265 @@ -549,7 +559,7 @@ msgstr "NomĆ©s pot tenir lletres, nĆŗmeros, espais, guions i guions baixos. Ha d #: src/view/com/modals/VerifyEmail.tsx:247 #: src/view/com/modals/VerifyEmail.tsx:253 #: src/view/com/modals/Waitlist.tsx:142 -#: src/view/screens/Search/Search.tsx:693 +#: src/view/screens/Search/Search.tsx:716 #: src/view/shell/desktop/Search.tsx:238 msgid "Cancel" msgstr "CancelĀ·la" @@ -704,7 +714,7 @@ msgid "Clear all storage data (restart after this)" msgstr "Esborra totes les dades emmagatzemades (i desprĆ©s reinicia)" #: src/view/com/util/forms/SearchInput.tsx:88 -#: src/view/screens/Search/Search.tsx:674 +#: src/view/screens/Search/Search.tsx:697 msgid "Clear search query" msgstr "Esborra la cerca" @@ -712,6 +722,11 @@ msgstr "Esborra la cerca" msgid "click here" msgstr "clica aquĆ­" +#: src/components/RichText.tsx:189 +#: src/components/TagMenu/index.web.tsx:125 +msgid "Click here to open tag menu for {tag}" +msgstr "" + #: src/screens/Onboarding/index.tsx:35 msgid "Climate" msgstr "" @@ -742,11 +757,15 @@ msgstr "Tanca la imatge" msgid "Close image viewer" msgstr "Tanca el visor d'imatges" -#: src/view/shell/index.web.tsx:49 +#: src/view/shell/index.web.tsx:51 msgid "Close navigation footer" msgstr "Tanca el peu de la navegació" -#: src/view/shell/index.web.tsx:50 +#: src/components/TagMenu/index.tsx:266 +msgid "Close this dialog" +msgstr "" + +#: src/view/shell/index.web.tsx:52 msgid "Closes bottom navigation bar" msgstr "Tanca la barra de navegació inferior" @@ -754,7 +773,7 @@ msgstr "Tanca la barra de navegació inferior" msgid "Closes password update alert" msgstr "Tanca l'alerta d'actualització de contrasenya" -#: src/view/com/composer/Composer.tsx:302 +#: src/view/com/composer/Composer.tsx:309 msgid "Closes post composer and discards post draft" msgstr "Tanca l'editor de la publicació i descarta l'esborrany" @@ -787,7 +806,7 @@ msgstr "" msgid "Complete the challenge" msgstr "" -#: src/view/com/composer/Composer.tsx:417 +#: src/view/com/composer/Composer.tsx:424 msgid "Compose posts up to {MAX_GRAPHEME_LENGTH} characters in length" msgstr "Crea publicacions de fins a {MAX_GRAPHEME_LENGTH} carĆ cters" @@ -851,7 +870,7 @@ msgstr "Connectant…" msgid "Contact support" msgstr "Contacta amb suport" -#: src/view/screens/Moderation.tsx:81 +#: src/view/screens/Moderation.tsx:83 msgid "Content filtering" msgstr "Filtre de contingut" @@ -917,7 +936,7 @@ msgstr "NĆŗmero de versió copiat en memòria" #: src/view/com/modals/AddAppPasswords.tsx:76 #: src/view/com/modals/InviteCodes.tsx:152 -#: src/view/com/util/forms/PostDropdownBtn.tsx:141 +#: src/view/com/util/forms/PostDropdownBtn.tsx:143 msgid "Copied to clipboard" msgstr "Copiat en memòria" @@ -933,7 +952,7 @@ msgstr "Copia" msgid "Copy link to list" msgstr "Copia l'enllaƧ a la llista" -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 msgid "Copy link to post" msgstr "Copia l'enllaƧ a la publicació" @@ -941,7 +960,7 @@ msgstr "Copia l'enllaƧ a la publicació" msgid "Copy link to profile" msgstr "Copia l'enllaƧ al perfil" -#: src/view/com/util/forms/PostDropdownBtn.tsx:168 +#: src/view/com/util/forms/PostDropdownBtn.tsx:170 msgid "Copy post text" msgstr "Copia el text de la publicació" @@ -997,7 +1016,7 @@ msgstr "Creat per <0/>" msgid "Created by you" msgstr "Creat per tu" -#: src/view/com/composer/Composer.tsx:448 +#: src/view/com/composer/Composer.tsx:455 msgid "Creates a card with a thumbnail. The card links to {url}" msgstr "Crea una targeta amb una minuatura. La targeta enllaƧa a {url}" @@ -1074,11 +1093,11 @@ msgstr "Elimina el meu compte" msgid "Delete My Account…" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:257 +#: src/view/com/util/forms/PostDropdownBtn.tsx:273 msgid "Delete post" msgstr "Elimina la publicació" -#: src/view/com/util/forms/PostDropdownBtn.tsx:261 +#: src/view/com/util/forms/PostDropdownBtn.tsx:277 msgid "Delete this post?" msgstr "Vols eliminar aquesta publicació?" @@ -1105,7 +1124,7 @@ msgstr "Descripció" #~ msgid "Developer Tools" #~ msgstr "Eines de desenvolupador" -#: src/view/com/composer/Composer.tsx:211 +#: src/view/com/composer/Composer.tsx:218 msgid "Did you want to say anything?" msgstr "Vols dir alguna cosa?" @@ -1113,15 +1132,15 @@ msgstr "Vols dir alguna cosa?" msgid "Dim" msgstr "" -#: src/view/com/composer/Composer.tsx:144 +#: src/view/com/composer/Composer.tsx:151 msgid "Discard" msgstr "Descarta" -#: src/view/com/composer/Composer.tsx:138 +#: src/view/com/composer/Composer.tsx:145 msgid "Discard draft" msgstr "Descarta l'esborrany" -#: src/view/screens/Moderation.tsx:207 +#: src/view/screens/Moderation.tsx:226 msgid "Discourage apps from showing my account to logged-out users" msgstr "Evita que les aplicacions mostrin el meu compte als usuaris no connectats" @@ -1200,7 +1219,7 @@ msgstr "" msgid "Download CAR file" msgstr "" -#: src/view/com/composer/text-input/TextInput.web.tsx:247 +#: src/view/com/composer/text-input/TextInput.web.tsx:249 msgid "Drop to add images" msgstr "" @@ -1272,6 +1291,7 @@ msgstr "Edita el perfil" msgid "Edit Profile" msgstr "Edita el perfil" +#: src/view/com/home/HomeHeaderLayout.web.tsx:59 #: src/view/screens/Feeds.tsx:355 msgid "Edit Saved Feeds" msgstr "Edita els meus canals guardats" @@ -1354,6 +1374,11 @@ msgstr "Fi del canal" msgid "Enter a name for this App Password" msgstr "Posa un nom a aquesta contrasenya d'aplicació" +#: src/components/dialogs/MutedWords.tsx:87 +#: src/components/dialogs/MutedWords.tsx:88 +msgid "Enter a word or tag" +msgstr "" + #: src/view/com/modals/VerifyEmail.tsx:105 msgid "Enter Confirmation Code" msgstr "Entra el codi de confirmació" @@ -1407,7 +1432,7 @@ msgstr "Introdueix el teu usuari i contrasenya" msgid "Error receiving captcha response." msgstr "" -#: src/view/screens/Search/Search.tsx:109 +#: src/view/screens/Search/Search.tsx:110 msgid "Error:" msgstr "Error:" @@ -1478,7 +1503,7 @@ msgstr "No s'ha pogut crear la contrasenya d'aplicació" msgid "Failed to create the list. Check your internet connection and try again." msgstr "No s'ha pogut crear la llista. Comprova la teva connexió a internet i torna-ho a provar." -#: src/view/com/util/forms/PostDropdownBtn.tsx:108 +#: src/view/com/util/forms/PostDropdownBtn.tsx:110 msgid "Failed to delete post, please try again" msgstr "No s'ha pogut esborrar la publicació, torna-ho a provar" @@ -1500,8 +1525,8 @@ msgid "Feed offline" msgstr "Canal fora de lĆ­nia" #: src/view/com/feeds/FeedPage.tsx:143 -msgid "Feed Preferences" -msgstr "PreferĆØncies del canal" +#~ msgid "Feed Preferences" +#~ msgstr "PreferĆØncies del canal" #: src/view/shell/desktop/RightNav.tsx:61 #: src/view/shell/Drawer.tsx:311 @@ -1541,11 +1566,11 @@ msgstr "" msgid "Find accounts to follow" msgstr "Troba comptes per seguir" -#: src/view/screens/Search/Search.tsx:439 +#: src/view/screens/Search/Search.tsx:440 msgid "Find users on Bluesky" msgstr "Troba usuaris a Bluesky" -#: src/view/screens/Search/Search.tsx:437 +#: src/view/screens/Search/Search.tsx:438 msgid "Find users with the search tool on the right" msgstr "Troba usuaris amb l'eina de cerca de la dreta" @@ -1646,6 +1671,7 @@ msgid "Following {0}" msgstr "Seguint {0}" #: src/Navigation.tsx:248 +#: src/view/com/home/HomeHeaderLayout.web.tsx:45 #: src/view/com/home/HomeHeaderLayoutMobile.tsx:83 #: src/view/screens/PreferencesFollowingFeed.tsx:104 #: src/view/screens/Settings/index.tsx:543 @@ -1685,7 +1711,7 @@ msgstr "He oblidat la contrasenya" msgid "Forgot Password" msgstr "He oblidat la contrasenya" -#: src/view/com/posts/FeedItem.tsx:187 +#: src/view/com/posts/FeedItem.tsx:189 msgctxt "from-feed" msgid "From <0/>" msgstr "De <0/>" @@ -1718,7 +1744,7 @@ msgstr "Ves enrere" msgid "Go back to previous step" msgstr "" -#: src/view/screens/Search/Search.tsx:724 +#: src/view/screens/Search/Search.tsx:747 #: src/view/shell/desktop/Search.tsx:262 msgid "Go to @{queryMaybeHandle}" msgstr "VĆ©s a @{queryMaybeHandle}" @@ -1735,6 +1761,10 @@ msgstr "Ves al següent" msgid "Handle" msgstr "Identificador" +#: src/components/RichText.tsx:188 +msgid "Hashtag: {tag}" +msgstr "" + #: src/view/com/auth/create/CreateAccount.tsx:208 msgid "Having trouble?" msgstr "Tens problemes?" @@ -1773,7 +1803,7 @@ msgctxt "action" msgid "Hide" msgstr "Amaga" -#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +#: src/view/com/util/forms/PostDropdownBtn.tsx:232 msgid "Hide post" msgstr "Amaga l'entrada" @@ -1782,7 +1812,7 @@ msgstr "Amaga l'entrada" msgid "Hide the content" msgstr "Amaga el contingut" -#: src/view/com/util/forms/PostDropdownBtn.tsx:220 +#: src/view/com/util/forms/PostDropdownBtn.tsx:236 msgid "Hide this post?" msgstr "Vols amagar aquesta entrada?" @@ -1936,7 +1966,7 @@ msgstr "Introdueix la teva contrasenya" msgid "Input your user handle" msgstr "Introdueix el teu identificador d'usuari" -#: src/view/com/post-thread/PostThreadItem.tsx:224 +#: src/view/com/post-thread/PostThreadItem.tsx:226 msgid "Invalid or unsupported post record" msgstr "Registre de publicació no vĆ lid o no admĆØs" @@ -2038,7 +2068,7 @@ msgstr "MĆ©s informació" msgid "Learn more about this warning" msgstr "MĆ©s informació d'aquesta advertĆØncia" -#: src/view/screens/Moderation.tsx:243 +#: src/view/screens/Moderation.tsx:262 msgid "Learn more about what is public on Bluesky." msgstr "MĆ©s informació sobre quĆØ Ć©s pĆŗblic a Bluesky." @@ -2118,7 +2148,7 @@ msgstr "li ha agradat la teva publicació" msgid "Likes" msgstr "M'agrades" -#: src/view/com/post-thread/PostThreadItem.tsx:181 +#: src/view/com/post-thread/PostThreadItem.tsx:183 msgid "Likes on this post" msgstr "M'agrades a aquesta publicació" @@ -2175,7 +2205,7 @@ msgstr "Carrega mĆ©s publicacions" msgid "Load new notifications" msgstr "Carrega noves notificacions" -#: src/view/com/feeds/FeedPage.tsx:181 +#: src/view/com/feeds/FeedPage.tsx:115 #: src/view/screens/Profile.tsx:440 #: src/view/screens/ProfileFeed.tsx:495 #: src/view/screens/ProfileList.tsx:681 @@ -2201,7 +2231,7 @@ msgstr "Registre" msgid "Log out" msgstr "" -#: src/view/screens/Moderation.tsx:136 +#: src/view/screens/Moderation.tsx:155 msgid "Logged-out visibility" msgstr "Visibilitat pels usuaris no connectats" @@ -2216,6 +2246,10 @@ msgstr "Accedeix a un compte que no estĆ  llistat" msgid "Make sure this is where you intend to go!" msgstr "Assegura't que Ć©s aquĆ­ on vols anar!" +#: src/components/dialogs/MutedWords.tsx:71 +msgid "Manage your muted words and tags" +msgstr "" + #: src/view/com/auth/create/Step2.tsx:118 msgid "May not be longer than 253 characters" msgstr "" @@ -2237,7 +2271,7 @@ msgid "Mentioned users" msgstr "Usuaris mencionats" #: src/view/com/util/ViewHeader.tsx:81 -#: src/view/screens/Search/Search.tsx:623 +#: src/view/screens/Search/Search.tsx:646 msgid "Menu" msgstr "MenĆŗ" @@ -2250,7 +2284,7 @@ msgid "Message from server: {0}" msgstr "Missatge del servidor: {0}" #: src/Navigation.tsx:115 -#: src/view/screens/Moderation.tsx:64 +#: src/view/screens/Moderation.tsx:66 #: src/view/screens/Settings/index.tsx:625 #: src/view/shell/desktop/LeftNav.tsx:397 #: src/view/shell/Drawer.tsx:511 @@ -2281,7 +2315,7 @@ msgstr "S'ha creat la llista de moderació" msgid "Moderation list updated" msgstr "S'ha actualitzat la llista de moderació" -#: src/view/screens/Moderation.tsx:95 +#: src/view/screens/Moderation.tsx:114 msgid "Moderation lists" msgstr "Llistes de moderació" @@ -2308,7 +2342,7 @@ msgstr "MĆ©s canals" msgid "More options" msgstr "MĆ©s opcions" -#: src/view/com/util/forms/PostDropdownBtn.tsx:299 +#: src/view/com/util/forms/PostDropdownBtn.tsx:315 msgid "More post options" msgstr "MĆ©s opcions de publicació" @@ -2320,6 +2354,14 @@ msgstr "Respostes amb mĆ©s m'agrada primer" msgid "Must be at least 3 characters" msgstr "" +#: src/components/TagMenu/index.tsx:253 +msgid "Mute" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:91 +msgid "Mute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:327 msgid "Mute Account" msgstr "Silenciar el compte" @@ -2328,6 +2370,18 @@ msgstr "Silenciar el compte" msgid "Mute accounts" msgstr "Silencia els comptes" +#: src/components/TagMenu/index.tsx:211 +msgid "Mute all {tag} posts" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:131 +msgid "Mute in tags only" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:116 +msgid "Mute in text & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:491 msgid "Mute list" msgstr "Silencia la llista" @@ -2340,15 +2394,27 @@ msgstr "Vols silenciar aquests comptes?" msgid "Mute this List" msgstr "Silencia aquesta llista" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/dialogs/MutedWords.tsx:109 +msgid "Mute this word in post text and tags" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:124 +msgid "Mute this word in tags only" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Mute thread" msgstr "Silencia el fil de debat" +#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +msgid "Mute words & tags" +msgstr "" + #: src/view/com/lists/ListCard.tsx:102 msgid "Muted" msgstr "Silenciada" -#: src/view/screens/Moderation.tsx:109 +#: src/view/screens/Moderation.tsx:128 msgid "Muted accounts" msgstr "Comptes silenciats" @@ -2361,6 +2427,10 @@ msgstr "Comptes silenciats" msgid "Muted accounts have their posts removed from your feed and from your notifications. Mutes are completely private." msgstr "Les publicacions dels comptes silenciats seran eliminats del teu canal i de les teves notificacions. Silenciar comptes Ć©s completament privat." +#: src/view/screens/Moderation.tsx:100 +msgid "Muted words & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:277 msgid "Muting is private. Muted accounts can interact with you, but you will not see their posts or receive notifications from them." msgstr "Silenciar Ć©s privat. Els comptes silenciats poden interactuar amb tu, però tu no veurĆ s les seves publicacions ni rebrĆ s notificacions seves." @@ -2424,6 +2494,10 @@ msgstr "No perdis mai accĆ©s als teus seguidors ni a les teves dades." msgid "Never lose access to your followers or data." msgstr "" +#: src/components/dialogs/MutedWords.tsx:244 +msgid "Nevermind" +msgstr "" + #: src/view/screens/Lists.tsx:76 msgctxt "action" msgid "New" @@ -2445,7 +2519,7 @@ msgstr "Nova contrasenya" msgid "New Password" msgstr "" -#: src/view/com/feeds/FeedPage.tsx:192 +#: src/view/com/feeds/FeedPage.tsx:126 msgctxt "action" msgid "New post" msgstr "Nova publicació" @@ -2534,8 +2608,8 @@ msgid "No results found for \"{query}\"" msgstr "No s'han trobat resultats per \"{query}\"" #: src/view/com/modals/ListAddRemoveUsers.tsx:127 -#: src/view/screens/Search/Search.tsx:280 -#: src/view/screens/Search/Search.tsx:308 +#: src/view/screens/Search/Search.tsx:281 +#: src/view/screens/Search/Search.tsx:309 msgid "No results found for {query}" msgstr "No s'han trobat resultats per {query}" @@ -2561,7 +2635,7 @@ msgstr "No s'ha trobat" msgid "Not right now" msgstr "Ara mateix no" -#: src/view/screens/Moderation.tsx:233 +#: src/view/screens/Moderation.tsx:252 msgid "Note: Bluesky is an open and public network. This setting only limits the visibility of your content on the Bluesky app and website, and other apps may not respect this setting. Your content may still be shown to logged-out users by other apps and websites." msgstr "Nota: Bluesky Ć©s una xarxa oberta i pĆŗblica. Aquesta configuració tan sols limita el teu contingut a l'aplicació de Bluesky i a la web, altres aplicacions poden no respectar-ho. El teu contingut pot ser mostrat a usuaris no connectats per altres aplicacions i webs." @@ -2599,7 +2673,7 @@ msgstr "Respostes mĆ©s antigues primer" msgid "Onboarding reset" msgstr "Restableix la incorporació" -#: src/view/com/composer/Composer.tsx:375 +#: src/view/com/composer/Composer.tsx:382 msgid "One or more images is missing alt text." msgstr "Falta el text alternatiu a una o mĆ©s imatges." @@ -2616,8 +2690,12 @@ msgstr "Ostres!" msgid "Open" msgstr "" -#: src/view/com/composer/Composer.tsx:470 -#: src/view/com/composer/Composer.tsx:471 +#: src/view/screens/Moderation.tsx:75 +msgid "Open content filtering settings" +msgstr "" + +#: src/view/com/composer/Composer.tsx:477 +#: src/view/com/composer/Composer.tsx:478 msgid "Open emoji picker" msgstr "Obre el selector d'emojis" @@ -2625,6 +2703,10 @@ msgstr "Obre el selector d'emojis" msgid "Open links with in-app browser" msgstr "Obre els enllaƧos al navegador de l'aplicació" +#: src/view/screens/Moderation.tsx:92 +msgid "Open muted words settings" +msgstr "" + #: src/view/com/home/HomeHeaderLayoutMobile.tsx:49 msgid "Open navigation" msgstr "Obre la navegació" @@ -2701,6 +2783,7 @@ msgstr "Obre la configuració de la moderació" msgid "Opens password reset form" msgstr "Obre el formulari de restabliment de la contrasenya" +#: src/view/com/home/HomeHeaderLayout.web.tsx:60 #: src/view/screens/Feeds.tsx:356 msgid "Opens screen to edit Saved Feeds" msgstr "Obre pantalla per editar els canals desats" @@ -2879,7 +2962,7 @@ msgstr "Digues-nos per quĆØ creus que s'ha aplicat incorrectament l'advertĆØncia msgid "Please Verify Your Email" msgstr "Verifica el teu correu" -#: src/view/com/composer/Composer.tsx:215 +#: src/view/com/composer/Composer.tsx:222 msgid "Please wait for your link card to finish loading" msgstr "Espera que es generi la targeta de l'enllaƧ" @@ -2891,8 +2974,8 @@ msgstr "" msgid "Porn" msgstr "Pornografia" -#: src/view/com/composer/Composer.tsx:350 -#: src/view/com/composer/Composer.tsx:358 +#: src/view/com/composer/Composer.tsx:357 +#: src/view/com/composer/Composer.tsx:365 msgctxt "action" msgid "Post" msgstr "Publica" @@ -2908,7 +2991,7 @@ msgstr "Publicació" #~ msgid "Post" #~ msgstr "Publicació" -#: src/view/com/post-thread/PostThreadItem.tsx:173 +#: src/view/com/post-thread/PostThreadItem.tsx:175 msgid "Post by {0}" msgstr "Publicació per {0}" @@ -2918,11 +3001,11 @@ msgstr "Publicació per {0}" msgid "Post by @{0}" msgstr "Publicació per @{0}" -#: src/view/com/util/forms/PostDropdownBtn.tsx:88 +#: src/view/com/util/forms/PostDropdownBtn.tsx:90 msgid "Post deleted" msgstr "Publicació eliminada" -#: src/view/com/post-thread/PostThread.tsx:461 +#: src/view/com/post-thread/PostThread.tsx:462 msgid "Post hidden" msgstr "Publicació oculta" @@ -2934,14 +3017,22 @@ msgstr "Idioma de la publicació" msgid "Post Languages" msgstr "Idiomes de les publicacions" -#: src/view/com/post-thread/PostThread.tsx:513 +#: src/view/com/post-thread/PostThread.tsx:514 msgid "Post not found" msgstr "Publicació no trobada" +#: src/components/TagMenu/index.tsx:257 +msgid "posts" +msgstr "" + #: src/view/screens/Profile.tsx:180 msgid "Posts" msgstr "Publicacions" +#: src/components/dialogs/MutedWords.tsx:77 +msgid "Posts can be muted based on their text, their tags, or both." +msgstr "" + #: src/view/com/posts/FeedErrorMessage.tsx:64 msgid "Posts hidden" msgstr "Publicacions amagades" @@ -3006,11 +3097,11 @@ msgstr "Llistes d'usuaris per silenciar o bloquejar en massa, pĆŗbliques i per c msgid "Public, shareable lists which can drive feeds." msgstr "Llistes que poden nodrir canals, pĆŗbliques i per compartir." -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish post" msgstr "Publica" -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish reply" msgstr "Publica la resposta" @@ -3048,6 +3139,7 @@ msgstr "Canals recomanats" msgid "Recommended Users" msgstr "Usuaris recomanats" +#: src/components/dialogs/MutedWords.tsx:249 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/SelfLabel.tsx:83 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -3085,6 +3177,10 @@ msgstr "Elimina la imatge" msgid "Remove image preview" msgstr "Elimina la visualització prĆØvia de la imatge" +#: src/components/dialogs/MutedWords.tsx:294 +msgid "Remove mute word from your list" +msgstr "" + #: src/view/com/modals/Repost.tsx:47 msgid "Remove repost" msgstr "Elimina la republicació" @@ -3119,7 +3215,7 @@ msgstr "Respostes" msgid "Replies to this thread are disabled" msgstr "Les respostes a aquest fil de debat estan deshabilitades" -#: src/view/com/composer/Composer.tsx:348 +#: src/view/com/composer/Composer.tsx:355 msgctxt "action" msgid "Reply" msgstr "Respon" @@ -3129,7 +3225,7 @@ msgid "Reply Filters" msgstr "Filtres de resposta" #: src/view/com/post/Post.tsx:167 -#: src/view/com/posts/FeedItem.tsx:285 +#: src/view/com/posts/FeedItem.tsx:287 msgctxt "description" msgid "Reply to <0/>" msgstr "Resposta a <0/>" @@ -3151,7 +3247,7 @@ msgid "Report List" msgstr "Informa de la llista" #: src/view/com/modals/report/SendReportButton.tsx:37 -#: src/view/com/util/forms/PostDropdownBtn.tsx:239 +#: src/view/com/util/forms/PostDropdownBtn.tsx:255 msgid "Report post" msgstr "Informa de la publicació" @@ -3180,7 +3276,7 @@ msgstr "Republica o cita la publicació" msgid "Reposted By" msgstr "" -#: src/view/com/posts/FeedItem.tsx:205 +#: src/view/com/posts/FeedItem.tsx:207 msgid "Reposted by {0}" msgstr "" @@ -3188,7 +3284,7 @@ msgstr "" #~ msgid "Reposted by {0})" #~ msgstr "Republicada per {0}" -#: src/view/com/posts/FeedItem.tsx:222 +#: src/view/com/posts/FeedItem.tsx:224 msgid "Reposted by <0/>" msgstr "Republicada per <0/>" @@ -3196,7 +3292,7 @@ msgstr "Republicada per <0/>" msgid "reposted your post" msgstr "ha republicat la teva publicació" -#: src/view/com/post-thread/PostThreadItem.tsx:186 +#: src/view/com/post-thread/PostThreadItem.tsx:188 msgid "Reposts of this post" msgstr "Republicacions d'aquesta publicació" @@ -3347,9 +3443,9 @@ msgstr "DesplaƧa't cap a dalt" #: src/view/com/modals/ListAddRemoveUsers.tsx:75 #: src/view/com/util/forms/SearchInput.tsx:67 #: src/view/com/util/forms/SearchInput.tsx:79 -#: src/view/screens/Search/Search.tsx:418 -#: src/view/screens/Search/Search.tsx:645 -#: src/view/screens/Search/Search.tsx:663 +#: src/view/screens/Search/Search.tsx:419 +#: src/view/screens/Search/Search.tsx:668 +#: src/view/screens/Search/Search.tsx:686 #: src/view/shell/bottom-bar/BottomBar.tsx:159 #: src/view/shell/desktop/LeftNav.tsx:324 #: src/view/shell/desktop/Search.tsx:214 @@ -3359,11 +3455,19 @@ msgstr "DesplaƧa't cap a dalt" msgid "Search" msgstr "Cerca" -#: src/view/screens/Search/Search.tsx:712 +#: src/view/screens/Search/Search.tsx:735 #: src/view/shell/desktop/Search.tsx:255 msgid "Search for \"{query}\"" msgstr "Cerca per \"{query}\"" +#: src/components/TagMenu/index.tsx:145 +msgid "Search for all posts by @{authorHandle} with tag {tag}" +msgstr "" + +#: src/components/TagMenu/index.tsx:90 +msgid "Search for all posts with tag {tag}" +msgstr "" + #: src/view/com/auth/LoggedOut.tsx:104 #: src/view/com/auth/LoggedOut.tsx:105 #: src/view/com/modals/ListAddRemoveUsers.tsx:70 @@ -3374,6 +3478,22 @@ msgstr "Cerca usuaris" msgid "Security Step Required" msgstr "Es requereix un pas de seguretat" +#: src/components/TagMenu/index.web.tsx:50 +msgid "See {truncatedTag} posts" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:67 +msgid "See {truncatedTag} posts by user" +msgstr "" + +#: src/components/TagMenu/index.tsx:128 +msgid "See <0>{tag} posts" +msgstr "" + +#: src/components/TagMenu/index.tsx:189 +msgid "See <0>{tag} posts by this user" +msgstr "" + #: src/view/screens/SavedFeeds.tsx:163 msgid "See this guide" msgstr "Consulta aquesta guia" @@ -3583,7 +3703,7 @@ msgid "Share" msgstr "Comparteix" #: src/view/com/profile/ProfileHeader.tsx:295 -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 #: src/view/screens/ProfileList.tsx:418 msgid "Share" msgstr "Comparteix" @@ -3616,9 +3736,9 @@ msgstr "Mostra els incrustats de {0}" msgid "Show follows similar to {0}" msgstr "Mostra seguidors semblants a {0}" -#: src/view/com/post-thread/PostThreadItem.tsx:532 -#: src/view/com/post/Post.tsx:196 -#: src/view/com/posts/FeedItem.tsx:359 +#: src/view/com/post-thread/PostThreadItem.tsx:538 +#: src/view/com/post/Post.tsx:198 +#: src/view/com/posts/FeedItem.tsx:363 msgid "Show More" msgstr "Mostra mĆ©s" @@ -3786,7 +3906,7 @@ msgstr "" msgid "Something went wrong. Check your email and try again." msgstr "Alguna cosa ha fallat. Comprova el teu correu i torna-ho a provar." -#: src/App.native.tsx:61 +#: src/App.native.tsx:63 msgid "Sorry! Your session expired. Please log in again." msgstr "La teva sessió ha caducat. Torna a inciar-la." @@ -3844,7 +3964,7 @@ msgstr "" msgid "Subscribe to this list" msgstr "Subscriure's a la llista" -#: src/view/screens/Search/Search.tsx:373 +#: src/view/screens/Search/Search.tsx:374 msgid "Suggested Follows" msgstr "Usuaris suggerits per seguir" @@ -3888,6 +4008,14 @@ msgstr "Sistema" msgid "System log" msgstr "Registres del sistema" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "tag" +msgstr "" + +#: src/components/TagMenu/index.tsx:74 +msgid "Tag menu: {tag}" +msgstr "" + #: src/view/com/modals/crop-image/CropImage.web.tsx:112 msgid "Tall" msgstr "Alt" @@ -3911,6 +4039,10 @@ msgstr "Condicions" msgid "Terms of Service" msgstr "Condicions del servei" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "text" +msgstr "" + #: src/view/com/modals/AppealLabel.tsx:70 #: src/view/com/modals/report/InputIssueDetails.tsx:51 msgid "Text input field" @@ -3936,7 +4068,7 @@ msgstr "La polĆ­tica de drets d'autoria ha estat traslladada a <0/>" msgid "The following steps will help customize your Bluesky experience." msgstr "" -#: src/view/com/post-thread/PostThread.tsx:516 +#: src/view/com/post-thread/PostThread.tsx:517 msgid "The post may have been deleted." msgstr "Ɖs possible que la publicació s'hagi esborrat." @@ -4113,7 +4245,7 @@ msgstr "Aquesta llista estĆ  buida!" msgid "This name is already in use" msgstr "Aquest nom ja estĆ  en Ćŗs" -#: src/view/com/post-thread/PostThreadItem.tsx:123 +#: src/view/com/post-thread/PostThreadItem.tsx:125 msgid "This post has been deleted." msgstr "Aquesta publicació ha estat esborrada." @@ -4137,7 +4269,11 @@ msgstr "" msgid "This warning is only available for posts with media attached." msgstr "Aquesta advertĆØncia nomĆ©s estĆ  disponible per publicacions amb contingut adjuntat." -#: src/view/com/util/forms/PostDropdownBtn.tsx:221 +#: src/components/dialogs/MutedWords.tsx:236 +msgid "This will delete {0} from your muted words. You can always add it back later." +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:237 msgid "This will hide this post from your feeds." msgstr "Això amagarĆ  aquesta publicació dels teus canals." @@ -4154,6 +4290,10 @@ msgstr "Mode fils de debat" msgid "Threads Preferences" msgstr "PreferĆØncies dels fils de debat" +#: src/components/dialogs/MutedWords.tsx:95 +msgid "Toggle between muted word options." +msgstr "" + #: src/view/com/util/forms/DropdownButton.tsx:246 msgid "Toggle dropdown" msgstr "Commuta el menĆŗ desplegable" @@ -4162,9 +4302,9 @@ msgstr "Commuta el menĆŗ desplegable" msgid "Transformations" msgstr "Transformacions" -#: src/view/com/post-thread/PostThreadItem.tsx:679 -#: src/view/com/post-thread/PostThreadItem.tsx:681 -#: src/view/com/util/forms/PostDropdownBtn.tsx:154 +#: src/view/com/post-thread/PostThreadItem.tsx:685 +#: src/view/com/post-thread/PostThreadItem.tsx:687 +#: src/view/com/util/forms/PostDropdownBtn.tsx:156 msgid "Translate" msgstr "Tradueix" @@ -4233,15 +4373,24 @@ msgstr "No compleixes les condicions per crear un compte." msgid "Unlike" msgstr "DesfĆ©s el m'agrada" +#: src/components/TagMenu/index.tsx:253 #: src/view/screens/ProfileList.tsx:597 msgid "Unmute" msgstr "Deixa de silenciar" +#: src/components/TagMenu/index.web.tsx:90 +msgid "Unmute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:326 msgid "Unmute Account" msgstr "Deixa de silenciar el compte" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/TagMenu/index.tsx:210 +msgid "Unmute all {tag} posts" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Unmute thread" msgstr "Deixa de silenciar el fil de debat" @@ -4438,6 +4587,10 @@ msgstr "" msgid "We ran out of posts from your follows. Here's the latest from <0/>." msgstr "Ja no hi ha mĆ©s publicacions dels usuaris que segueixes. AquĆ­ n'hi ha altres de <0/>." +#: src/components/dialogs/MutedWords.tsx:161 +msgid "We recommend avoiding common words that appear in many posts, since it can result in no posts being shown." +msgstr "" + #: src/screens/Onboarding/StepAlgoFeeds/index.tsx:124 msgid "We recommend our \"Discover\" feed:" msgstr "" @@ -4466,7 +4619,11 @@ msgstr "Ens fa molta ilĀ·lusió que t'uneixis a nosaltres!" msgid "We're sorry, but we were unable to resolve this list. If this persists, please contact the list creator, @{handleOrDid}." msgstr "Ho sentim, però no hem pogut resoldre aquesta llista. Si això continua, posa't en contacte amb el creador de la llista, @{handleOrDid}." -#: src/view/screens/Search/Search.tsx:253 +#: src/components/dialogs/MutedWords.tsx:182 +msgid "We're sorry, but we weren't able to load your muted words at this time. Please try again." +msgstr "" + +#: src/view/screens/Search/Search.tsx:254 msgid "We're sorry, but your search could not be completed. Please try again in a few minutes." msgstr "Ens sap greu, però la teva cerca no s'ha pogut fer. Prova-ho d'aquĆ­ una estona." @@ -4490,7 +4647,7 @@ msgstr "Quin problema hi ha amb {collectionName}?" #~ msgstr "ĀæQuĆ© sigue?" #: src/view/com/auth/SplashScreen.tsx:59 -#: src/view/com/composer/Composer.tsx:279 +#: src/view/com/composer/Composer.tsx:286 msgid "What's up?" msgstr "QuĆØ hi ha de nou" @@ -4511,11 +4668,11 @@ msgstr "Qui hi pot respondre" msgid "Wide" msgstr "Amplada" -#: src/view/com/composer/Composer.tsx:415 +#: src/view/com/composer/Composer.tsx:422 msgid "Write post" msgstr "Escriu una publicació" -#: src/view/com/composer/Composer.tsx:278 +#: src/view/com/composer/Composer.tsx:285 #: src/view/com/composer/Prompt.tsx:33 msgid "Write your reply" msgstr "Escriu la teva resposta" @@ -4576,7 +4733,7 @@ msgstr "No tens cap canal desat!" msgid "You don't have any saved feeds." msgstr "No tens cap canal desat." -#: src/view/com/post-thread/PostThread.tsx:464 +#: src/view/com/post-thread/PostThread.tsx:465 msgid "You have blocked the author or you have been blocked by the author." msgstr "Has bloquejat l'autor o has estat bloquejat per ell." @@ -4616,6 +4773,10 @@ msgstr "Encara no has creat cap contrasenya d'aplicació. Pots fer-ho amb el bot msgid "You have not muted any accounts yet. To mute an account, go to their profile and selected \"Mute account\" from the menu on their account." msgstr "Encara no has silenciat cap compte. Per fer-ho, vĆ©s al seu perfil i selecciona \"Silencia compte\" en el menĆŗ del seu compte." +#: src/components/dialogs/MutedWords.tsx:202 +msgid "You haven't muted any words or tags yet" +msgstr "" + #: src/view/com/modals/ContentFilteringSettings.tsx:175 msgid "You must be 18 or older to enable adult content." msgstr "Has de tenir 18 anys o mĆ©s per habilitar el contingut per a adults." @@ -4624,11 +4785,11 @@ msgstr "Has de tenir 18 anys o mĆ©s per habilitar el contingut per a adults." msgid "You must be 18 years or older to enable adult content" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:127 +#: src/view/com/util/forms/PostDropdownBtn.tsx:129 msgid "You will no longer receive notifications for this thread" msgstr "Ja no rebrĆ s mĆ©s notificacions d'aquest debat" -#: src/view/com/util/forms/PostDropdownBtn.tsx:130 +#: src/view/com/util/forms/PostDropdownBtn.tsx:132 msgid "You will now receive notifications for this thread" msgstr "Ara rebrĆ s notificacions d'aquest debat" @@ -4718,11 +4879,15 @@ msgstr "El teu identificador complet serĆ  <0>@{0}" #~ msgid "Your invite codes are hidden when logged in using an App Password" #~ msgstr "Els teus codis d'invitació no es mostren quan has iniciat sessió amb una contrasenya d'aplicació" +#: src/components/dialogs/MutedWords.tsx:173 +msgid "Your muted words" +msgstr "" + #: src/view/com/modals/ChangePassword.tsx:155 msgid "Your password has been changed successfully!" msgstr "" -#: src/view/com/composer/Composer.tsx:267 +#: src/view/com/composer/Composer.tsx:274 msgid "Your post has been published" msgstr "S'ha publicat" @@ -4737,7 +4902,7 @@ msgstr "Les teves publicacions, m'agrades i bloquejos són pĆŗblics. Els comptes msgid "Your profile" msgstr "El teu perfil" -#: src/view/com/composer/Composer.tsx:266 +#: src/view/com/composer/Composer.tsx:273 msgid "Your reply has been published" msgstr "S'ha publicat a teva resposta" diff --git a/src/locale/locales/de/messages.po b/src/locale/locales/de/messages.po index a4b0a8cb3c..1c41880336 100644 --- a/src/locale/locales/de/messages.po +++ b/src/locale/locales/de/messages.po @@ -76,7 +76,7 @@ msgid "A new version of the app is available. Please update to continue using th msgstr "Eine neue Version der App ist verfügbar. Bitte aktualisiere die App, um sie weiter nutzen zu kƶnnen." #: src/view/com/util/ViewHeader.tsx:83 -#: src/view/screens/Search/Search.tsx:624 +#: src/view/screens/Search/Search.tsx:647 msgid "Access navigation links and settings" msgstr "" @@ -127,6 +127,7 @@ msgstr "" msgid "Account unmuted" msgstr "" +#: src/components/dialogs/MutedWords.tsx:147 #: src/view/com/auth/onboarding/RecommendedFeedsItem.tsx:150 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -168,14 +169,22 @@ msgstr "Details hinzufügen" msgid "Add details to report" msgstr "Details zum Report hinzufügen" -#: src/view/com/composer/Composer.tsx:446 +#: src/view/com/composer/Composer.tsx:453 msgid "Add link card" msgstr "Link-Karte hinzufügen" -#: src/view/com/composer/Composer.tsx:451 +#: src/view/com/composer/Composer.tsx:458 msgid "Add link card:" msgstr "Link-Karte hinzufügen:" +#: src/components/dialogs/MutedWords.tsx:140 +msgid "Add mute word for configured settings" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:74 +msgid "Add muted words and tags" +msgstr "" + #: src/view/com/modals/ChangeHandle.tsx:417 msgid "Add the following DNS record to your domain:" msgstr "Füge den folgenden DNS-Eintrag zu deiner Domain hinzu:" @@ -299,7 +308,7 @@ msgstr "" msgid "App Passwords" msgstr "App-Passwƶrter" -#: src/view/com/util/forms/PostDropdownBtn.tsx:279 +#: src/view/com/util/forms/PostDropdownBtn.tsx:295 msgid "Appeal content warning" msgstr "" @@ -323,15 +332,16 @@ msgstr "Erscheinungsbild" msgid "Are you sure you want to delete the app password \"{name}\"?" msgstr "Bist du sicher, dass du das App-Passwort \"{name}\" lƶschen mƶchtest?" -#: src/view/com/composer/Composer.tsx:143 +#: src/view/com/composer/Composer.tsx:150 msgid "Are you sure you'd like to discard this draft?" msgstr "Bist du sicher, dass du diesen Entwurf verwerfen mƶchtest?" +#: src/components/dialogs/MutedWords.tsx:233 #: src/view/screens/ProfileList.tsx:365 msgid "Are you sure?" msgstr "Bist du sicher?" -#: src/view/com/util/forms/PostDropdownBtn.tsx:262 +#: src/view/com/util/forms/PostDropdownBtn.tsx:278 msgid "Are you sure? This cannot be undone." msgstr "Bist du sicher? Dies kann nicht rückgƤngig gemacht werden." @@ -353,15 +363,15 @@ msgstr "Künstlerische oder nicht-erotische Nacktheit." #: src/view/com/auth/login/LoginForm.tsx:259 #: src/view/com/auth/login/SetNewPasswordForm.tsx:179 #: src/view/com/modals/report/InputIssueDetails.tsx:46 -#: src/view/com/post-thread/PostThread.tsx:471 -#: src/view/com/post-thread/PostThread.tsx:521 -#: src/view/com/post-thread/PostThread.tsx:529 +#: src/view/com/post-thread/PostThread.tsx:472 +#: src/view/com/post-thread/PostThread.tsx:522 +#: src/view/com/post-thread/PostThread.tsx:530 #: src/view/com/profile/ProfileHeader.tsx:649 #: src/view/com/util/ViewHeader.tsx:81 msgid "Back" msgstr "Zurück" -#: src/view/com/post-thread/PostThread.tsx:479 +#: src/view/com/post-thread/PostThread.tsx:480 msgctxt "action" msgid "Back" msgstr "" @@ -409,7 +419,7 @@ msgstr "" msgid "Blocked" msgstr "" -#: src/view/screens/Moderation.tsx:123 +#: src/view/screens/Moderation.tsx:142 msgid "Blocked accounts" msgstr "Blockierte Konten" @@ -468,7 +478,7 @@ msgstr "Bluesky ist ƶffentlich." msgid "Bluesky uses invites to build a healthier community. If you don't know anybody with an invite, you can sign up for the waitlist and we'll send one soon." msgstr "Bluesky nutzt Einladungen, um eine gesündere Community aufzubauen. Wenn du niemanden kennst, der eine Einladung hat, kannst du dich auf die Warteliste setzen lassen und wir schicken dir bald eine zu." -#: src/view/screens/Moderation.tsx:226 +#: src/view/screens/Moderation.tsx:245 msgid "Bluesky will not show your profile and posts to logged-out users. Other apps may not honor this request. This does not make your account private." msgstr "Bluesky zeigt dein Profil und deine BeitrƤge nicht für abgemeldete Nutzer an. Andere Apps kommen dieser Aufforderung mƶglicherweise nicht nach." @@ -520,8 +530,8 @@ msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must msgstr "Darf nur Buchstaben, Zahlen, Leerzeichen, Bindestriche und Unterstriche enthalten. Muss mindestens 4 Zeichen lang sein, darf aber nicht lƤnger als 32 Zeichen sein." #: src/components/Prompt.tsx:91 -#: src/view/com/composer/Composer.tsx:300 -#: src/view/com/composer/Composer.tsx:305 +#: src/view/com/composer/Composer.tsx:307 +#: src/view/com/composer/Composer.tsx:312 #: src/view/com/modals/ChangeEmail.tsx:218 #: src/view/com/modals/ChangeEmail.tsx:220 #: src/view/com/modals/ChangePassword.tsx:265 @@ -535,7 +545,7 @@ msgstr "Darf nur Buchstaben, Zahlen, Leerzeichen, Bindestriche und Unterstriche #: src/view/com/modals/VerifyEmail.tsx:247 #: src/view/com/modals/VerifyEmail.tsx:253 #: src/view/com/modals/Waitlist.tsx:142 -#: src/view/screens/Search/Search.tsx:693 +#: src/view/screens/Search/Search.tsx:716 #: src/view/shell/desktop/Search.tsx:238 msgid "Cancel" msgstr "Abbrechen" @@ -686,7 +696,7 @@ msgid "Clear all storage data (restart after this)" msgstr "Alle Speicherdaten lƶschen (danach neu starten)" #: src/view/com/util/forms/SearchInput.tsx:88 -#: src/view/screens/Search/Search.tsx:674 +#: src/view/screens/Search/Search.tsx:697 msgid "Clear search query" msgstr "Suchanfrage lƶschen" @@ -694,6 +704,11 @@ msgstr "Suchanfrage lƶschen" msgid "click here" msgstr "" +#: src/components/RichText.tsx:189 +#: src/components/TagMenu/index.web.tsx:125 +msgid "Click here to open tag menu for {tag}" +msgstr "" + #: src/screens/Onboarding/index.tsx:35 msgid "Climate" msgstr "" @@ -724,11 +739,15 @@ msgstr "Bild schließen" msgid "Close image viewer" msgstr "" -#: src/view/shell/index.web.tsx:49 +#: src/view/shell/index.web.tsx:51 msgid "Close navigation footer" msgstr "" -#: src/view/shell/index.web.tsx:50 +#: src/components/TagMenu/index.tsx:266 +msgid "Close this dialog" +msgstr "" + +#: src/view/shell/index.web.tsx:52 msgid "Closes bottom navigation bar" msgstr "" @@ -736,7 +755,7 @@ msgstr "" msgid "Closes password update alert" msgstr "" -#: src/view/com/composer/Composer.tsx:302 +#: src/view/com/composer/Composer.tsx:309 msgid "Closes post composer and discards post draft" msgstr "" @@ -769,7 +788,7 @@ msgstr "" msgid "Complete the challenge" msgstr "" -#: src/view/com/composer/Composer.tsx:417 +#: src/view/com/composer/Composer.tsx:424 msgid "Compose posts up to {MAX_GRAPHEME_LENGTH} characters in length" msgstr "" @@ -833,7 +852,7 @@ msgstr "Verbinden..." msgid "Contact support" msgstr "" -#: src/view/screens/Moderation.tsx:81 +#: src/view/screens/Moderation.tsx:83 msgid "Content filtering" msgstr "Inhaltsfilterung" @@ -899,7 +918,7 @@ msgstr "" #: src/view/com/modals/AddAppPasswords.tsx:76 #: src/view/com/modals/InviteCodes.tsx:152 -#: src/view/com/util/forms/PostDropdownBtn.tsx:141 +#: src/view/com/util/forms/PostDropdownBtn.tsx:143 msgid "Copied to clipboard" msgstr "" @@ -915,7 +934,7 @@ msgstr "Kopieren" msgid "Copy link to list" msgstr "Link zur Liste kopieren" -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 msgid "Copy link to post" msgstr "Link zum Beitrag kopieren" @@ -923,7 +942,7 @@ msgstr "Link zum Beitrag kopieren" msgid "Copy link to profile" msgstr "Link zum Profil kopieren" -#: src/view/com/util/forms/PostDropdownBtn.tsx:168 +#: src/view/com/util/forms/PostDropdownBtn.tsx:170 msgid "Copy post text" msgstr "" @@ -979,7 +998,7 @@ msgstr "" msgid "Created by you" msgstr "" -#: src/view/com/composer/Composer.tsx:448 +#: src/view/com/composer/Composer.tsx:455 msgid "Creates a card with a thumbnail. The card links to {url}" msgstr "" @@ -1056,11 +1075,11 @@ msgstr "Mein Konto lƶschen" msgid "Delete My Account…" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:257 +#: src/view/com/util/forms/PostDropdownBtn.tsx:273 msgid "Delete post" msgstr "Beitrag lƶschen" -#: src/view/com/util/forms/PostDropdownBtn.tsx:261 +#: src/view/com/util/forms/PostDropdownBtn.tsx:277 msgid "Delete this post?" msgstr "Diesen Beitrag lƶschen?" @@ -1083,7 +1102,7 @@ msgstr "Beschreibung" #~ msgid "Developer Tools" #~ msgstr "Entwickler-Tools" -#: src/view/com/composer/Composer.tsx:211 +#: src/view/com/composer/Composer.tsx:218 msgid "Did you want to say anything?" msgstr "" @@ -1091,15 +1110,15 @@ msgstr "" msgid "Dim" msgstr "" -#: src/view/com/composer/Composer.tsx:144 +#: src/view/com/composer/Composer.tsx:151 msgid "Discard" msgstr "Verwerfen" -#: src/view/com/composer/Composer.tsx:138 +#: src/view/com/composer/Composer.tsx:145 msgid "Discard draft" msgstr "Entwurf verwerfen" -#: src/view/screens/Moderation.tsx:207 +#: src/view/screens/Moderation.tsx:226 msgid "Discourage apps from showing my account to logged-out users" msgstr "Apps daran hindern, abgemeldeten Nutzern mein Konto zu zeigen" @@ -1178,7 +1197,7 @@ msgstr "" msgid "Download CAR file" msgstr "" -#: src/view/com/composer/text-input/TextInput.web.tsx:247 +#: src/view/com/composer/text-input/TextInput.web.tsx:249 msgid "Drop to add images" msgstr "" @@ -1250,6 +1269,7 @@ msgstr "Profil bearbeiten" msgid "Edit Profile" msgstr "Profil bearbeiten" +#: src/view/com/home/HomeHeaderLayout.web.tsx:59 #: src/view/screens/Feeds.tsx:355 msgid "Edit Saved Feeds" msgstr "Gespeicherte Feeds bearbeiten" @@ -1332,6 +1352,11 @@ msgstr "Ende des Feeds" msgid "Enter a name for this App Password" msgstr "" +#: src/components/dialogs/MutedWords.tsx:87 +#: src/components/dialogs/MutedWords.tsx:88 +msgid "Enter a word or tag" +msgstr "" + #: src/view/com/modals/VerifyEmail.tsx:105 msgid "Enter Confirmation Code" msgstr "" @@ -1381,7 +1406,7 @@ msgstr "Gib deinen Benutzernamen und dein Passwort ein" msgid "Error receiving captcha response." msgstr "" -#: src/view/screens/Search/Search.tsx:109 +#: src/view/screens/Search/Search.tsx:110 msgid "Error:" msgstr "Fehler:" @@ -1452,7 +1477,7 @@ msgstr "" msgid "Failed to create the list. Check your internet connection and try again." msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:108 +#: src/view/com/util/forms/PostDropdownBtn.tsx:110 msgid "Failed to delete post, please try again" msgstr "" @@ -1474,8 +1499,8 @@ msgid "Feed offline" msgstr "Feed offline" #: src/view/com/feeds/FeedPage.tsx:143 -msgid "Feed Preferences" -msgstr "Feed-Einstellungen" +#~ msgid "Feed Preferences" +#~ msgstr "Feed-Einstellungen" #: src/view/shell/desktop/RightNav.tsx:61 #: src/view/shell/Drawer.tsx:311 @@ -1523,11 +1548,11 @@ msgstr "" msgid "Find accounts to follow" msgstr "" -#: src/view/screens/Search/Search.tsx:439 +#: src/view/screens/Search/Search.tsx:440 msgid "Find users on Bluesky" msgstr "Nutzer auf Bluesky finden" -#: src/view/screens/Search/Search.tsx:437 +#: src/view/screens/Search/Search.tsx:438 msgid "Find users with the search tool on the right" msgstr "Finde Nutzer mit der Suchfunktion auf der rechten Seite" @@ -1624,6 +1649,7 @@ msgid "Following {0}" msgstr "" #: src/Navigation.tsx:248 +#: src/view/com/home/HomeHeaderLayout.web.tsx:45 #: src/view/com/home/HomeHeaderLayoutMobile.tsx:83 #: src/view/screens/PreferencesFollowingFeed.tsx:104 #: src/view/screens/Settings/index.tsx:543 @@ -1663,7 +1689,7 @@ msgstr "Passwort vergessen" msgid "Forgot Password" msgstr "Passwort vergessen" -#: src/view/com/posts/FeedItem.tsx:187 +#: src/view/com/posts/FeedItem.tsx:189 msgctxt "from-feed" msgid "From <0/>" msgstr "" @@ -1696,7 +1722,7 @@ msgstr "Gehe zurück" msgid "Go back to previous step" msgstr "" -#: src/view/screens/Search/Search.tsx:724 +#: src/view/screens/Search/Search.tsx:747 #: src/view/shell/desktop/Search.tsx:262 msgid "Go to @{queryMaybeHandle}" msgstr "" @@ -1713,6 +1739,10 @@ msgstr "Gehe zum nƤchsten" msgid "Handle" msgstr "Handle" +#: src/components/RichText.tsx:188 +msgid "Hashtag: {tag}" +msgstr "" + #: src/view/com/auth/create/CreateAccount.tsx:208 msgid "Having trouble?" msgstr "" @@ -1751,7 +1781,7 @@ msgctxt "action" msgid "Hide" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +#: src/view/com/util/forms/PostDropdownBtn.tsx:232 msgid "Hide post" msgstr "Beitrag ausblenden" @@ -1760,7 +1790,7 @@ msgstr "Beitrag ausblenden" msgid "Hide the content" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:220 +#: src/view/com/util/forms/PostDropdownBtn.tsx:236 msgid "Hide this post?" msgstr "Diesen Beitrag ausblenden?" @@ -1909,7 +1939,7 @@ msgstr "" msgid "Input your user handle" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:224 +#: src/view/com/post-thread/PostThreadItem.tsx:226 msgid "Invalid or unsupported post record" msgstr "" @@ -2011,7 +2041,7 @@ msgstr "Mehr erfahren" msgid "Learn more about this warning" msgstr "Erfahre mehr über diese Warnung" -#: src/view/screens/Moderation.tsx:243 +#: src/view/screens/Moderation.tsx:262 msgid "Learn more about what is public on Bluesky." msgstr "Erfahre mehr darüber, was auf Bluesky ƶffentlich ist." @@ -2087,7 +2117,7 @@ msgstr "" msgid "Likes" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:181 +#: src/view/com/post-thread/PostThreadItem.tsx:183 msgid "Likes on this post" msgstr "" @@ -2144,7 +2174,7 @@ msgstr "Mehr BeitrƤge laden" msgid "Load new notifications" msgstr "Neue Benachrichtigungen laden" -#: src/view/com/feeds/FeedPage.tsx:181 +#: src/view/com/feeds/FeedPage.tsx:115 #: src/view/screens/Profile.tsx:440 #: src/view/screens/ProfileFeed.tsx:495 #: src/view/screens/ProfileList.tsx:681 @@ -2170,7 +2200,7 @@ msgstr "" msgid "Log out" msgstr "" -#: src/view/screens/Moderation.tsx:136 +#: src/view/screens/Moderation.tsx:155 msgid "Logged-out visibility" msgstr "" @@ -2182,6 +2212,10 @@ msgstr "Anmeldung bei einem Konto, das nicht aufgelistet ist" msgid "Make sure this is where you intend to go!" msgstr "Vergewissere dich, dass du auch wirklich dorthin gehen willst!" +#: src/components/dialogs/MutedWords.tsx:71 +msgid "Manage your muted words and tags" +msgstr "" + #: src/view/com/auth/create/Step2.tsx:118 msgid "May not be longer than 253 characters" msgstr "" @@ -2203,7 +2237,7 @@ msgid "Mentioned users" msgstr "ErwƤhnte Benutzer" #: src/view/com/util/ViewHeader.tsx:81 -#: src/view/screens/Search/Search.tsx:623 +#: src/view/screens/Search/Search.tsx:646 msgid "Menu" msgstr "Menü" @@ -2212,7 +2246,7 @@ msgid "Message from server: {0}" msgstr "Nachricht vom Server: {0}" #: src/Navigation.tsx:115 -#: src/view/screens/Moderation.tsx:64 +#: src/view/screens/Moderation.tsx:66 #: src/view/screens/Settings/index.tsx:625 #: src/view/shell/desktop/LeftNav.tsx:397 #: src/view/shell/Drawer.tsx:511 @@ -2243,7 +2277,7 @@ msgstr "" msgid "Moderation list updated" msgstr "" -#: src/view/screens/Moderation.tsx:95 +#: src/view/screens/Moderation.tsx:114 msgid "Moderation lists" msgstr "Moderationslisten" @@ -2270,7 +2304,7 @@ msgstr "Mehr Feeds" msgid "More options" msgstr "Mehr Optionen" -#: src/view/com/util/forms/PostDropdownBtn.tsx:299 +#: src/view/com/util/forms/PostDropdownBtn.tsx:315 msgid "More post options" msgstr "" @@ -2282,6 +2316,14 @@ msgstr "" msgid "Must be at least 3 characters" msgstr "" +#: src/components/TagMenu/index.tsx:253 +msgid "Mute" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:91 +msgid "Mute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:327 msgid "Mute Account" msgstr "Konto stummschalten" @@ -2290,6 +2332,18 @@ msgstr "Konto stummschalten" msgid "Mute accounts" msgstr "Konten stummschalten" +#: src/components/TagMenu/index.tsx:211 +msgid "Mute all {tag} posts" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:131 +msgid "Mute in tags only" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:116 +msgid "Mute in text & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:491 msgid "Mute list" msgstr "" @@ -2302,15 +2356,27 @@ msgstr "Diese Konten stummschalten?" msgid "Mute this List" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/dialogs/MutedWords.tsx:109 +msgid "Mute this word in post text and tags" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:124 +msgid "Mute this word in tags only" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Mute thread" msgstr "Thread stummschalten" +#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +msgid "Mute words & tags" +msgstr "" + #: src/view/com/lists/ListCard.tsx:102 msgid "Muted" msgstr "" -#: src/view/screens/Moderation.tsx:109 +#: src/view/screens/Moderation.tsx:128 msgid "Muted accounts" msgstr "Stummgeschaltete Konten" @@ -2323,6 +2389,10 @@ msgstr "Stummgeschaltete Konten" msgid "Muted accounts have their posts removed from your feed and from your notifications. Mutes are completely private." msgstr "Bei stummgeschalteten Konten werden ihre BeitrƤge aus deinem Feed und deinen Benachrichtigungen entfernt. Stummschaltungen sind vƶllig privat." +#: src/view/screens/Moderation.tsx:100 +msgid "Muted words & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:277 msgid "Muting is private. Muted accounts can interact with you, but you will not see their posts or receive notifications from them." msgstr "Stummschaltung ist privat. Stummgeschaltete Konten kƶnnen mit dir interagieren, aber du siehst ihre BeitrƤge nicht und erhƤltst keine Benachrichtigungen von ihnen." @@ -2386,6 +2456,10 @@ msgstr "Verliere nie den Zugriff auf deine Follower und Daten." msgid "Never lose access to your followers or data." msgstr "" +#: src/components/dialogs/MutedWords.tsx:244 +msgid "Nevermind" +msgstr "" + #: src/view/screens/Lists.tsx:76 msgctxt "action" msgid "New" @@ -2407,7 +2481,7 @@ msgstr "" msgid "New Password" msgstr "" -#: src/view/com/feeds/FeedPage.tsx:192 +#: src/view/com/feeds/FeedPage.tsx:126 msgctxt "action" msgid "New post" msgstr "" @@ -2492,8 +2566,8 @@ msgid "No results found for \"{query}\"" msgstr "Keine Ergebnisse für \"{query}\" gefunden" #: src/view/com/modals/ListAddRemoveUsers.tsx:127 -#: src/view/screens/Search/Search.tsx:280 -#: src/view/screens/Search/Search.tsx:308 +#: src/view/screens/Search/Search.tsx:281 +#: src/view/screens/Search/Search.tsx:309 msgid "No results found for {query}" msgstr "Keine Ergebnisse für {query} gefunden" @@ -2519,7 +2593,7 @@ msgstr "" msgid "Not right now" msgstr "" -#: src/view/screens/Moderation.tsx:233 +#: src/view/screens/Moderation.tsx:252 msgid "Note: Bluesky is an open and public network. This setting only limits the visibility of your content on the Bluesky app and website, and other apps may not respect this setting. Your content may still be shown to logged-out users by other apps and websites." msgstr "Hinweis: Bluesky ist ein offenes und ƶffentliches Netzwerk. Diese Einstellung schrƤnkt lediglich die Sichtbarkeit deiner Inhalte in der Bluesky-App und auf der Website ein. Andere Apps respektieren diese Einstellung mƶglicherweise nicht. Deine Inhalte werden abgemeldeten Nutzern mƶglicherweise weiterhin in anderen Apps und Websites angezeigt." @@ -2557,7 +2631,7 @@ msgstr "" msgid "Onboarding reset" msgstr "" -#: src/view/com/composer/Composer.tsx:375 +#: src/view/com/composer/Composer.tsx:382 msgid "One or more images is missing alt text." msgstr "Bei einem oder mehreren Bildern fehlt der Alt-Text." @@ -2574,8 +2648,12 @@ msgstr "" msgid "Open" msgstr "" -#: src/view/com/composer/Composer.tsx:470 -#: src/view/com/composer/Composer.tsx:471 +#: src/view/screens/Moderation.tsx:75 +msgid "Open content filtering settings" +msgstr "" + +#: src/view/com/composer/Composer.tsx:477 +#: src/view/com/composer/Composer.tsx:478 msgid "Open emoji picker" msgstr "" @@ -2583,6 +2661,10 @@ msgstr "" msgid "Open links with in-app browser" msgstr "" +#: src/view/screens/Moderation.tsx:92 +msgid "Open muted words settings" +msgstr "" + #: src/view/com/home/HomeHeaderLayoutMobile.tsx:49 msgid "Open navigation" msgstr "Navigation ƶffnen" @@ -2659,6 +2741,7 @@ msgstr "Ɩffnet die Moderationseinstellungen" msgid "Opens password reset form" msgstr "" +#: src/view/com/home/HomeHeaderLayout.web.tsx:60 #: src/view/screens/Feeds.tsx:356 msgid "Opens screen to edit Saved Feeds" msgstr "" @@ -2834,7 +2917,7 @@ msgstr "Bitte teile uns mit, warum du denkst, dass diese Inhaltswarnung falsch a msgid "Please Verify Your Email" msgstr "" -#: src/view/com/composer/Composer.tsx:215 +#: src/view/com/composer/Composer.tsx:222 msgid "Please wait for your link card to finish loading" msgstr "" @@ -2846,8 +2929,8 @@ msgstr "" msgid "Porn" msgstr "" -#: src/view/com/composer/Composer.tsx:350 -#: src/view/com/composer/Composer.tsx:358 +#: src/view/com/composer/Composer.tsx:357 +#: src/view/com/composer/Composer.tsx:365 msgctxt "action" msgid "Post" msgstr "" @@ -2857,7 +2940,7 @@ msgctxt "description" msgid "Post" msgstr "Beitrag" -#: src/view/com/post-thread/PostThreadItem.tsx:173 +#: src/view/com/post-thread/PostThreadItem.tsx:175 msgid "Post by {0}" msgstr "" @@ -2867,11 +2950,11 @@ msgstr "" msgid "Post by @{0}" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:88 +#: src/view/com/util/forms/PostDropdownBtn.tsx:90 msgid "Post deleted" msgstr "" -#: src/view/com/post-thread/PostThread.tsx:461 +#: src/view/com/post-thread/PostThread.tsx:462 msgid "Post hidden" msgstr "Beitrag ausgeblendet" @@ -2883,14 +2966,22 @@ msgstr "Beitragssprache" msgid "Post Languages" msgstr "Beitragssprachen" -#: src/view/com/post-thread/PostThread.tsx:513 +#: src/view/com/post-thread/PostThread.tsx:514 msgid "Post not found" msgstr "Beitrag nicht gefunden" +#: src/components/TagMenu/index.tsx:257 +msgid "posts" +msgstr "" + #: src/view/screens/Profile.tsx:180 msgid "Posts" msgstr "BeitrƤge" +#: src/components/dialogs/MutedWords.tsx:77 +msgid "Posts can be muted based on their text, their tags, or both." +msgstr "" + #: src/view/com/posts/FeedErrorMessage.tsx:64 msgid "Posts hidden" msgstr "" @@ -2955,11 +3046,11 @@ msgstr "Ɩffentliche, gemeinsam nutzbare Listen von Nutzern, die du stummschalte msgid "Public, shareable lists which can drive feeds." msgstr "Ɩffentliche, gemeinsam nutzbare Listen, die Feeds steuern kƶnnen." -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish post" msgstr "" -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish reply" msgstr "" @@ -2993,6 +3084,7 @@ msgstr "Empfohlene Feeds" msgid "Recommended Users" msgstr "Empfohlene Nutzer" +#: src/components/dialogs/MutedWords.tsx:249 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/SelfLabel.tsx:83 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -3030,6 +3122,10 @@ msgstr "Bild entfernen" msgid "Remove image preview" msgstr "Bildvorschau entfernen" +#: src/components/dialogs/MutedWords.tsx:294 +msgid "Remove mute word from your list" +msgstr "" + #: src/view/com/modals/Repost.tsx:47 msgid "Remove repost" msgstr "" @@ -3064,7 +3160,7 @@ msgstr "Antworten" msgid "Replies to this thread are disabled" msgstr "Antworten auf diesen Thread sind deaktiviert" -#: src/view/com/composer/Composer.tsx:348 +#: src/view/com/composer/Composer.tsx:355 msgctxt "action" msgid "Reply" msgstr "" @@ -3074,7 +3170,7 @@ msgid "Reply Filters" msgstr "Antwortfilter" #: src/view/com/post/Post.tsx:167 -#: src/view/com/posts/FeedItem.tsx:285 +#: src/view/com/posts/FeedItem.tsx:287 msgctxt "description" msgid "Reply to <0/>" msgstr "" @@ -3096,7 +3192,7 @@ msgid "Report List" msgstr "Liste melden" #: src/view/com/modals/report/SendReportButton.tsx:37 -#: src/view/com/util/forms/PostDropdownBtn.tsx:239 +#: src/view/com/util/forms/PostDropdownBtn.tsx:255 msgid "Report post" msgstr "Beitrag melden" @@ -3121,11 +3217,11 @@ msgstr "" msgid "Reposted By" msgstr "" -#: src/view/com/posts/FeedItem.tsx:205 +#: src/view/com/posts/FeedItem.tsx:207 msgid "Reposted by {0}" msgstr "" -#: src/view/com/posts/FeedItem.tsx:222 +#: src/view/com/posts/FeedItem.tsx:224 msgid "Reposted by <0/>" msgstr "" @@ -3133,7 +3229,7 @@ msgstr "" msgid "reposted your post" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:186 +#: src/view/com/post-thread/PostThreadItem.tsx:188 msgid "Reposts of this post" msgstr "" @@ -3284,9 +3380,9 @@ msgstr "" #: src/view/com/modals/ListAddRemoveUsers.tsx:75 #: src/view/com/util/forms/SearchInput.tsx:67 #: src/view/com/util/forms/SearchInput.tsx:79 -#: src/view/screens/Search/Search.tsx:418 -#: src/view/screens/Search/Search.tsx:645 -#: src/view/screens/Search/Search.tsx:663 +#: src/view/screens/Search/Search.tsx:419 +#: src/view/screens/Search/Search.tsx:668 +#: src/view/screens/Search/Search.tsx:686 #: src/view/shell/bottom-bar/BottomBar.tsx:159 #: src/view/shell/desktop/LeftNav.tsx:324 #: src/view/shell/desktop/Search.tsx:214 @@ -3296,11 +3392,19 @@ msgstr "" msgid "Search" msgstr "Suche" -#: src/view/screens/Search/Search.tsx:712 +#: src/view/screens/Search/Search.tsx:735 #: src/view/shell/desktop/Search.tsx:255 msgid "Search for \"{query}\"" msgstr "" +#: src/components/TagMenu/index.tsx:145 +msgid "Search for all posts by @{authorHandle} with tag {tag}" +msgstr "" + +#: src/components/TagMenu/index.tsx:90 +msgid "Search for all posts with tag {tag}" +msgstr "" + #: src/view/com/auth/LoggedOut.tsx:104 #: src/view/com/auth/LoggedOut.tsx:105 #: src/view/com/modals/ListAddRemoveUsers.tsx:70 @@ -3311,6 +3415,22 @@ msgstr "Nach Nutzern suchen" msgid "Security Step Required" msgstr "Sicherheitsschritt erforderlich" +#: src/components/TagMenu/index.web.tsx:50 +msgid "See {truncatedTag} posts" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:67 +msgid "See {truncatedTag} posts by user" +msgstr "" + +#: src/components/TagMenu/index.tsx:128 +msgid "See <0>{tag} posts" +msgstr "" + +#: src/components/TagMenu/index.tsx:189 +msgid "See <0>{tag} posts by this user" +msgstr "" + #: src/view/screens/SavedFeeds.tsx:163 msgid "See this guide" msgstr "" @@ -3520,7 +3640,7 @@ msgid "Share" msgstr "" #: src/view/com/profile/ProfileHeader.tsx:295 -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 #: src/view/screens/ProfileList.tsx:418 msgid "Share" msgstr "Teilen" @@ -3553,9 +3673,9 @@ msgstr "" msgid "Show follows similar to {0}" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:532 -#: src/view/com/post/Post.tsx:196 -#: src/view/com/posts/FeedItem.tsx:359 +#: src/view/com/post-thread/PostThreadItem.tsx:538 +#: src/view/com/post/Post.tsx:198 +#: src/view/com/posts/FeedItem.tsx:363 msgid "Show More" msgstr "" @@ -3723,7 +3843,7 @@ msgstr "" msgid "Something went wrong. Check your email and try again." msgstr "" -#: src/App.native.tsx:61 +#: src/App.native.tsx:63 msgid "Sorry! Your session expired. Please log in again." msgstr "" @@ -3781,7 +3901,7 @@ msgstr "" msgid "Subscribe to this list" msgstr "Abonniere diese Liste" -#: src/view/screens/Search/Search.tsx:373 +#: src/view/screens/Search/Search.tsx:374 msgid "Suggested Follows" msgstr "Vorgeschlagene Follower" @@ -3825,6 +3945,14 @@ msgstr "" msgid "System log" msgstr "Systemprotokoll" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "tag" +msgstr "" + +#: src/components/TagMenu/index.tsx:74 +msgid "Tag menu: {tag}" +msgstr "" + #: src/view/com/modals/crop-image/CropImage.web.tsx:112 msgid "Tall" msgstr "Groß" @@ -3848,6 +3976,10 @@ msgstr "Bedingungen" msgid "Terms of Service" msgstr "Nutzungsbedingungen" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "text" +msgstr "" + #: src/view/com/modals/AppealLabel.tsx:70 #: src/view/com/modals/report/InputIssueDetails.tsx:51 msgid "Text input field" @@ -3873,7 +4005,7 @@ msgstr "" msgid "The following steps will help customize your Bluesky experience." msgstr "" -#: src/view/com/post-thread/PostThread.tsx:516 +#: src/view/com/post-thread/PostThread.tsx:517 msgid "The post may have been deleted." msgstr "Mƶglicherweise wurde der Post gelƶscht." @@ -4039,7 +4171,7 @@ msgstr "" msgid "This name is already in use" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:123 +#: src/view/com/post-thread/PostThreadItem.tsx:125 msgid "This post has been deleted." msgstr "Dieser Beitrag wurde gelƶscht." @@ -4063,7 +4195,11 @@ msgstr "" msgid "This warning is only available for posts with media attached." msgstr "Diese Warnung ist nur für BeitrƤge mit angehƤngten Medien verfügbar." -#: src/view/com/util/forms/PostDropdownBtn.tsx:221 +#: src/components/dialogs/MutedWords.tsx:236 +msgid "This will delete {0} from your muted words. You can always add it back later." +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:237 msgid "This will hide this post from your feeds." msgstr "Dadurch wird dieser Beitrag aus deinen Feeds ausgeblendet." @@ -4080,6 +4216,10 @@ msgstr "" msgid "Threads Preferences" msgstr "" +#: src/components/dialogs/MutedWords.tsx:95 +msgid "Toggle between muted word options." +msgstr "" + #: src/view/com/util/forms/DropdownButton.tsx:246 msgid "Toggle dropdown" msgstr "" @@ -4088,9 +4228,9 @@ msgstr "" msgid "Transformations" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:679 -#: src/view/com/post-thread/PostThreadItem.tsx:681 -#: src/view/com/util/forms/PostDropdownBtn.tsx:154 +#: src/view/com/post-thread/PostThreadItem.tsx:685 +#: src/view/com/post-thread/PostThreadItem.tsx:687 +#: src/view/com/util/forms/PostDropdownBtn.tsx:156 msgid "Translate" msgstr "Übersetzen" @@ -4155,15 +4295,24 @@ msgstr "Leider erfüllst du nicht die Voraussetzungen, um einen Account zu erste msgid "Unlike" msgstr "" +#: src/components/TagMenu/index.tsx:253 #: src/view/screens/ProfileList.tsx:597 msgid "Unmute" msgstr "" +#: src/components/TagMenu/index.web.tsx:90 +msgid "Unmute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:326 msgid "Unmute Account" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/TagMenu/index.tsx:210 +msgid "Unmute all {tag} posts" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Unmute thread" msgstr "" @@ -4364,6 +4513,10 @@ msgstr "" #~ msgid "We recommend \"For You\" by Skygaze:" #~ msgstr "" +#: src/components/dialogs/MutedWords.tsx:161 +msgid "We recommend avoiding common words that appear in many posts, since it can result in no posts being shown." +msgstr "" + #: src/screens/Onboarding/StepAlgoFeeds/index.tsx:124 msgid "We recommend our \"Discover\" feed:" msgstr "" @@ -4392,7 +4545,11 @@ msgstr "Wir freuen uns sehr, dass du dabei bist!" msgid "We're sorry, but we were unable to resolve this list. If this persists, please contact the list creator, @{handleOrDid}." msgstr "" -#: src/view/screens/Search/Search.tsx:253 +#: src/components/dialogs/MutedWords.tsx:182 +msgid "We're sorry, but we weren't able to load your muted words at this time. Please try again." +msgstr "" + +#: src/view/screens/Search/Search.tsx:254 msgid "We're sorry, but your search could not be completed. Please try again in a few minutes." msgstr "Es tut uns leid, aber deine Suche konnte nicht abgeschlossen werden. Bitte versuche es in ein paar Minuten erneut." @@ -4413,7 +4570,7 @@ msgid "What is the issue with this {collectionName}?" msgstr "" #: src/view/com/auth/SplashScreen.tsx:59 -#: src/view/com/composer/Composer.tsx:279 +#: src/view/com/composer/Composer.tsx:286 msgid "What's up?" msgstr "Was gibt's?" @@ -4434,11 +4591,11 @@ msgstr "Wer antworten kann" msgid "Wide" msgstr "Breit" -#: src/view/com/composer/Composer.tsx:415 +#: src/view/com/composer/Composer.tsx:422 msgid "Write post" msgstr "Beitrag verfassen" -#: src/view/com/composer/Composer.tsx:278 +#: src/view/com/composer/Composer.tsx:285 #: src/view/com/composer/Prompt.tsx:33 msgid "Write your reply" msgstr "Schreibe deine Antwort" @@ -4503,7 +4660,7 @@ msgstr "Du hast keine gespeicherten Feeds!" msgid "You don't have any saved feeds." msgstr "Du hast keine gespeicherten Feeds." -#: src/view/com/post-thread/PostThread.tsx:464 +#: src/view/com/post-thread/PostThread.tsx:465 msgid "You have blocked the author or you have been blocked by the author." msgstr "Du hast den Verfasser blockiert oder du wurdest vom Verfasser blockiert." @@ -4543,6 +4700,10 @@ msgstr "Du hast noch keine App-Passwƶrter erstellt. Du kannst eines erstellen, msgid "You have not muted any accounts yet. To mute an account, go to their profile and selected \"Mute account\" from the menu on their account." msgstr "" +#: src/components/dialogs/MutedWords.tsx:202 +msgid "You haven't muted any words or tags yet" +msgstr "" + #: src/view/com/modals/ContentFilteringSettings.tsx:175 msgid "You must be 18 or older to enable adult content." msgstr "" @@ -4551,11 +4712,11 @@ msgstr "" msgid "You must be 18 years or older to enable adult content" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:127 +#: src/view/com/util/forms/PostDropdownBtn.tsx:129 msgid "You will no longer receive notifications for this thread" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:130 +#: src/view/com/util/forms/PostDropdownBtn.tsx:132 msgid "You will now receive notifications for this thread" msgstr "" @@ -4641,11 +4802,15 @@ msgstr "" #~ msgid "Your invite codes are hidden when logged in using an App Password" #~ msgstr "Deine Einladungscodes werden ausgeblendet, wenn du dich mit einem App-Passwort anmeldest" +#: src/components/dialogs/MutedWords.tsx:173 +msgid "Your muted words" +msgstr "" + #: src/view/com/modals/ChangePassword.tsx:155 msgid "Your password has been changed successfully!" msgstr "" -#: src/view/com/composer/Composer.tsx:267 +#: src/view/com/composer/Composer.tsx:274 msgid "Your post has been published" msgstr "" @@ -4660,7 +4825,7 @@ msgstr "Deine BeitrƤge, Likes und Blockierungen sind ƶffentlich. Stummschaltun msgid "Your profile" msgstr "Dein Profil" -#: src/view/com/composer/Composer.tsx:266 +#: src/view/com/composer/Composer.tsx:273 msgid "Your reply has been published" msgstr "" diff --git a/src/locale/locales/en/messages.po b/src/locale/locales/en/messages.po index b944990551..cc40e1f0ef 100644 --- a/src/locale/locales/en/messages.po +++ b/src/locale/locales/en/messages.po @@ -76,7 +76,7 @@ msgid "A new version of the app is available. Please update to continue using th msgstr "" #: src/view/com/util/ViewHeader.tsx:83 -#: src/view/screens/Search/Search.tsx:624 +#: src/view/screens/Search/Search.tsx:647 msgid "Access navigation links and settings" msgstr "" @@ -127,6 +127,7 @@ msgstr "" msgid "Account unmuted" msgstr "" +#: src/components/dialogs/MutedWords.tsx:147 #: src/view/com/auth/onboarding/RecommendedFeedsItem.tsx:150 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -168,14 +169,22 @@ msgstr "" msgid "Add details to report" msgstr "" -#: src/view/com/composer/Composer.tsx:446 +#: src/view/com/composer/Composer.tsx:453 msgid "Add link card" msgstr "" -#: src/view/com/composer/Composer.tsx:451 +#: src/view/com/composer/Composer.tsx:458 msgid "Add link card:" msgstr "" +#: src/components/dialogs/MutedWords.tsx:140 +msgid "Add mute word for configured settings" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:74 +msgid "Add muted words and tags" +msgstr "" + #: src/view/com/modals/ChangeHandle.tsx:417 msgid "Add the following DNS record to your domain:" msgstr "" @@ -299,7 +308,7 @@ msgstr "" msgid "App Passwords" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:279 +#: src/view/com/util/forms/PostDropdownBtn.tsx:295 msgid "Appeal content warning" msgstr "" @@ -323,15 +332,16 @@ msgstr "" msgid "Are you sure you want to delete the app password \"{name}\"?" msgstr "" -#: src/view/com/composer/Composer.tsx:143 +#: src/view/com/composer/Composer.tsx:150 msgid "Are you sure you'd like to discard this draft?" msgstr "" +#: src/components/dialogs/MutedWords.tsx:233 #: src/view/screens/ProfileList.tsx:365 msgid "Are you sure?" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:262 +#: src/view/com/util/forms/PostDropdownBtn.tsx:278 msgid "Are you sure? This cannot be undone." msgstr "" @@ -353,15 +363,15 @@ msgstr "" #: src/view/com/auth/login/LoginForm.tsx:259 #: src/view/com/auth/login/SetNewPasswordForm.tsx:179 #: src/view/com/modals/report/InputIssueDetails.tsx:46 -#: src/view/com/post-thread/PostThread.tsx:471 -#: src/view/com/post-thread/PostThread.tsx:521 -#: src/view/com/post-thread/PostThread.tsx:529 +#: src/view/com/post-thread/PostThread.tsx:472 +#: src/view/com/post-thread/PostThread.tsx:522 +#: src/view/com/post-thread/PostThread.tsx:530 #: src/view/com/profile/ProfileHeader.tsx:649 #: src/view/com/util/ViewHeader.tsx:81 msgid "Back" msgstr "" -#: src/view/com/post-thread/PostThread.tsx:479 +#: src/view/com/post-thread/PostThread.tsx:480 msgctxt "action" msgid "Back" msgstr "" @@ -409,7 +419,7 @@ msgstr "" msgid "Blocked" msgstr "" -#: src/view/screens/Moderation.tsx:123 +#: src/view/screens/Moderation.tsx:142 msgid "Blocked accounts" msgstr "" @@ -468,7 +478,7 @@ msgstr "" msgid "Bluesky uses invites to build a healthier community. If you don't know anybody with an invite, you can sign up for the waitlist and we'll send one soon." msgstr "" -#: src/view/screens/Moderation.tsx:226 +#: src/view/screens/Moderation.tsx:245 msgid "Bluesky will not show your profile and posts to logged-out users. Other apps may not honor this request. This does not make your account private." msgstr "" @@ -520,8 +530,8 @@ msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must msgstr "" #: src/components/Prompt.tsx:91 -#: src/view/com/composer/Composer.tsx:300 -#: src/view/com/composer/Composer.tsx:305 +#: src/view/com/composer/Composer.tsx:307 +#: src/view/com/composer/Composer.tsx:312 #: src/view/com/modals/ChangeEmail.tsx:218 #: src/view/com/modals/ChangeEmail.tsx:220 #: src/view/com/modals/ChangePassword.tsx:265 @@ -535,7 +545,7 @@ msgstr "" #: src/view/com/modals/VerifyEmail.tsx:247 #: src/view/com/modals/VerifyEmail.tsx:253 #: src/view/com/modals/Waitlist.tsx:142 -#: src/view/screens/Search/Search.tsx:693 +#: src/view/screens/Search/Search.tsx:716 #: src/view/shell/desktop/Search.tsx:238 msgid "Cancel" msgstr "" @@ -686,7 +696,7 @@ msgid "Clear all storage data (restart after this)" msgstr "" #: src/view/com/util/forms/SearchInput.tsx:88 -#: src/view/screens/Search/Search.tsx:674 +#: src/view/screens/Search/Search.tsx:697 msgid "Clear search query" msgstr "" @@ -694,6 +704,11 @@ msgstr "" msgid "click here" msgstr "" +#: src/components/RichText.tsx:189 +#: src/components/TagMenu/index.web.tsx:125 +msgid "Click here to open tag menu for {tag}" +msgstr "" + #: src/screens/Onboarding/index.tsx:35 msgid "Climate" msgstr "" @@ -724,11 +739,15 @@ msgstr "" msgid "Close image viewer" msgstr "" -#: src/view/shell/index.web.tsx:49 +#: src/view/shell/index.web.tsx:51 msgid "Close navigation footer" msgstr "" -#: src/view/shell/index.web.tsx:50 +#: src/components/TagMenu/index.tsx:266 +msgid "Close this dialog" +msgstr "" + +#: src/view/shell/index.web.tsx:52 msgid "Closes bottom navigation bar" msgstr "" @@ -736,7 +755,7 @@ msgstr "" msgid "Closes password update alert" msgstr "" -#: src/view/com/composer/Composer.tsx:302 +#: src/view/com/composer/Composer.tsx:309 msgid "Closes post composer and discards post draft" msgstr "" @@ -769,7 +788,7 @@ msgstr "" msgid "Complete the challenge" msgstr "" -#: src/view/com/composer/Composer.tsx:417 +#: src/view/com/composer/Composer.tsx:424 msgid "Compose posts up to {MAX_GRAPHEME_LENGTH} characters in length" msgstr "" @@ -833,7 +852,7 @@ msgstr "" msgid "Contact support" msgstr "" -#: src/view/screens/Moderation.tsx:81 +#: src/view/screens/Moderation.tsx:83 msgid "Content filtering" msgstr "" @@ -899,7 +918,7 @@ msgstr "" #: src/view/com/modals/AddAppPasswords.tsx:76 #: src/view/com/modals/InviteCodes.tsx:152 -#: src/view/com/util/forms/PostDropdownBtn.tsx:141 +#: src/view/com/util/forms/PostDropdownBtn.tsx:143 msgid "Copied to clipboard" msgstr "" @@ -915,7 +934,7 @@ msgstr "" msgid "Copy link to list" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 msgid "Copy link to post" msgstr "" @@ -923,7 +942,7 @@ msgstr "" msgid "Copy link to profile" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:168 +#: src/view/com/util/forms/PostDropdownBtn.tsx:170 msgid "Copy post text" msgstr "" @@ -979,7 +998,7 @@ msgstr "" msgid "Created by you" msgstr "" -#: src/view/com/composer/Composer.tsx:448 +#: src/view/com/composer/Composer.tsx:455 msgid "Creates a card with a thumbnail. The card links to {url}" msgstr "" @@ -1056,11 +1075,11 @@ msgstr "" msgid "Delete My Account…" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:257 +#: src/view/com/util/forms/PostDropdownBtn.tsx:273 msgid "Delete post" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:261 +#: src/view/com/util/forms/PostDropdownBtn.tsx:277 msgid "Delete this post?" msgstr "" @@ -1083,7 +1102,7 @@ msgstr "" #~ msgid "Developer Tools" #~ msgstr "" -#: src/view/com/composer/Composer.tsx:211 +#: src/view/com/composer/Composer.tsx:218 msgid "Did you want to say anything?" msgstr "" @@ -1091,15 +1110,15 @@ msgstr "" msgid "Dim" msgstr "" -#: src/view/com/composer/Composer.tsx:144 +#: src/view/com/composer/Composer.tsx:151 msgid "Discard" msgstr "" -#: src/view/com/composer/Composer.tsx:138 +#: src/view/com/composer/Composer.tsx:145 msgid "Discard draft" msgstr "" -#: src/view/screens/Moderation.tsx:207 +#: src/view/screens/Moderation.tsx:226 msgid "Discourage apps from showing my account to logged-out users" msgstr "" @@ -1178,7 +1197,7 @@ msgstr "" msgid "Download CAR file" msgstr "" -#: src/view/com/composer/text-input/TextInput.web.tsx:247 +#: src/view/com/composer/text-input/TextInput.web.tsx:249 msgid "Drop to add images" msgstr "" @@ -1250,6 +1269,7 @@ msgstr "" msgid "Edit Profile" msgstr "" +#: src/view/com/home/HomeHeaderLayout.web.tsx:59 #: src/view/screens/Feeds.tsx:355 msgid "Edit Saved Feeds" msgstr "" @@ -1332,6 +1352,11 @@ msgstr "" msgid "Enter a name for this App Password" msgstr "" +#: src/components/dialogs/MutedWords.tsx:87 +#: src/components/dialogs/MutedWords.tsx:88 +msgid "Enter a word or tag" +msgstr "" + #: src/view/com/modals/VerifyEmail.tsx:105 msgid "Enter Confirmation Code" msgstr "" @@ -1381,7 +1406,7 @@ msgstr "" msgid "Error receiving captcha response." msgstr "" -#: src/view/screens/Search/Search.tsx:109 +#: src/view/screens/Search/Search.tsx:110 msgid "Error:" msgstr "" @@ -1452,7 +1477,7 @@ msgstr "" msgid "Failed to create the list. Check your internet connection and try again." msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:108 +#: src/view/com/util/forms/PostDropdownBtn.tsx:110 msgid "Failed to delete post, please try again" msgstr "" @@ -1474,8 +1499,8 @@ msgid "Feed offline" msgstr "" #: src/view/com/feeds/FeedPage.tsx:143 -msgid "Feed Preferences" -msgstr "" +#~ msgid "Feed Preferences" +#~ msgstr "" #: src/view/shell/desktop/RightNav.tsx:61 #: src/view/shell/Drawer.tsx:311 @@ -1523,11 +1548,11 @@ msgstr "" msgid "Find accounts to follow" msgstr "" -#: src/view/screens/Search/Search.tsx:439 +#: src/view/screens/Search/Search.tsx:440 msgid "Find users on Bluesky" msgstr "" -#: src/view/screens/Search/Search.tsx:437 +#: src/view/screens/Search/Search.tsx:438 msgid "Find users with the search tool on the right" msgstr "" @@ -1624,6 +1649,7 @@ msgid "Following {0}" msgstr "" #: src/Navigation.tsx:248 +#: src/view/com/home/HomeHeaderLayout.web.tsx:45 #: src/view/com/home/HomeHeaderLayoutMobile.tsx:83 #: src/view/screens/PreferencesFollowingFeed.tsx:104 #: src/view/screens/Settings/index.tsx:543 @@ -1663,7 +1689,7 @@ msgstr "" msgid "Forgot Password" msgstr "" -#: src/view/com/posts/FeedItem.tsx:187 +#: src/view/com/posts/FeedItem.tsx:189 msgctxt "from-feed" msgid "From <0/>" msgstr "" @@ -1696,7 +1722,7 @@ msgstr "" msgid "Go back to previous step" msgstr "" -#: src/view/screens/Search/Search.tsx:724 +#: src/view/screens/Search/Search.tsx:747 #: src/view/shell/desktop/Search.tsx:262 msgid "Go to @{queryMaybeHandle}" msgstr "" @@ -1713,6 +1739,10 @@ msgstr "" msgid "Handle" msgstr "" +#: src/components/RichText.tsx:188 +msgid "Hashtag: {tag}" +msgstr "" + #: src/view/com/auth/create/CreateAccount.tsx:208 msgid "Having trouble?" msgstr "" @@ -1751,7 +1781,7 @@ msgctxt "action" msgid "Hide" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +#: src/view/com/util/forms/PostDropdownBtn.tsx:232 msgid "Hide post" msgstr "" @@ -1760,7 +1790,7 @@ msgstr "" msgid "Hide the content" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:220 +#: src/view/com/util/forms/PostDropdownBtn.tsx:236 msgid "Hide this post?" msgstr "" @@ -1909,7 +1939,7 @@ msgstr "" msgid "Input your user handle" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:224 +#: src/view/com/post-thread/PostThreadItem.tsx:226 msgid "Invalid or unsupported post record" msgstr "" @@ -2011,7 +2041,7 @@ msgstr "" msgid "Learn more about this warning" msgstr "" -#: src/view/screens/Moderation.tsx:243 +#: src/view/screens/Moderation.tsx:262 msgid "Learn more about what is public on Bluesky." msgstr "" @@ -2087,7 +2117,7 @@ msgstr "" msgid "Likes" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:181 +#: src/view/com/post-thread/PostThreadItem.tsx:183 msgid "Likes on this post" msgstr "" @@ -2144,7 +2174,7 @@ msgstr "" msgid "Load new notifications" msgstr "" -#: src/view/com/feeds/FeedPage.tsx:181 +#: src/view/com/feeds/FeedPage.tsx:115 #: src/view/screens/Profile.tsx:440 #: src/view/screens/ProfileFeed.tsx:495 #: src/view/screens/ProfileList.tsx:681 @@ -2170,7 +2200,7 @@ msgstr "" msgid "Log out" msgstr "" -#: src/view/screens/Moderation.tsx:136 +#: src/view/screens/Moderation.tsx:155 msgid "Logged-out visibility" msgstr "" @@ -2182,6 +2212,10 @@ msgstr "" msgid "Make sure this is where you intend to go!" msgstr "" +#: src/components/dialogs/MutedWords.tsx:71 +msgid "Manage your muted words and tags" +msgstr "" + #: src/view/com/auth/create/Step2.tsx:118 msgid "May not be longer than 253 characters" msgstr "" @@ -2203,7 +2237,7 @@ msgid "Mentioned users" msgstr "" #: src/view/com/util/ViewHeader.tsx:81 -#: src/view/screens/Search/Search.tsx:623 +#: src/view/screens/Search/Search.tsx:646 msgid "Menu" msgstr "" @@ -2212,7 +2246,7 @@ msgid "Message from server: {0}" msgstr "" #: src/Navigation.tsx:115 -#: src/view/screens/Moderation.tsx:64 +#: src/view/screens/Moderation.tsx:66 #: src/view/screens/Settings/index.tsx:625 #: src/view/shell/desktop/LeftNav.tsx:397 #: src/view/shell/Drawer.tsx:511 @@ -2243,7 +2277,7 @@ msgstr "" msgid "Moderation list updated" msgstr "" -#: src/view/screens/Moderation.tsx:95 +#: src/view/screens/Moderation.tsx:114 msgid "Moderation lists" msgstr "" @@ -2270,7 +2304,7 @@ msgstr "" msgid "More options" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:299 +#: src/view/com/util/forms/PostDropdownBtn.tsx:315 msgid "More post options" msgstr "" @@ -2282,6 +2316,14 @@ msgstr "" msgid "Must be at least 3 characters" msgstr "" +#: src/components/TagMenu/index.tsx:253 +msgid "Mute" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:91 +msgid "Mute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:327 msgid "Mute Account" msgstr "" @@ -2290,6 +2332,18 @@ msgstr "" msgid "Mute accounts" msgstr "" +#: src/components/TagMenu/index.tsx:211 +msgid "Mute all {tag} posts" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:131 +msgid "Mute in tags only" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:116 +msgid "Mute in text & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:491 msgid "Mute list" msgstr "" @@ -2302,15 +2356,27 @@ msgstr "" msgid "Mute this List" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/dialogs/MutedWords.tsx:109 +msgid "Mute this word in post text and tags" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:124 +msgid "Mute this word in tags only" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Mute thread" msgstr "" +#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +msgid "Mute words & tags" +msgstr "" + #: src/view/com/lists/ListCard.tsx:102 msgid "Muted" msgstr "" -#: src/view/screens/Moderation.tsx:109 +#: src/view/screens/Moderation.tsx:128 msgid "Muted accounts" msgstr "" @@ -2323,6 +2389,10 @@ msgstr "" msgid "Muted accounts have their posts removed from your feed and from your notifications. Mutes are completely private." msgstr "" +#: src/view/screens/Moderation.tsx:100 +msgid "Muted words & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:277 msgid "Muting is private. Muted accounts can interact with you, but you will not see their posts or receive notifications from them." msgstr "" @@ -2386,6 +2456,10 @@ msgstr "" msgid "Never lose access to your followers or data." msgstr "" +#: src/components/dialogs/MutedWords.tsx:244 +msgid "Nevermind" +msgstr "" + #: src/view/screens/Lists.tsx:76 msgctxt "action" msgid "New" @@ -2407,7 +2481,7 @@ msgstr "" msgid "New Password" msgstr "" -#: src/view/com/feeds/FeedPage.tsx:192 +#: src/view/com/feeds/FeedPage.tsx:126 msgctxt "action" msgid "New post" msgstr "" @@ -2492,8 +2566,8 @@ msgid "No results found for \"{query}\"" msgstr "" #: src/view/com/modals/ListAddRemoveUsers.tsx:127 -#: src/view/screens/Search/Search.tsx:280 -#: src/view/screens/Search/Search.tsx:308 +#: src/view/screens/Search/Search.tsx:281 +#: src/view/screens/Search/Search.tsx:309 msgid "No results found for {query}" msgstr "" @@ -2519,7 +2593,7 @@ msgstr "" msgid "Not right now" msgstr "" -#: src/view/screens/Moderation.tsx:233 +#: src/view/screens/Moderation.tsx:252 msgid "Note: Bluesky is an open and public network. This setting only limits the visibility of your content on the Bluesky app and website, and other apps may not respect this setting. Your content may still be shown to logged-out users by other apps and websites." msgstr "" @@ -2557,7 +2631,7 @@ msgstr "" msgid "Onboarding reset" msgstr "" -#: src/view/com/composer/Composer.tsx:375 +#: src/view/com/composer/Composer.tsx:382 msgid "One or more images is missing alt text." msgstr "" @@ -2574,8 +2648,12 @@ msgstr "" msgid "Open" msgstr "" -#: src/view/com/composer/Composer.tsx:470 -#: src/view/com/composer/Composer.tsx:471 +#: src/view/screens/Moderation.tsx:75 +msgid "Open content filtering settings" +msgstr "" + +#: src/view/com/composer/Composer.tsx:477 +#: src/view/com/composer/Composer.tsx:478 msgid "Open emoji picker" msgstr "" @@ -2583,6 +2661,10 @@ msgstr "" msgid "Open links with in-app browser" msgstr "" +#: src/view/screens/Moderation.tsx:92 +msgid "Open muted words settings" +msgstr "" + #: src/view/com/home/HomeHeaderLayoutMobile.tsx:49 msgid "Open navigation" msgstr "" @@ -2659,6 +2741,7 @@ msgstr "" msgid "Opens password reset form" msgstr "" +#: src/view/com/home/HomeHeaderLayout.web.tsx:60 #: src/view/screens/Feeds.tsx:356 msgid "Opens screen to edit Saved Feeds" msgstr "" @@ -2839,7 +2922,7 @@ msgstr "" msgid "Please Verify Your Email" msgstr "" -#: src/view/com/composer/Composer.tsx:215 +#: src/view/com/composer/Composer.tsx:222 msgid "Please wait for your link card to finish loading" msgstr "" @@ -2851,8 +2934,8 @@ msgstr "" msgid "Porn" msgstr "" -#: src/view/com/composer/Composer.tsx:350 -#: src/view/com/composer/Composer.tsx:358 +#: src/view/com/composer/Composer.tsx:357 +#: src/view/com/composer/Composer.tsx:365 msgctxt "action" msgid "Post" msgstr "" @@ -2862,7 +2945,7 @@ msgctxt "description" msgid "Post" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:173 +#: src/view/com/post-thread/PostThreadItem.tsx:175 msgid "Post by {0}" msgstr "" @@ -2872,11 +2955,11 @@ msgstr "" msgid "Post by @{0}" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:88 +#: src/view/com/util/forms/PostDropdownBtn.tsx:90 msgid "Post deleted" msgstr "" -#: src/view/com/post-thread/PostThread.tsx:461 +#: src/view/com/post-thread/PostThread.tsx:462 msgid "Post hidden" msgstr "" @@ -2888,14 +2971,22 @@ msgstr "" msgid "Post Languages" msgstr "" -#: src/view/com/post-thread/PostThread.tsx:513 +#: src/view/com/post-thread/PostThread.tsx:514 msgid "Post not found" msgstr "" +#: src/components/TagMenu/index.tsx:257 +msgid "posts" +msgstr "" + #: src/view/screens/Profile.tsx:180 msgid "Posts" msgstr "" +#: src/components/dialogs/MutedWords.tsx:77 +msgid "Posts can be muted based on their text, their tags, or both." +msgstr "" + #: src/view/com/posts/FeedErrorMessage.tsx:64 msgid "Posts hidden" msgstr "" @@ -2960,11 +3051,11 @@ msgstr "" msgid "Public, shareable lists which can drive feeds." msgstr "" -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish post" msgstr "" -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish reply" msgstr "" @@ -2998,6 +3089,7 @@ msgstr "" msgid "Recommended Users" msgstr "" +#: src/components/dialogs/MutedWords.tsx:249 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/SelfLabel.tsx:83 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -3035,6 +3127,10 @@ msgstr "" msgid "Remove image preview" msgstr "" +#: src/components/dialogs/MutedWords.tsx:294 +msgid "Remove mute word from your list" +msgstr "" + #: src/view/com/modals/Repost.tsx:47 msgid "Remove repost" msgstr "" @@ -3069,7 +3165,7 @@ msgstr "" msgid "Replies to this thread are disabled" msgstr "" -#: src/view/com/composer/Composer.tsx:348 +#: src/view/com/composer/Composer.tsx:355 msgctxt "action" msgid "Reply" msgstr "" @@ -3079,7 +3175,7 @@ msgid "Reply Filters" msgstr "" #: src/view/com/post/Post.tsx:167 -#: src/view/com/posts/FeedItem.tsx:285 +#: src/view/com/posts/FeedItem.tsx:287 msgctxt "description" msgid "Reply to <0/>" msgstr "" @@ -3101,7 +3197,7 @@ msgid "Report List" msgstr "" #: src/view/com/modals/report/SendReportButton.tsx:37 -#: src/view/com/util/forms/PostDropdownBtn.tsx:239 +#: src/view/com/util/forms/PostDropdownBtn.tsx:255 msgid "Report post" msgstr "" @@ -3126,11 +3222,11 @@ msgstr "" msgid "Reposted By" msgstr "" -#: src/view/com/posts/FeedItem.tsx:205 +#: src/view/com/posts/FeedItem.tsx:207 msgid "Reposted by {0}" msgstr "" -#: src/view/com/posts/FeedItem.tsx:222 +#: src/view/com/posts/FeedItem.tsx:224 msgid "Reposted by <0/>" msgstr "" @@ -3138,7 +3234,7 @@ msgstr "" msgid "reposted your post" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:186 +#: src/view/com/post-thread/PostThreadItem.tsx:188 msgid "Reposts of this post" msgstr "" @@ -3289,9 +3385,9 @@ msgstr "" #: src/view/com/modals/ListAddRemoveUsers.tsx:75 #: src/view/com/util/forms/SearchInput.tsx:67 #: src/view/com/util/forms/SearchInput.tsx:79 -#: src/view/screens/Search/Search.tsx:418 -#: src/view/screens/Search/Search.tsx:645 -#: src/view/screens/Search/Search.tsx:663 +#: src/view/screens/Search/Search.tsx:419 +#: src/view/screens/Search/Search.tsx:668 +#: src/view/screens/Search/Search.tsx:686 #: src/view/shell/bottom-bar/BottomBar.tsx:159 #: src/view/shell/desktop/LeftNav.tsx:324 #: src/view/shell/desktop/Search.tsx:214 @@ -3301,11 +3397,19 @@ msgstr "" msgid "Search" msgstr "" -#: src/view/screens/Search/Search.tsx:712 +#: src/view/screens/Search/Search.tsx:735 #: src/view/shell/desktop/Search.tsx:255 msgid "Search for \"{query}\"" msgstr "" +#: src/components/TagMenu/index.tsx:145 +msgid "Search for all posts by @{authorHandle} with tag {tag}" +msgstr "" + +#: src/components/TagMenu/index.tsx:90 +msgid "Search for all posts with tag {tag}" +msgstr "" + #: src/view/com/auth/LoggedOut.tsx:104 #: src/view/com/auth/LoggedOut.tsx:105 #: src/view/com/modals/ListAddRemoveUsers.tsx:70 @@ -3316,6 +3420,22 @@ msgstr "" msgid "Security Step Required" msgstr "" +#: src/components/TagMenu/index.web.tsx:50 +msgid "See {truncatedTag} posts" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:67 +msgid "See {truncatedTag} posts by user" +msgstr "" + +#: src/components/TagMenu/index.tsx:128 +msgid "See <0>{tag} posts" +msgstr "" + +#: src/components/TagMenu/index.tsx:189 +msgid "See <0>{tag} posts by this user" +msgstr "" + #: src/view/screens/SavedFeeds.tsx:163 msgid "See this guide" msgstr "" @@ -3525,7 +3645,7 @@ msgid "Share" msgstr "" #: src/view/com/profile/ProfileHeader.tsx:295 -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 #: src/view/screens/ProfileList.tsx:418 msgid "Share" msgstr "" @@ -3558,9 +3678,9 @@ msgstr "" msgid "Show follows similar to {0}" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:532 -#: src/view/com/post/Post.tsx:196 -#: src/view/com/posts/FeedItem.tsx:359 +#: src/view/com/post-thread/PostThreadItem.tsx:538 +#: src/view/com/post/Post.tsx:198 +#: src/view/com/posts/FeedItem.tsx:363 msgid "Show More" msgstr "" @@ -3728,7 +3848,7 @@ msgstr "" msgid "Something went wrong. Check your email and try again." msgstr "" -#: src/App.native.tsx:61 +#: src/App.native.tsx:63 msgid "Sorry! Your session expired. Please log in again." msgstr "" @@ -3786,7 +3906,7 @@ msgstr "" msgid "Subscribe to this list" msgstr "" -#: src/view/screens/Search/Search.tsx:373 +#: src/view/screens/Search/Search.tsx:374 msgid "Suggested Follows" msgstr "" @@ -3830,6 +3950,14 @@ msgstr "" msgid "System log" msgstr "" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "tag" +msgstr "" + +#: src/components/TagMenu/index.tsx:74 +msgid "Tag menu: {tag}" +msgstr "" + #: src/view/com/modals/crop-image/CropImage.web.tsx:112 msgid "Tall" msgstr "" @@ -3853,6 +3981,10 @@ msgstr "" msgid "Terms of Service" msgstr "" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "text" +msgstr "" + #: src/view/com/modals/AppealLabel.tsx:70 #: src/view/com/modals/report/InputIssueDetails.tsx:51 msgid "Text input field" @@ -3878,7 +4010,7 @@ msgstr "" msgid "The following steps will help customize your Bluesky experience." msgstr "" -#: src/view/com/post-thread/PostThread.tsx:516 +#: src/view/com/post-thread/PostThread.tsx:517 msgid "The post may have been deleted." msgstr "" @@ -4044,7 +4176,7 @@ msgstr "" msgid "This name is already in use" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:123 +#: src/view/com/post-thread/PostThreadItem.tsx:125 msgid "This post has been deleted." msgstr "" @@ -4068,7 +4200,11 @@ msgstr "" msgid "This warning is only available for posts with media attached." msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:221 +#: src/components/dialogs/MutedWords.tsx:236 +msgid "This will delete {0} from your muted words. You can always add it back later." +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:237 msgid "This will hide this post from your feeds." msgstr "" @@ -4085,6 +4221,10 @@ msgstr "" msgid "Threads Preferences" msgstr "" +#: src/components/dialogs/MutedWords.tsx:95 +msgid "Toggle between muted word options." +msgstr "" + #: src/view/com/util/forms/DropdownButton.tsx:246 msgid "Toggle dropdown" msgstr "" @@ -4093,9 +4233,9 @@ msgstr "" msgid "Transformations" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:679 -#: src/view/com/post-thread/PostThreadItem.tsx:681 -#: src/view/com/util/forms/PostDropdownBtn.tsx:154 +#: src/view/com/post-thread/PostThreadItem.tsx:685 +#: src/view/com/post-thread/PostThreadItem.tsx:687 +#: src/view/com/util/forms/PostDropdownBtn.tsx:156 msgid "Translate" msgstr "" @@ -4160,15 +4300,24 @@ msgstr "" msgid "Unlike" msgstr "" +#: src/components/TagMenu/index.tsx:253 #: src/view/screens/ProfileList.tsx:597 msgid "Unmute" msgstr "" +#: src/components/TagMenu/index.web.tsx:90 +msgid "Unmute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:326 msgid "Unmute Account" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/TagMenu/index.tsx:210 +msgid "Unmute all {tag} posts" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Unmute thread" msgstr "" @@ -4369,6 +4518,10 @@ msgstr "" #~ msgid "We recommend \"For You\" by Skygaze:" #~ msgstr "" +#: src/components/dialogs/MutedWords.tsx:161 +msgid "We recommend avoiding common words that appear in many posts, since it can result in no posts being shown." +msgstr "" + #: src/screens/Onboarding/StepAlgoFeeds/index.tsx:124 msgid "We recommend our \"Discover\" feed:" msgstr "" @@ -4397,7 +4550,11 @@ msgstr "" msgid "We're sorry, but we were unable to resolve this list. If this persists, please contact the list creator, @{handleOrDid}." msgstr "" -#: src/view/screens/Search/Search.tsx:253 +#: src/components/dialogs/MutedWords.tsx:182 +msgid "We're sorry, but we weren't able to load your muted words at this time. Please try again." +msgstr "" + +#: src/view/screens/Search/Search.tsx:254 msgid "We're sorry, but your search could not be completed. Please try again in a few minutes." msgstr "" @@ -4418,7 +4575,7 @@ msgid "What is the issue with this {collectionName}?" msgstr "" #: src/view/com/auth/SplashScreen.tsx:59 -#: src/view/com/composer/Composer.tsx:279 +#: src/view/com/composer/Composer.tsx:286 msgid "What's up?" msgstr "" @@ -4439,11 +4596,11 @@ msgstr "" msgid "Wide" msgstr "" -#: src/view/com/composer/Composer.tsx:415 +#: src/view/com/composer/Composer.tsx:422 msgid "Write post" msgstr "" -#: src/view/com/composer/Composer.tsx:278 +#: src/view/com/composer/Composer.tsx:285 #: src/view/com/composer/Prompt.tsx:33 msgid "Write your reply" msgstr "" @@ -4508,7 +4665,7 @@ msgstr "" msgid "You don't have any saved feeds." msgstr "" -#: src/view/com/post-thread/PostThread.tsx:464 +#: src/view/com/post-thread/PostThread.tsx:465 msgid "You have blocked the author or you have been blocked by the author." msgstr "" @@ -4548,6 +4705,10 @@ msgstr "" msgid "You have not muted any accounts yet. To mute an account, go to their profile and selected \"Mute account\" from the menu on their account." msgstr "" +#: src/components/dialogs/MutedWords.tsx:202 +msgid "You haven't muted any words or tags yet" +msgstr "" + #: src/view/com/modals/ContentFilteringSettings.tsx:175 msgid "You must be 18 or older to enable adult content." msgstr "" @@ -4556,11 +4717,11 @@ msgstr "" msgid "You must be 18 years or older to enable adult content" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:127 +#: src/view/com/util/forms/PostDropdownBtn.tsx:129 msgid "You will no longer receive notifications for this thread" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:130 +#: src/view/com/util/forms/PostDropdownBtn.tsx:132 msgid "You will now receive notifications for this thread" msgstr "" @@ -4646,11 +4807,15 @@ msgstr "" #~ msgid "Your invite codes are hidden when logged in using an App Password" #~ msgstr "" +#: src/components/dialogs/MutedWords.tsx:173 +msgid "Your muted words" +msgstr "" + #: src/view/com/modals/ChangePassword.tsx:155 msgid "Your password has been changed successfully!" msgstr "" -#: src/view/com/composer/Composer.tsx:267 +#: src/view/com/composer/Composer.tsx:274 msgid "Your post has been published" msgstr "" @@ -4665,7 +4830,7 @@ msgstr "" msgid "Your profile" msgstr "" -#: src/view/com/composer/Composer.tsx:266 +#: src/view/com/composer/Composer.tsx:273 msgid "Your reply has been published" msgstr "" diff --git a/src/locale/locales/es/messages.po b/src/locale/locales/es/messages.po index b0689cb5a5..fed1beb6cb 100644 --- a/src/locale/locales/es/messages.po +++ b/src/locale/locales/es/messages.po @@ -76,7 +76,7 @@ msgid "A new version of the app is available. Please update to continue using th msgstr "Ya estĆ” disponible una nueva versión de la aplicación. ActualĆ­zala para seguir utilizĆ”ndola." #: src/view/com/util/ViewHeader.tsx:83 -#: src/view/screens/Search/Search.tsx:624 +#: src/view/screens/Search/Search.tsx:647 msgid "Access navigation links and settings" msgstr "" @@ -127,6 +127,7 @@ msgstr "" msgid "Account unmuted" msgstr "" +#: src/components/dialogs/MutedWords.tsx:147 #: src/view/com/auth/onboarding/RecommendedFeedsItem.tsx:150 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -168,14 +169,22 @@ msgstr "Agregar detalles" msgid "Add details to report" msgstr "Agregar detalles al informe" -#: src/view/com/composer/Composer.tsx:446 +#: src/view/com/composer/Composer.tsx:453 msgid "Add link card" msgstr "Agregar una tarjeta de enlace" -#: src/view/com/composer/Composer.tsx:451 +#: src/view/com/composer/Composer.tsx:458 msgid "Add link card:" msgstr "Agregar una tarjeta de enlace:" +#: src/components/dialogs/MutedWords.tsx:140 +msgid "Add mute word for configured settings" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:74 +msgid "Add muted words and tags" +msgstr "" + #: src/view/com/modals/ChangeHandle.tsx:417 msgid "Add the following DNS record to your domain:" msgstr "AƱade el siguiente registro DNS a tu dominio:" @@ -299,7 +308,7 @@ msgstr "" msgid "App Passwords" msgstr "ContraseƱas de la app" -#: src/view/com/util/forms/PostDropdownBtn.tsx:279 +#: src/view/com/util/forms/PostDropdownBtn.tsx:295 msgid "Appeal content warning" msgstr "Aviso sobre el contenido del recurso" @@ -323,15 +332,16 @@ msgstr "Aspecto exterior" msgid "Are you sure you want to delete the app password \"{name}\"?" msgstr "ĀæEstĆ”s seguro de que quieres eliminar la contraseƱa de la app \"{name}\"?" -#: src/view/com/composer/Composer.tsx:143 +#: src/view/com/composer/Composer.tsx:150 msgid "Are you sure you'd like to discard this draft?" msgstr "ĀæEstĆ”s seguro de que quieres descartar este borrador?" +#: src/components/dialogs/MutedWords.tsx:233 #: src/view/screens/ProfileList.tsx:365 msgid "Are you sure?" msgstr "ĀæEstĆ”s seguro?" -#: src/view/com/util/forms/PostDropdownBtn.tsx:262 +#: src/view/com/util/forms/PostDropdownBtn.tsx:278 msgid "Are you sure? This cannot be undone." msgstr "ĀæEstĆ”s seguro? Esto no puede deshacerse." @@ -353,15 +363,15 @@ msgstr "Desnudez artĆ­stica o no erótica." #: src/view/com/auth/login/LoginForm.tsx:259 #: src/view/com/auth/login/SetNewPasswordForm.tsx:179 #: src/view/com/modals/report/InputIssueDetails.tsx:46 -#: src/view/com/post-thread/PostThread.tsx:471 -#: src/view/com/post-thread/PostThread.tsx:521 -#: src/view/com/post-thread/PostThread.tsx:529 +#: src/view/com/post-thread/PostThread.tsx:472 +#: src/view/com/post-thread/PostThread.tsx:522 +#: src/view/com/post-thread/PostThread.tsx:530 #: src/view/com/profile/ProfileHeader.tsx:649 #: src/view/com/util/ViewHeader.tsx:81 msgid "Back" msgstr "Regresar" -#: src/view/com/post-thread/PostThread.tsx:479 +#: src/view/com/post-thread/PostThread.tsx:480 msgctxt "action" msgid "Back" msgstr "" @@ -409,7 +419,7 @@ msgstr "" msgid "Blocked" msgstr "" -#: src/view/screens/Moderation.tsx:123 +#: src/view/screens/Moderation.tsx:142 msgid "Blocked accounts" msgstr "Cuentas bloqueadas" @@ -468,7 +478,7 @@ msgstr "Bluesky es pĆŗblico." msgid "Bluesky uses invites to build a healthier community. If you don't know anybody with an invite, you can sign up for the waitlist and we'll send one soon." msgstr "Bluesky utiliza las invitaciones para construir una comunidad mĆ”s saludable. Si no conoces a nadie con una invitación, puedes apuntarte a la lista de espera y te enviaremos una en breve." -#: src/view/screens/Moderation.tsx:226 +#: src/view/screens/Moderation.tsx:245 msgid "Bluesky will not show your profile and posts to logged-out users. Other apps may not honor this request. This does not make your account private." msgstr "Bluesky no mostrarĆ” tu perfil ni tus publicaciones a los usuarios que hayan cerrado sesión. Es posible que otras aplicaciones no acepten esta solicitud. Esto no hace que tu cuenta sea privada." @@ -520,8 +530,8 @@ msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must msgstr "Sólo puede contener letras, nĆŗmeros, espacios, guiones y guiones bajos. Debe tener al menos 4 caracteres, pero no mĆ”s de 32." #: src/components/Prompt.tsx:91 -#: src/view/com/composer/Composer.tsx:300 -#: src/view/com/composer/Composer.tsx:305 +#: src/view/com/composer/Composer.tsx:307 +#: src/view/com/composer/Composer.tsx:312 #: src/view/com/modals/ChangeEmail.tsx:218 #: src/view/com/modals/ChangeEmail.tsx:220 #: src/view/com/modals/ChangePassword.tsx:265 @@ -535,7 +545,7 @@ msgstr "Sólo puede contener letras, nĆŗmeros, espacios, guiones y guiones bajos #: src/view/com/modals/VerifyEmail.tsx:247 #: src/view/com/modals/VerifyEmail.tsx:253 #: src/view/com/modals/Waitlist.tsx:142 -#: src/view/screens/Search/Search.tsx:693 +#: src/view/screens/Search/Search.tsx:716 #: src/view/shell/desktop/Search.tsx:238 msgid "Cancel" msgstr "Cancelar" @@ -686,7 +696,7 @@ msgid "Clear all storage data (restart after this)" msgstr "Borrar todos los datos de almacenamiento (reiniciar despuĆ©s de esto)" #: src/view/com/util/forms/SearchInput.tsx:88 -#: src/view/screens/Search/Search.tsx:674 +#: src/view/screens/Search/Search.tsx:697 msgid "Clear search query" msgstr "Borrar consulta de bĆŗsqueda" @@ -694,6 +704,11 @@ msgstr "Borrar consulta de bĆŗsqueda" msgid "click here" msgstr "" +#: src/components/RichText.tsx:189 +#: src/components/TagMenu/index.web.tsx:125 +msgid "Click here to open tag menu for {tag}" +msgstr "" + #: src/screens/Onboarding/index.tsx:35 msgid "Climate" msgstr "" @@ -724,11 +739,15 @@ msgstr "Cerrar la imagen" msgid "Close image viewer" msgstr "Cerrar el visor de imagen" -#: src/view/shell/index.web.tsx:49 +#: src/view/shell/index.web.tsx:51 msgid "Close navigation footer" msgstr "Cerrar el pie de pĆ”gina de navegación" -#: src/view/shell/index.web.tsx:50 +#: src/components/TagMenu/index.tsx:266 +msgid "Close this dialog" +msgstr "" + +#: src/view/shell/index.web.tsx:52 msgid "Closes bottom navigation bar" msgstr "" @@ -736,7 +755,7 @@ msgstr "" msgid "Closes password update alert" msgstr "" -#: src/view/com/composer/Composer.tsx:302 +#: src/view/com/composer/Composer.tsx:309 msgid "Closes post composer and discards post draft" msgstr "" @@ -769,7 +788,7 @@ msgstr "" msgid "Complete the challenge" msgstr "" -#: src/view/com/composer/Composer.tsx:417 +#: src/view/com/composer/Composer.tsx:424 msgid "Compose posts up to {MAX_GRAPHEME_LENGTH} characters in length" msgstr "" @@ -833,7 +852,7 @@ msgstr "Conectando..." msgid "Contact support" msgstr "" -#: src/view/screens/Moderation.tsx:81 +#: src/view/screens/Moderation.tsx:83 msgid "Content filtering" msgstr "Filtro de contenido" @@ -899,7 +918,7 @@ msgstr "" #: src/view/com/modals/AddAppPasswords.tsx:76 #: src/view/com/modals/InviteCodes.tsx:152 -#: src/view/com/util/forms/PostDropdownBtn.tsx:141 +#: src/view/com/util/forms/PostDropdownBtn.tsx:143 msgid "Copied to clipboard" msgstr "" @@ -915,7 +934,7 @@ msgstr "Copiar" msgid "Copy link to list" msgstr "Copia el enlace a la lista" -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 msgid "Copy link to post" msgstr "Copia el enlace a la publicación" @@ -923,7 +942,7 @@ msgstr "Copia el enlace a la publicación" msgid "Copy link to profile" msgstr "Copia el enlace al perfil" -#: src/view/com/util/forms/PostDropdownBtn.tsx:168 +#: src/view/com/util/forms/PostDropdownBtn.tsx:170 msgid "Copy post text" msgstr "Copiar el texto de la publicación" @@ -979,7 +998,7 @@ msgstr "" msgid "Created by you" msgstr "" -#: src/view/com/composer/Composer.tsx:448 +#: src/view/com/composer/Composer.tsx:455 msgid "Creates a card with a thumbnail. The card links to {url}" msgstr "" @@ -1056,11 +1075,11 @@ msgstr "Borrar mi cuenta" msgid "Delete My Account…" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:257 +#: src/view/com/util/forms/PostDropdownBtn.tsx:273 msgid "Delete post" msgstr "Borrar una publicación" -#: src/view/com/util/forms/PostDropdownBtn.tsx:261 +#: src/view/com/util/forms/PostDropdownBtn.tsx:277 msgid "Delete this post?" msgstr "ĀæBorrar esta publicación?" @@ -1083,7 +1102,7 @@ msgstr "Descripción" #~ msgid "Developer Tools" #~ msgstr "Herramientas de desarrollador" -#: src/view/com/composer/Composer.tsx:211 +#: src/view/com/composer/Composer.tsx:218 msgid "Did you want to say anything?" msgstr "ĀæQuieres decir algo?" @@ -1091,15 +1110,15 @@ msgstr "ĀæQuieres decir algo?" msgid "Dim" msgstr "" -#: src/view/com/composer/Composer.tsx:144 +#: src/view/com/composer/Composer.tsx:151 msgid "Discard" msgstr "Descartar" -#: src/view/com/composer/Composer.tsx:138 +#: src/view/com/composer/Composer.tsx:145 msgid "Discard draft" msgstr "Descartar el borrador" -#: src/view/screens/Moderation.tsx:207 +#: src/view/screens/Moderation.tsx:226 msgid "Discourage apps from showing my account to logged-out users" msgstr "Evitar que las aplicaciones muestren mi cuenta a los usuarios desconectados" @@ -1178,7 +1197,7 @@ msgstr "" msgid "Download CAR file" msgstr "" -#: src/view/com/composer/text-input/TextInput.web.tsx:247 +#: src/view/com/composer/text-input/TextInput.web.tsx:249 msgid "Drop to add images" msgstr "" @@ -1250,6 +1269,7 @@ msgstr "Editar el perfil" msgid "Edit Profile" msgstr "Editar el perfil" +#: src/view/com/home/HomeHeaderLayout.web.tsx:59 #: src/view/screens/Feeds.tsx:355 msgid "Edit Saved Feeds" msgstr "Editar mis noticias guardadas" @@ -1332,6 +1352,11 @@ msgstr "Fin de noticias" msgid "Enter a name for this App Password" msgstr "" +#: src/components/dialogs/MutedWords.tsx:87 +#: src/components/dialogs/MutedWords.tsx:88 +msgid "Enter a word or tag" +msgstr "" + #: src/view/com/modals/VerifyEmail.tsx:105 msgid "Enter Confirmation Code" msgstr "" @@ -1381,7 +1406,7 @@ msgstr "Introduce tu nombre de usuario y contraseƱa" msgid "Error receiving captcha response." msgstr "" -#: src/view/screens/Search/Search.tsx:109 +#: src/view/screens/Search/Search.tsx:110 msgid "Error:" msgstr "Error:" @@ -1452,7 +1477,7 @@ msgstr "" msgid "Failed to create the list. Check your internet connection and try again." msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:108 +#: src/view/com/util/forms/PostDropdownBtn.tsx:110 msgid "Failed to delete post, please try again" msgstr "" @@ -1474,8 +1499,8 @@ msgid "Feed offline" msgstr "Noticias fuera de lĆ­nea" #: src/view/com/feeds/FeedPage.tsx:143 -msgid "Feed Preferences" -msgstr "Preferencias de noticias" +#~ msgid "Feed Preferences" +#~ msgstr "Preferencias de noticias" #: src/view/shell/desktop/RightNav.tsx:61 #: src/view/shell/Drawer.tsx:311 @@ -1523,11 +1548,11 @@ msgstr "" msgid "Find accounts to follow" msgstr "" -#: src/view/screens/Search/Search.tsx:439 +#: src/view/screens/Search/Search.tsx:440 msgid "Find users on Bluesky" msgstr "Encontrar usuarios en Bluesky" -#: src/view/screens/Search/Search.tsx:437 +#: src/view/screens/Search/Search.tsx:438 msgid "Find users with the search tool on the right" msgstr "Encuentra usuarios con la herramienta de bĆŗsqueda de la derecha" @@ -1624,6 +1649,7 @@ msgid "Following {0}" msgstr "" #: src/Navigation.tsx:248 +#: src/view/com/home/HomeHeaderLayout.web.tsx:45 #: src/view/com/home/HomeHeaderLayoutMobile.tsx:83 #: src/view/screens/PreferencesFollowingFeed.tsx:104 #: src/view/screens/Settings/index.tsx:543 @@ -1663,7 +1689,7 @@ msgstr "OlvidĆ© mi contraseƱa" msgid "Forgot Password" msgstr "OlvidĆ© mi contraseƱa" -#: src/view/com/posts/FeedItem.tsx:187 +#: src/view/com/posts/FeedItem.tsx:189 msgctxt "from-feed" msgid "From <0/>" msgstr "" @@ -1696,7 +1722,7 @@ msgstr "Regresar" msgid "Go back to previous step" msgstr "" -#: src/view/screens/Search/Search.tsx:724 +#: src/view/screens/Search/Search.tsx:747 #: src/view/shell/desktop/Search.tsx:262 msgid "Go to @{queryMaybeHandle}" msgstr "" @@ -1713,6 +1739,10 @@ msgstr "Ir al siguiente" msgid "Handle" msgstr "Identificador" +#: src/components/RichText.tsx:188 +msgid "Hashtag: {tag}" +msgstr "" + #: src/view/com/auth/create/CreateAccount.tsx:208 msgid "Having trouble?" msgstr "" @@ -1751,7 +1781,7 @@ msgctxt "action" msgid "Hide" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +#: src/view/com/util/forms/PostDropdownBtn.tsx:232 msgid "Hide post" msgstr "Ocultar publicación" @@ -1760,7 +1790,7 @@ msgstr "Ocultar publicación" msgid "Hide the content" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:220 +#: src/view/com/util/forms/PostDropdownBtn.tsx:236 msgid "Hide this post?" msgstr "ĀæOcultar esta publicación?" @@ -1909,7 +1939,7 @@ msgstr "" msgid "Input your user handle" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:224 +#: src/view/com/post-thread/PostThreadItem.tsx:226 msgid "Invalid or unsupported post record" msgstr "" @@ -2011,7 +2041,7 @@ msgstr "Aprender mĆ”s" msgid "Learn more about this warning" msgstr "Aprender mĆ”s acerca de esta advertencia" -#: src/view/screens/Moderation.tsx:243 +#: src/view/screens/Moderation.tsx:262 msgid "Learn more about what is public on Bluesky." msgstr "MĆ”s información sobre lo que es pĆŗblico en Bluesky." @@ -2087,7 +2117,7 @@ msgstr "" msgid "Likes" msgstr "Cantidad de Ā«Me gustaĀ»" -#: src/view/com/post-thread/PostThreadItem.tsx:181 +#: src/view/com/post-thread/PostThreadItem.tsx:183 msgid "Likes on this post" msgstr "" @@ -2144,7 +2174,7 @@ msgstr "Cargar mĆ”s publicaciones" msgid "Load new notifications" msgstr "Cargar notificaciones nuevas" -#: src/view/com/feeds/FeedPage.tsx:181 +#: src/view/com/feeds/FeedPage.tsx:115 #: src/view/screens/Profile.tsx:440 #: src/view/screens/ProfileFeed.tsx:495 #: src/view/screens/ProfileList.tsx:681 @@ -2170,7 +2200,7 @@ msgstr "" msgid "Log out" msgstr "" -#: src/view/screens/Moderation.tsx:136 +#: src/view/screens/Moderation.tsx:155 msgid "Logged-out visibility" msgstr "Visibilidad de desconexión" @@ -2182,6 +2212,10 @@ msgstr "Acceder a una cuenta que no estĆ” en la lista" msgid "Make sure this is where you intend to go!" msgstr "Ā”AsegĆŗrate de que es aquĆ­ a donde pretendes ir!" +#: src/components/dialogs/MutedWords.tsx:71 +msgid "Manage your muted words and tags" +msgstr "" + #: src/view/com/auth/create/Step2.tsx:118 msgid "May not be longer than 253 characters" msgstr "" @@ -2203,7 +2237,7 @@ msgid "Mentioned users" msgstr "Usuarios mencionados" #: src/view/com/util/ViewHeader.tsx:81 -#: src/view/screens/Search/Search.tsx:623 +#: src/view/screens/Search/Search.tsx:646 msgid "Menu" msgstr "MenĆŗ" @@ -2212,7 +2246,7 @@ msgid "Message from server: {0}" msgstr "Mensaje del servidor: {0}" #: src/Navigation.tsx:115 -#: src/view/screens/Moderation.tsx:64 +#: src/view/screens/Moderation.tsx:66 #: src/view/screens/Settings/index.tsx:625 #: src/view/shell/desktop/LeftNav.tsx:397 #: src/view/shell/Drawer.tsx:511 @@ -2243,7 +2277,7 @@ msgstr "" msgid "Moderation list updated" msgstr "" -#: src/view/screens/Moderation.tsx:95 +#: src/view/screens/Moderation.tsx:114 msgid "Moderation lists" msgstr "Listas de moderación" @@ -2270,7 +2304,7 @@ msgstr "MĆ”s canales de noticias" msgid "More options" msgstr "MĆ”s opciones" -#: src/view/com/util/forms/PostDropdownBtn.tsx:299 +#: src/view/com/util/forms/PostDropdownBtn.tsx:315 msgid "More post options" msgstr "" @@ -2282,6 +2316,14 @@ msgstr "" msgid "Must be at least 3 characters" msgstr "" +#: src/components/TagMenu/index.tsx:253 +msgid "Mute" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:91 +msgid "Mute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:327 msgid "Mute Account" msgstr "Silenciar la cuenta" @@ -2290,6 +2332,18 @@ msgstr "Silenciar la cuenta" msgid "Mute accounts" msgstr "Silenciar las cuentas" +#: src/components/TagMenu/index.tsx:211 +msgid "Mute all {tag} posts" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:131 +msgid "Mute in tags only" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:116 +msgid "Mute in text & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:491 msgid "Mute list" msgstr "Silenciar la lista" @@ -2302,15 +2356,27 @@ msgstr "ĀæSilenciar estas cuentas?" msgid "Mute this List" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/dialogs/MutedWords.tsx:109 +msgid "Mute this word in post text and tags" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:124 +msgid "Mute this word in tags only" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Mute thread" msgstr "Silenciar el hilo" +#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +msgid "Mute words & tags" +msgstr "" + #: src/view/com/lists/ListCard.tsx:102 msgid "Muted" msgstr "" -#: src/view/screens/Moderation.tsx:109 +#: src/view/screens/Moderation.tsx:128 msgid "Muted accounts" msgstr "Cuentas silenciadas" @@ -2323,6 +2389,10 @@ msgstr "Cuentas silenciadas" msgid "Muted accounts have their posts removed from your feed and from your notifications. Mutes are completely private." msgstr "Las cuentas silenciadas eliminan sus publicaciones de tu canal de noticias y de tus notificaciones. Las cuentas silenciadas son completamente privadas." +#: src/view/screens/Moderation.tsx:100 +msgid "Muted words & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:277 msgid "Muting is private. Muted accounts can interact with you, but you will not see their posts or receive notifications from them." msgstr "Silenciar es privado. Las cuentas silenciadas pueden interactuar contigo, pero no verĆ”s sus publicaciones ni recibirĆ”s notificaciones suyas." @@ -2386,6 +2456,10 @@ msgstr "No pierdas nunca el acceso a tus seguidores y datos." msgid "Never lose access to your followers or data." msgstr "" +#: src/components/dialogs/MutedWords.tsx:244 +msgid "Nevermind" +msgstr "" + #: src/view/screens/Lists.tsx:76 msgctxt "action" msgid "New" @@ -2407,7 +2481,7 @@ msgstr "" msgid "New Password" msgstr "" -#: src/view/com/feeds/FeedPage.tsx:192 +#: src/view/com/feeds/FeedPage.tsx:126 msgctxt "action" msgid "New post" msgstr "" @@ -2492,8 +2566,8 @@ msgid "No results found for \"{query}\"" msgstr "No se han encontrado resultados para \"{query}\"" #: src/view/com/modals/ListAddRemoveUsers.tsx:127 -#: src/view/screens/Search/Search.tsx:280 -#: src/view/screens/Search/Search.tsx:308 +#: src/view/screens/Search/Search.tsx:281 +#: src/view/screens/Search/Search.tsx:309 msgid "No results found for {query}" msgstr "No se han encontrado resultados para {query}" @@ -2519,7 +2593,7 @@ msgstr "" msgid "Not right now" msgstr "" -#: src/view/screens/Moderation.tsx:233 +#: src/view/screens/Moderation.tsx:252 msgid "Note: Bluesky is an open and public network. This setting only limits the visibility of your content on the Bluesky app and website, and other apps may not respect this setting. Your content may still be shown to logged-out users by other apps and websites." msgstr "Nota: Bluesky es una red abierta y pĆŗblica. Esta configuración sólo limita la visibilidad de tu contenido en la aplicación y el sitio web de Bluesky, y es posible que otras aplicaciones no respeten esta configuración. Otras aplicaciones y sitios web pueden seguir mostrando tu contenido a los usuarios que hayan cerrado sesión." @@ -2557,7 +2631,7 @@ msgstr "" msgid "Onboarding reset" msgstr "" -#: src/view/com/composer/Composer.tsx:375 +#: src/view/com/composer/Composer.tsx:382 msgid "One or more images is missing alt text." msgstr "Falta el texto alternativo en una o varias imĆ”genes." @@ -2574,8 +2648,12 @@ msgstr "" msgid "Open" msgstr "" -#: src/view/com/composer/Composer.tsx:470 -#: src/view/com/composer/Composer.tsx:471 +#: src/view/screens/Moderation.tsx:75 +msgid "Open content filtering settings" +msgstr "" + +#: src/view/com/composer/Composer.tsx:477 +#: src/view/com/composer/Composer.tsx:478 msgid "Open emoji picker" msgstr "" @@ -2583,6 +2661,10 @@ msgstr "" msgid "Open links with in-app browser" msgstr "" +#: src/view/screens/Moderation.tsx:92 +msgid "Open muted words settings" +msgstr "" + #: src/view/com/home/HomeHeaderLayoutMobile.tsx:49 msgid "Open navigation" msgstr "Abrir navegación" @@ -2659,6 +2741,7 @@ msgstr "Abre la configuración de moderación" msgid "Opens password reset form" msgstr "" +#: src/view/com/home/HomeHeaderLayout.web.tsx:60 #: src/view/screens/Feeds.tsx:356 msgid "Opens screen to edit Saved Feeds" msgstr "" @@ -2834,7 +2917,7 @@ msgstr "Por favor, dinos por quĆ© crees que esta advertencia de contenido se ha msgid "Please Verify Your Email" msgstr "" -#: src/view/com/composer/Composer.tsx:215 +#: src/view/com/composer/Composer.tsx:222 msgid "Please wait for your link card to finish loading" msgstr "Por favor, espera a que tu tarjeta de enlace termine de cargarse" @@ -2846,8 +2929,8 @@ msgstr "" msgid "Porn" msgstr "" -#: src/view/com/composer/Composer.tsx:350 -#: src/view/com/composer/Composer.tsx:358 +#: src/view/com/composer/Composer.tsx:357 +#: src/view/com/composer/Composer.tsx:365 msgctxt "action" msgid "Post" msgstr "" @@ -2857,7 +2940,7 @@ msgctxt "description" msgid "Post" msgstr "Publicación" -#: src/view/com/post-thread/PostThreadItem.tsx:173 +#: src/view/com/post-thread/PostThreadItem.tsx:175 msgid "Post by {0}" msgstr "" @@ -2867,11 +2950,11 @@ msgstr "" msgid "Post by @{0}" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:88 +#: src/view/com/util/forms/PostDropdownBtn.tsx:90 msgid "Post deleted" msgstr "" -#: src/view/com/post-thread/PostThread.tsx:461 +#: src/view/com/post-thread/PostThread.tsx:462 msgid "Post hidden" msgstr "Publicación oculta" @@ -2883,14 +2966,22 @@ msgstr "Lenguaje de la publicación" msgid "Post Languages" msgstr "Lenguajes de la publicación" -#: src/view/com/post-thread/PostThread.tsx:513 +#: src/view/com/post-thread/PostThread.tsx:514 msgid "Post not found" msgstr "Publicación no encontrada" +#: src/components/TagMenu/index.tsx:257 +msgid "posts" +msgstr "" + #: src/view/screens/Profile.tsx:180 msgid "Posts" msgstr "Publicaciones" +#: src/components/dialogs/MutedWords.tsx:77 +msgid "Posts can be muted based on their text, their tags, or both." +msgstr "" + #: src/view/com/posts/FeedErrorMessage.tsx:64 msgid "Posts hidden" msgstr "" @@ -2955,11 +3046,11 @@ msgstr "Listas pĆŗblicas y compartibles de usuarios para silenciar o bloquear en msgid "Public, shareable lists which can drive feeds." msgstr "Listas pĆŗblicas y compartibles que pueden impulsar las noticias." -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish post" msgstr "" -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish reply" msgstr "" @@ -2993,6 +3084,7 @@ msgstr "Canales de noticias recomendados" msgid "Recommended Users" msgstr "Usuarios recomendados" +#: src/components/dialogs/MutedWords.tsx:249 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/SelfLabel.tsx:83 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -3030,6 +3122,10 @@ msgstr "Eliminar la imagen" msgid "Remove image preview" msgstr "Eliminar la vista previa de la imagen" +#: src/components/dialogs/MutedWords.tsx:294 +msgid "Remove mute word from your list" +msgstr "" + #: src/view/com/modals/Repost.tsx:47 msgid "Remove repost" msgstr "" @@ -3064,7 +3160,7 @@ msgstr "Respuestas" msgid "Replies to this thread are disabled" msgstr "Las respuestas a este hilo estĆ”n desactivadas" -#: src/view/com/composer/Composer.tsx:348 +#: src/view/com/composer/Composer.tsx:355 msgctxt "action" msgid "Reply" msgstr "" @@ -3074,7 +3170,7 @@ msgid "Reply Filters" msgstr "Filtros de respuestas" #: src/view/com/post/Post.tsx:167 -#: src/view/com/posts/FeedItem.tsx:285 +#: src/view/com/posts/FeedItem.tsx:287 msgctxt "description" msgid "Reply to <0/>" msgstr "" @@ -3096,7 +3192,7 @@ msgid "Report List" msgstr "Informe de la lista" #: src/view/com/modals/report/SendReportButton.tsx:37 -#: src/view/com/util/forms/PostDropdownBtn.tsx:239 +#: src/view/com/util/forms/PostDropdownBtn.tsx:255 msgid "Report post" msgstr "Informe de la publicación" @@ -3121,11 +3217,11 @@ msgstr "Volver a publicar o citar publicación" msgid "Reposted By" msgstr "Vuelto a publicar por" -#: src/view/com/posts/FeedItem.tsx:205 +#: src/view/com/posts/FeedItem.tsx:207 msgid "Reposted by {0}" msgstr "Vuelto a publicar por {0}" -#: src/view/com/posts/FeedItem.tsx:222 +#: src/view/com/posts/FeedItem.tsx:224 msgid "Reposted by <0/>" msgstr "Vuelto a publicar por <0/>" @@ -3133,7 +3229,7 @@ msgstr "Vuelto a publicar por <0/>" msgid "reposted your post" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:186 +#: src/view/com/post-thread/PostThreadItem.tsx:188 msgid "Reposts of this post" msgstr "" @@ -3284,9 +3380,9 @@ msgstr "" #: src/view/com/modals/ListAddRemoveUsers.tsx:75 #: src/view/com/util/forms/SearchInput.tsx:67 #: src/view/com/util/forms/SearchInput.tsx:79 -#: src/view/screens/Search/Search.tsx:418 -#: src/view/screens/Search/Search.tsx:645 -#: src/view/screens/Search/Search.tsx:663 +#: src/view/screens/Search/Search.tsx:419 +#: src/view/screens/Search/Search.tsx:668 +#: src/view/screens/Search/Search.tsx:686 #: src/view/shell/bottom-bar/BottomBar.tsx:159 #: src/view/shell/desktop/LeftNav.tsx:324 #: src/view/shell/desktop/Search.tsx:214 @@ -3296,11 +3392,19 @@ msgstr "" msgid "Search" msgstr "Buscar" -#: src/view/screens/Search/Search.tsx:712 +#: src/view/screens/Search/Search.tsx:735 #: src/view/shell/desktop/Search.tsx:255 msgid "Search for \"{query}\"" msgstr "" +#: src/components/TagMenu/index.tsx:145 +msgid "Search for all posts by @{authorHandle} with tag {tag}" +msgstr "" + +#: src/components/TagMenu/index.tsx:90 +msgid "Search for all posts with tag {tag}" +msgstr "" + #: src/view/com/auth/LoggedOut.tsx:104 #: src/view/com/auth/LoggedOut.tsx:105 #: src/view/com/modals/ListAddRemoveUsers.tsx:70 @@ -3311,6 +3415,22 @@ msgstr "Buscar usuarios" msgid "Security Step Required" msgstr "Se requiere un paso de seguridad" +#: src/components/TagMenu/index.web.tsx:50 +msgid "See {truncatedTag} posts" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:67 +msgid "See {truncatedTag} posts by user" +msgstr "" + +#: src/components/TagMenu/index.tsx:128 +msgid "See <0>{tag} posts" +msgstr "" + +#: src/components/TagMenu/index.tsx:189 +msgid "See <0>{tag} posts by this user" +msgstr "" + #: src/view/screens/SavedFeeds.tsx:163 msgid "See this guide" msgstr "" @@ -3520,7 +3640,7 @@ msgid "Share" msgstr "" #: src/view/com/profile/ProfileHeader.tsx:295 -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 #: src/view/screens/ProfileList.tsx:418 msgid "Share" msgstr "Compartir" @@ -3553,9 +3673,9 @@ msgstr "" msgid "Show follows similar to {0}" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:532 -#: src/view/com/post/Post.tsx:196 -#: src/view/com/posts/FeedItem.tsx:359 +#: src/view/com/post-thread/PostThreadItem.tsx:538 +#: src/view/com/post/Post.tsx:198 +#: src/view/com/posts/FeedItem.tsx:363 msgid "Show More" msgstr "" @@ -3723,7 +3843,7 @@ msgstr "" msgid "Something went wrong. Check your email and try again." msgstr "" -#: src/App.native.tsx:61 +#: src/App.native.tsx:63 msgid "Sorry! Your session expired. Please log in again." msgstr "" @@ -3781,7 +3901,7 @@ msgstr "" msgid "Subscribe to this list" msgstr "Suscribirse a esta lista" -#: src/view/screens/Search/Search.tsx:373 +#: src/view/screens/Search/Search.tsx:374 msgid "Suggested Follows" msgstr "Usuarios sugeridos a seguir" @@ -3825,6 +3945,14 @@ msgstr "" msgid "System log" msgstr "BitĆ”cora del sistema" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "tag" +msgstr "" + +#: src/components/TagMenu/index.tsx:74 +msgid "Tag menu: {tag}" +msgstr "" + #: src/view/com/modals/crop-image/CropImage.web.tsx:112 msgid "Tall" msgstr "Alto" @@ -3848,6 +3976,10 @@ msgstr "Condiciones" msgid "Terms of Service" msgstr "Condiciones de servicio" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "text" +msgstr "" + #: src/view/com/modals/AppealLabel.tsx:70 #: src/view/com/modals/report/InputIssueDetails.tsx:51 msgid "Text input field" @@ -3873,7 +4005,7 @@ msgstr "La PolĆ­tica de derechos de autor se han trasladado a <0/>" msgid "The following steps will help customize your Bluesky experience." msgstr "" -#: src/view/com/post-thread/PostThread.tsx:516 +#: src/view/com/post-thread/PostThread.tsx:517 msgid "The post may have been deleted." msgstr "Es posible que se haya borrado la publicación." @@ -4039,7 +4171,7 @@ msgstr "" msgid "This name is already in use" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:123 +#: src/view/com/post-thread/PostThreadItem.tsx:125 msgid "This post has been deleted." msgstr "Esta publicación ha sido eliminada." @@ -4063,7 +4195,11 @@ msgstr "" msgid "This warning is only available for posts with media attached." msgstr "Esta advertencia sólo estĆ” disponible para las publicaciones con medios adjuntos." -#: src/view/com/util/forms/PostDropdownBtn.tsx:221 +#: src/components/dialogs/MutedWords.tsx:236 +msgid "This will delete {0} from your muted words. You can always add it back later." +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:237 msgid "This will hide this post from your feeds." msgstr "Esto ocultarĆ” esta entrada de tus contenidos." @@ -4080,6 +4216,10 @@ msgstr "Modo con hilos" msgid "Threads Preferences" msgstr "" +#: src/components/dialogs/MutedWords.tsx:95 +msgid "Toggle between muted word options." +msgstr "" + #: src/view/com/util/forms/DropdownButton.tsx:246 msgid "Toggle dropdown" msgstr "Conmutar el menĆŗ desplegable" @@ -4088,9 +4228,9 @@ msgstr "Conmutar el menĆŗ desplegable" msgid "Transformations" msgstr "Transformaciones" -#: src/view/com/post-thread/PostThreadItem.tsx:679 -#: src/view/com/post-thread/PostThreadItem.tsx:681 -#: src/view/com/util/forms/PostDropdownBtn.tsx:154 +#: src/view/com/post-thread/PostThreadItem.tsx:685 +#: src/view/com/post-thread/PostThreadItem.tsx:687 +#: src/view/com/util/forms/PostDropdownBtn.tsx:156 msgid "Translate" msgstr "Traducir" @@ -4155,15 +4295,24 @@ msgstr "Lamentablemente, no cumples los requisitos para crear una cuenta." msgid "Unlike" msgstr "" +#: src/components/TagMenu/index.tsx:253 #: src/view/screens/ProfileList.tsx:597 msgid "Unmute" msgstr "" +#: src/components/TagMenu/index.web.tsx:90 +msgid "Unmute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:326 msgid "Unmute Account" msgstr "Desactivar la opción de silenciar la cuenta" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/TagMenu/index.tsx:210 +msgid "Unmute all {tag} posts" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Unmute thread" msgstr "Desactivar la opción de silenciar el hilo" @@ -4364,6 +4513,10 @@ msgstr "" #~ msgid "We recommend \"For You\" by Skygaze:" #~ msgstr "" +#: src/components/dialogs/MutedWords.tsx:161 +msgid "We recommend avoiding common words that appear in many posts, since it can result in no posts being shown." +msgstr "" + #: src/screens/Onboarding/StepAlgoFeeds/index.tsx:124 msgid "We recommend our \"Discover\" feed:" msgstr "" @@ -4392,7 +4545,11 @@ msgstr "Ā”Nos hace mucha ilusión que te unas a nosotros!" msgid "We're sorry, but we were unable to resolve this list. If this persists, please contact the list creator, @{handleOrDid}." msgstr "" -#: src/view/screens/Search/Search.tsx:253 +#: src/components/dialogs/MutedWords.tsx:182 +msgid "We're sorry, but we weren't able to load your muted words at this time. Please try again." +msgstr "" + +#: src/view/screens/Search/Search.tsx:254 msgid "We're sorry, but your search could not be completed. Please try again in a few minutes." msgstr "Lo sentimos, pero no se ha podido completar tu bĆŗsqueda. Vuelve a intentarlo dentro de unos minutos." @@ -4413,7 +4570,7 @@ msgid "What is the issue with this {collectionName}?" msgstr "ĀæCuĆ”l es el problema con esta {collectionName}?" #: src/view/com/auth/SplashScreen.tsx:59 -#: src/view/com/composer/Composer.tsx:279 +#: src/view/com/composer/Composer.tsx:286 msgid "What's up?" msgstr "ĀæQuĆ© hay de nuevo?" @@ -4434,11 +4591,11 @@ msgstr "QuiĆ©n puede responder" msgid "Wide" msgstr "Ancho" -#: src/view/com/composer/Composer.tsx:415 +#: src/view/com/composer/Composer.tsx:422 msgid "Write post" msgstr "Redactar una publicación" -#: src/view/com/composer/Composer.tsx:278 +#: src/view/com/composer/Composer.tsx:285 #: src/view/com/composer/Prompt.tsx:33 msgid "Write your reply" msgstr "Redactar tu respuesta" @@ -4503,7 +4660,7 @@ msgstr "Ā”No tienes ninguna noticia guardada!" msgid "You don't have any saved feeds." msgstr "No tienes ninguna noticia guardada." -#: src/view/com/post-thread/PostThread.tsx:464 +#: src/view/com/post-thread/PostThread.tsx:465 msgid "You have blocked the author or you have been blocked by the author." msgstr "Has bloqueado al autor o has sido bloqueado por el autor." @@ -4543,6 +4700,10 @@ msgstr "AĆŗn no has creado ninguna contraseƱa de aplicación. Puedes crear una msgid "You have not muted any accounts yet. To mute an account, go to their profile and selected \"Mute account\" from the menu on their account." msgstr "AĆŗn no has silenciado ninguna cuenta. Para silenciar una cuenta, ve a su perfil y selecciona \"Silenciar cuenta\" en el menĆŗ de su cuenta." +#: src/components/dialogs/MutedWords.tsx:202 +msgid "You haven't muted any words or tags yet" +msgstr "" + #: src/view/com/modals/ContentFilteringSettings.tsx:175 msgid "You must be 18 or older to enable adult content." msgstr "" @@ -4551,11 +4712,11 @@ msgstr "" msgid "You must be 18 years or older to enable adult content" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:127 +#: src/view/com/util/forms/PostDropdownBtn.tsx:129 msgid "You will no longer receive notifications for this thread" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:130 +#: src/view/com/util/forms/PostDropdownBtn.tsx:132 msgid "You will now receive notifications for this thread" msgstr "" @@ -4641,11 +4802,15 @@ msgstr "" #~ msgid "Your invite codes are hidden when logged in using an App Password" #~ msgstr "Tus códigos de invitación estĆ”n ocultos cuando inicias sesión con una contraseƱa de la app" +#: src/components/dialogs/MutedWords.tsx:173 +msgid "Your muted words" +msgstr "" + #: src/view/com/modals/ChangePassword.tsx:155 msgid "Your password has been changed successfully!" msgstr "" -#: src/view/com/composer/Composer.tsx:267 +#: src/view/com/composer/Composer.tsx:274 msgid "Your post has been published" msgstr "" @@ -4660,7 +4825,7 @@ msgstr "Tus publicaciones, Me gustas y bloqueos son pĆŗblicos. Las cuentas silen msgid "Your profile" msgstr "Tu perfil" -#: src/view/com/composer/Composer.tsx:266 +#: src/view/com/composer/Composer.tsx:273 msgid "Your reply has been published" msgstr "" diff --git a/src/locale/locales/fr/messages.po b/src/locale/locales/fr/messages.po index 8a78424e22..44b9fb9a2b 100644 --- a/src/locale/locales/fr/messages.po +++ b/src/locale/locales/fr/messages.po @@ -80,7 +80,7 @@ msgid "A new version of the app is available. Please update to continue using th msgstr "Une nouvelle version de l’application est disponible. Veuillez faire la mise Ć  jour pour continuer Ć  utiliser l’application." #: src/view/com/util/ViewHeader.tsx:83 -#: src/view/screens/Search/Search.tsx:624 +#: src/view/screens/Search/Search.tsx:647 msgid "Access navigation links and settings" msgstr "AccĆØde aux liens de navigation et aux paramĆØtres" @@ -131,6 +131,7 @@ msgstr "Compte dĆ©bloquĆ©" msgid "Account unmuted" msgstr "Compte dĆ©masquĆ©" +#: src/components/dialogs/MutedWords.tsx:147 #: src/view/com/auth/onboarding/RecommendedFeedsItem.tsx:150 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -172,14 +173,22 @@ msgstr "Ajouter des dĆ©tails" msgid "Add details to report" msgstr "Ajouter des dĆ©tails au rapport" -#: src/view/com/composer/Composer.tsx:446 +#: src/view/com/composer/Composer.tsx:453 msgid "Add link card" msgstr "Ajouter une carte de lien" -#: src/view/com/composer/Composer.tsx:451 +#: src/view/com/composer/Composer.tsx:458 msgid "Add link card:" msgstr "Ajouter une carte de lien :" +#: src/components/dialogs/MutedWords.tsx:140 +msgid "Add mute word for configured settings" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:74 +msgid "Add muted words and tags" +msgstr "" + #: src/view/com/modals/ChangeHandle.tsx:417 msgid "Add the following DNS record to your domain:" msgstr "Ajoutez l’enregistrement DNS suivant Ć  votre domaine :" @@ -303,7 +312,7 @@ msgstr "ParamĆØtres de mot de passe d’application" msgid "App Passwords" msgstr "Mots de passe d’application" -#: src/view/com/util/forms/PostDropdownBtn.tsx:279 +#: src/view/com/util/forms/PostDropdownBtn.tsx:295 msgid "Appeal content warning" msgstr "Faire appel de l’avertissement sur le contenu" @@ -327,15 +336,16 @@ msgstr "Affichage" msgid "Are you sure you want to delete the app password \"{name}\"?" msgstr "Êtes-vous sĆ»r de vouloir supprimer le mot de passe de l’application Ā« {name} Ā» ?" -#: src/view/com/composer/Composer.tsx:143 +#: src/view/com/composer/Composer.tsx:150 msgid "Are you sure you'd like to discard this draft?" msgstr "Êtes-vous sĆ»r de vouloir rejeter ce brouillon ?" +#: src/components/dialogs/MutedWords.tsx:233 #: src/view/screens/ProfileList.tsx:365 msgid "Are you sure?" msgstr "Vous confirmez ?" -#: src/view/com/util/forms/PostDropdownBtn.tsx:262 +#: src/view/com/util/forms/PostDropdownBtn.tsx:278 msgid "Are you sure? This cannot be undone." msgstr "Vous confirmez ? Cela ne pourra pas ĆŖtre annulĆ©." @@ -357,15 +367,15 @@ msgstr "NuditĆ© artistique ou non Ć©rotique." #: src/view/com/auth/login/LoginForm.tsx:259 #: src/view/com/auth/login/SetNewPasswordForm.tsx:179 #: src/view/com/modals/report/InputIssueDetails.tsx:46 -#: src/view/com/post-thread/PostThread.tsx:471 -#: src/view/com/post-thread/PostThread.tsx:521 -#: src/view/com/post-thread/PostThread.tsx:529 +#: src/view/com/post-thread/PostThread.tsx:472 +#: src/view/com/post-thread/PostThread.tsx:522 +#: src/view/com/post-thread/PostThread.tsx:530 #: src/view/com/profile/ProfileHeader.tsx:649 #: src/view/com/util/ViewHeader.tsx:81 msgid "Back" msgstr "ArriĆØre" -#: src/view/com/post-thread/PostThread.tsx:479 +#: src/view/com/post-thread/PostThread.tsx:480 msgctxt "action" msgid "Back" msgstr "Retour" @@ -413,7 +423,7 @@ msgstr "Bloquer cette liste" msgid "Blocked" msgstr "BloquĆ©" -#: src/view/screens/Moderation.tsx:123 +#: src/view/screens/Moderation.tsx:142 msgid "Blocked accounts" msgstr "Comptes bloquĆ©s" @@ -472,7 +482,7 @@ msgstr "Bluesky est public." msgid "Bluesky uses invites to build a healthier community. If you don't know anybody with an invite, you can sign up for the waitlist and we'll send one soon." msgstr "Bluesky distribue des invitations pour construire une communautĆ© plus saine. Si personne ne peut vous donner une invitation, vous pouvez vous inscrire sur notre liste d’attente et nous vous en enverrons une bientĆ“t." -#: src/view/screens/Moderation.tsx:226 +#: src/view/screens/Moderation.tsx:245 msgid "Bluesky will not show your profile and posts to logged-out users. Other apps may not honor this request. This does not make your account private." msgstr "Bluesky n’affichera pas votre profil et vos messages Ć  des personnes non connectĆ©es. Il est possible que d’autres applications n’honorent pas cette demande. Cela ne privatise pas votre compte." @@ -524,8 +534,8 @@ msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must msgstr "Ne peut contenir que des lettres, des chiffres, des espaces, des tirets et des tirets bas. La longueur doit ĆŖtre d’au moins 4 caractĆØres, mais pas plus de 32." #: src/components/Prompt.tsx:91 -#: src/view/com/composer/Composer.tsx:300 -#: src/view/com/composer/Composer.tsx:305 +#: src/view/com/composer/Composer.tsx:307 +#: src/view/com/composer/Composer.tsx:312 #: src/view/com/modals/ChangeEmail.tsx:218 #: src/view/com/modals/ChangeEmail.tsx:220 #: src/view/com/modals/ChangePassword.tsx:265 @@ -539,7 +549,7 @@ msgstr "Ne peut contenir que des lettres, des chiffres, des espaces, des tirets #: src/view/com/modals/VerifyEmail.tsx:247 #: src/view/com/modals/VerifyEmail.tsx:253 #: src/view/com/modals/Waitlist.tsx:142 -#: src/view/screens/Search/Search.tsx:693 +#: src/view/screens/Search/Search.tsx:716 #: src/view/shell/desktop/Search.tsx:238 msgid "Cancel" msgstr "Annuler" @@ -690,7 +700,7 @@ msgid "Clear all storage data (restart after this)" msgstr "Effacer toutes les donnĆ©es de stockage (redĆ©marrer ensuite)" #: src/view/com/util/forms/SearchInput.tsx:88 -#: src/view/screens/Search/Search.tsx:674 +#: src/view/screens/Search/Search.tsx:697 msgid "Clear search query" msgstr "Effacer la recherche" @@ -698,6 +708,11 @@ msgstr "Effacer la recherche" msgid "click here" msgstr "cliquez ici" +#: src/components/RichText.tsx:189 +#: src/components/TagMenu/index.web.tsx:125 +msgid "Click here to open tag menu for {tag}" +msgstr "" + #: src/screens/Onboarding/index.tsx:35 msgid "Climate" msgstr "" @@ -728,11 +743,15 @@ msgstr "Fermer l’image" msgid "Close image viewer" msgstr "Fermer la visionneuse d’images" -#: src/view/shell/index.web.tsx:49 +#: src/view/shell/index.web.tsx:51 msgid "Close navigation footer" msgstr "Fermer le pied de page de navigation" -#: src/view/shell/index.web.tsx:50 +#: src/components/TagMenu/index.tsx:266 +msgid "Close this dialog" +msgstr "" + +#: src/view/shell/index.web.tsx:52 msgid "Closes bottom navigation bar" msgstr "Ferme la barre de navigation du bas" @@ -740,7 +759,7 @@ msgstr "Ferme la barre de navigation du bas" msgid "Closes password update alert" msgstr "Ferme la notification de mise Ć  jour du mot de passe" -#: src/view/com/composer/Composer.tsx:302 +#: src/view/com/composer/Composer.tsx:309 msgid "Closes post composer and discards post draft" msgstr "Ferme la fenĆŖtre de rĆ©daction et supprime le brouillon" @@ -773,7 +792,7 @@ msgstr "" msgid "Complete the challenge" msgstr "" -#: src/view/com/composer/Composer.tsx:417 +#: src/view/com/composer/Composer.tsx:424 msgid "Compose posts up to {MAX_GRAPHEME_LENGTH} characters in length" msgstr "Permet d’écrire des messages de {MAX_GRAPHEME_LENGTH} caractĆØres maximum" @@ -837,7 +856,7 @@ msgstr "Connexion…" msgid "Contact support" msgstr "" -#: src/view/screens/Moderation.tsx:81 +#: src/view/screens/Moderation.tsx:83 msgid "Content filtering" msgstr "Filtrage du contenu" @@ -903,7 +922,7 @@ msgstr "Version de build copiĆ©e dans le presse-papier" #: src/view/com/modals/AddAppPasswords.tsx:76 #: src/view/com/modals/InviteCodes.tsx:152 -#: src/view/com/util/forms/PostDropdownBtn.tsx:141 +#: src/view/com/util/forms/PostDropdownBtn.tsx:143 msgid "Copied to clipboard" msgstr "CopiĆ© dans le presse-papier" @@ -919,7 +938,7 @@ msgstr "Copie" msgid "Copy link to list" msgstr "Copier le lien vers la liste" -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 msgid "Copy link to post" msgstr "Copier le lien vers le post" @@ -927,7 +946,7 @@ msgstr "Copier le lien vers le post" msgid "Copy link to profile" msgstr "Copier le lien vers le profil" -#: src/view/com/util/forms/PostDropdownBtn.tsx:168 +#: src/view/com/util/forms/PostDropdownBtn.tsx:170 msgid "Copy post text" msgstr "Copier le texte du post" @@ -983,7 +1002,7 @@ msgstr "CrƩƩe par <0/>" msgid "Created by you" msgstr "CrƩƩe par vous" -#: src/view/com/composer/Composer.tsx:448 +#: src/view/com/composer/Composer.tsx:455 msgid "Creates a card with a thumbnail. The card links to {url}" msgstr "CrĆ©e une carte avec une miniature. La carte pointe vers {url}" @@ -1060,11 +1079,11 @@ msgstr "Supprimer mon compte" msgid "Delete My Account…" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:257 +#: src/view/com/util/forms/PostDropdownBtn.tsx:273 msgid "Delete post" msgstr "Supprimer le post" -#: src/view/com/util/forms/PostDropdownBtn.tsx:261 +#: src/view/com/util/forms/PostDropdownBtn.tsx:277 msgid "Delete this post?" msgstr "Supprimer ce post ?" @@ -1087,7 +1106,7 @@ msgstr "Description" #~ msgid "Developer Tools" #~ msgstr "Outils de dĆ©v" -#: src/view/com/composer/Composer.tsx:211 +#: src/view/com/composer/Composer.tsx:218 msgid "Did you want to say anything?" msgstr "Vous vouliez dire quelque chose ?" @@ -1095,15 +1114,15 @@ msgstr "Vous vouliez dire quelque chose ?" msgid "Dim" msgstr "" -#: src/view/com/composer/Composer.tsx:144 +#: src/view/com/composer/Composer.tsx:151 msgid "Discard" msgstr "Ignorer" -#: src/view/com/composer/Composer.tsx:138 +#: src/view/com/composer/Composer.tsx:145 msgid "Discard draft" msgstr "Ignorer le brouillon" -#: src/view/screens/Moderation.tsx:207 +#: src/view/screens/Moderation.tsx:226 msgid "Discourage apps from showing my account to logged-out users" msgstr "EmpĆŖcher les applis de montrer mon compte aux personnes non connectĆ©es" @@ -1182,7 +1201,7 @@ msgstr "" msgid "Download CAR file" msgstr "" -#: src/view/com/composer/text-input/TextInput.web.tsx:247 +#: src/view/com/composer/text-input/TextInput.web.tsx:249 msgid "Drop to add images" msgstr "" @@ -1254,6 +1273,7 @@ msgstr "Modifier le profil" msgid "Edit Profile" msgstr "Modifier le profil" +#: src/view/com/home/HomeHeaderLayout.web.tsx:59 #: src/view/screens/Feeds.tsx:355 msgid "Edit Saved Feeds" msgstr "Modifier les fils d’actu enregistrĆ©s" @@ -1336,6 +1356,11 @@ msgstr "Fin du fil d’actu" msgid "Enter a name for this App Password" msgstr "Entrer un nom pour ce mot de passe d’application" +#: src/components/dialogs/MutedWords.tsx:87 +#: src/components/dialogs/MutedWords.tsx:88 +msgid "Enter a word or tag" +msgstr "" + #: src/view/com/modals/VerifyEmail.tsx:105 msgid "Enter Confirmation Code" msgstr "Entrer un code de confirmation" @@ -1385,7 +1410,7 @@ msgstr "Entrez votre pseudo et votre mot de passe" msgid "Error receiving captcha response." msgstr "" -#: src/view/screens/Search/Search.tsx:109 +#: src/view/screens/Search/Search.tsx:110 msgid "Error:" msgstr "Erreur :" @@ -1456,7 +1481,7 @@ msgstr "Ɖchec de la crĆ©ation du mot de passe d’application." msgid "Failed to create the list. Check your internet connection and try again." msgstr "Ɖchec de la crĆ©ation de la liste. VĆ©rifiez votre connexion Internet et rĆ©essayez." -#: src/view/com/util/forms/PostDropdownBtn.tsx:108 +#: src/view/com/util/forms/PostDropdownBtn.tsx:110 msgid "Failed to delete post, please try again" msgstr "Ɖchec de la suppression du post, veuillez rĆ©essayer" @@ -1478,8 +1503,8 @@ msgid "Feed offline" msgstr "Fil d’actu hors ligne" #: src/view/com/feeds/FeedPage.tsx:143 -msgid "Feed Preferences" -msgstr "PrĆ©fĆ©rences en matiĆØre de fil d’actu" +#~ msgid "Feed Preferences" +#~ msgstr "PrĆ©fĆ©rences en matiĆØre de fil d’actu" #: src/view/shell/desktop/RightNav.tsx:61 #: src/view/shell/Drawer.tsx:311 @@ -1527,11 +1552,11 @@ msgstr "" msgid "Find accounts to follow" msgstr "Trouver des comptes Ć  suivre" -#: src/view/screens/Search/Search.tsx:439 +#: src/view/screens/Search/Search.tsx:440 msgid "Find users on Bluesky" msgstr "Trouver des comptes sur Bluesky" -#: src/view/screens/Search/Search.tsx:437 +#: src/view/screens/Search/Search.tsx:438 msgid "Find users with the search tool on the right" msgstr "Trouvez des comptes Ć  l’aide de l’outil de recherche, Ć  droite" @@ -1628,6 +1653,7 @@ msgid "Following {0}" msgstr "Suit {0}" #: src/Navigation.tsx:248 +#: src/view/com/home/HomeHeaderLayout.web.tsx:45 #: src/view/com/home/HomeHeaderLayoutMobile.tsx:83 #: src/view/screens/PreferencesFollowingFeed.tsx:104 #: src/view/screens/Settings/index.tsx:543 @@ -1667,7 +1693,7 @@ msgstr "Mot de passe oubliĆ©" msgid "Forgot Password" msgstr "Mot de passe oubliĆ©" -#: src/view/com/posts/FeedItem.tsx:187 +#: src/view/com/posts/FeedItem.tsx:189 msgctxt "from-feed" msgid "From <0/>" msgstr "TirĆ© de <0/>" @@ -1700,7 +1726,7 @@ msgstr "Retour" msgid "Go back to previous step" msgstr "" -#: src/view/screens/Search/Search.tsx:724 +#: src/view/screens/Search/Search.tsx:747 #: src/view/shell/desktop/Search.tsx:262 msgid "Go to @{queryMaybeHandle}" msgstr "" @@ -1717,6 +1743,10 @@ msgstr "Aller Ć  la suite" msgid "Handle" msgstr "Pseudo" +#: src/components/RichText.tsx:188 +msgid "Hashtag: {tag}" +msgstr "" + #: src/view/com/auth/create/CreateAccount.tsx:208 msgid "Having trouble?" msgstr "" @@ -1755,7 +1785,7 @@ msgctxt "action" msgid "Hide" msgstr "Cacher" -#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +#: src/view/com/util/forms/PostDropdownBtn.tsx:232 msgid "Hide post" msgstr "Cacher ce post" @@ -1764,7 +1794,7 @@ msgstr "Cacher ce post" msgid "Hide the content" msgstr "Cacher ce contenu" -#: src/view/com/util/forms/PostDropdownBtn.tsx:220 +#: src/view/com/util/forms/PostDropdownBtn.tsx:236 msgid "Hide this post?" msgstr "Cacher ce post ?" @@ -1913,7 +1943,7 @@ msgstr "Entrez votre mot de passe" msgid "Input your user handle" msgstr "Entrez votre pseudo" -#: src/view/com/post-thread/PostThreadItem.tsx:224 +#: src/view/com/post-thread/PostThreadItem.tsx:226 msgid "Invalid or unsupported post record" msgstr "Enregistrement de post invalide ou non pris en charge" @@ -2015,7 +2045,7 @@ msgstr "En savoir plus" msgid "Learn more about this warning" msgstr "En savoir plus sur cet avertissement" -#: src/view/screens/Moderation.tsx:243 +#: src/view/screens/Moderation.tsx:262 msgid "Learn more about what is public on Bluesky." msgstr "En savoir plus sur ce qui est public sur Bluesky." @@ -2091,7 +2121,7 @@ msgstr "likĆ© votre post" msgid "Likes" msgstr "Likes" -#: src/view/com/post-thread/PostThreadItem.tsx:181 +#: src/view/com/post-thread/PostThreadItem.tsx:183 msgid "Likes on this post" msgstr "Likes sur ce post" @@ -2148,7 +2178,7 @@ msgstr "Charger plus d’articles" msgid "Load new notifications" msgstr "Charger les nouvelles notifications" -#: src/view/com/feeds/FeedPage.tsx:181 +#: src/view/com/feeds/FeedPage.tsx:115 #: src/view/screens/Profile.tsx:440 #: src/view/screens/ProfileFeed.tsx:495 #: src/view/screens/ProfileList.tsx:681 @@ -2174,7 +2204,7 @@ msgstr "Journaux" msgid "Log out" msgstr "" -#: src/view/screens/Moderation.tsx:136 +#: src/view/screens/Moderation.tsx:155 msgid "Logged-out visibility" msgstr "VisibilitĆ© dĆ©connectĆ©e" @@ -2186,6 +2216,10 @@ msgstr "Se connecter Ć  un compte qui n’est pas listĆ©" msgid "Make sure this is where you intend to go!" msgstr "Assurez-vous que c’est bien lĆ  que vous avez l’intention d’aller !" +#: src/components/dialogs/MutedWords.tsx:71 +msgid "Manage your muted words and tags" +msgstr "" + #: src/view/com/auth/create/Step2.tsx:118 msgid "May not be longer than 253 characters" msgstr "" @@ -2207,7 +2241,7 @@ msgid "Mentioned users" msgstr "Comptes mentionnĆ©s" #: src/view/com/util/ViewHeader.tsx:81 -#: src/view/screens/Search/Search.tsx:623 +#: src/view/screens/Search/Search.tsx:646 msgid "Menu" msgstr "Menu" @@ -2216,7 +2250,7 @@ msgid "Message from server: {0}" msgstr "Message du serveur : {0}" #: src/Navigation.tsx:115 -#: src/view/screens/Moderation.tsx:64 +#: src/view/screens/Moderation.tsx:66 #: src/view/screens/Settings/index.tsx:625 #: src/view/shell/desktop/LeftNav.tsx:397 #: src/view/shell/Drawer.tsx:511 @@ -2247,7 +2281,7 @@ msgstr "Liste de modĆ©ration crƩƩe" msgid "Moderation list updated" msgstr "Liste de modĆ©ration mise Ć  jour" -#: src/view/screens/Moderation.tsx:95 +#: src/view/screens/Moderation.tsx:114 msgid "Moderation lists" msgstr "Listes de modĆ©ration" @@ -2274,7 +2308,7 @@ msgstr "Plus de fils d’actu" msgid "More options" msgstr "Plus d’options" -#: src/view/com/util/forms/PostDropdownBtn.tsx:299 +#: src/view/com/util/forms/PostDropdownBtn.tsx:315 msgid "More post options" msgstr "Plus d’options de post" @@ -2286,6 +2320,14 @@ msgstr "RĆ©ponses les plus likĆ©es en premier" msgid "Must be at least 3 characters" msgstr "" +#: src/components/TagMenu/index.tsx:253 +msgid "Mute" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:91 +msgid "Mute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:327 msgid "Mute Account" msgstr "Masquer le compte" @@ -2294,6 +2336,18 @@ msgstr "Masquer le compte" msgid "Mute accounts" msgstr "Masquer les comptes" +#: src/components/TagMenu/index.tsx:211 +msgid "Mute all {tag} posts" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:131 +msgid "Mute in tags only" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:116 +msgid "Mute in text & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:491 msgid "Mute list" msgstr "Masquer la liste" @@ -2306,15 +2360,27 @@ msgstr "Masquer ces comptes ?" msgid "Mute this List" msgstr "Masquer cette liste" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/dialogs/MutedWords.tsx:109 +msgid "Mute this word in post text and tags" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:124 +msgid "Mute this word in tags only" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Mute thread" msgstr "Masquer ce fil de discussion" +#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +msgid "Mute words & tags" +msgstr "" + #: src/view/com/lists/ListCard.tsx:102 msgid "Muted" msgstr "" -#: src/view/screens/Moderation.tsx:109 +#: src/view/screens/Moderation.tsx:128 msgid "Muted accounts" msgstr "Comptes masquĆ©s" @@ -2327,6 +2393,10 @@ msgstr "Comptes masquĆ©s" msgid "Muted accounts have their posts removed from your feed and from your notifications. Mutes are completely private." msgstr "Les comptes masquĆ©s voient leurs posts supprimĆ©s de votre fil d’actualitĆ© et de vos notifications. Cette option est totalement privĆ©e." +#: src/view/screens/Moderation.tsx:100 +msgid "Muted words & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:277 msgid "Muting is private. Muted accounts can interact with you, but you will not see their posts or receive notifications from them." msgstr "Ce que vous masquez reste privĆ©. Les comptes masquĆ©s peuvent interagir avec vous, mais vous ne verrez pas leurs posts et ne recevrez pas de notifications de leur part." @@ -2390,6 +2460,10 @@ msgstr "Ne perdez jamais l’accĆØs Ć  vos followers et Ć  vos donnĆ©es." msgid "Never lose access to your followers or data." msgstr "" +#: src/components/dialogs/MutedWords.tsx:244 +msgid "Nevermind" +msgstr "" + #: src/view/screens/Lists.tsx:76 msgctxt "action" msgid "New" @@ -2411,7 +2485,7 @@ msgstr "Nouveau mot de passe" msgid "New Password" msgstr "" -#: src/view/com/feeds/FeedPage.tsx:192 +#: src/view/com/feeds/FeedPage.tsx:126 msgctxt "action" msgid "New post" msgstr "Nouveau post" @@ -2496,8 +2570,8 @@ msgid "No results found for \"{query}\"" msgstr "Aucun rĆ©sultat trouvĆ© pour Ā« {query} Ā»" #: src/view/com/modals/ListAddRemoveUsers.tsx:127 -#: src/view/screens/Search/Search.tsx:280 -#: src/view/screens/Search/Search.tsx:308 +#: src/view/screens/Search/Search.tsx:281 +#: src/view/screens/Search/Search.tsx:309 msgid "No results found for {query}" msgstr "Aucun rĆ©sultat trouvĆ© pour {query}" @@ -2523,7 +2597,7 @@ msgstr "Introuvable" msgid "Not right now" msgstr "Pas maintenant" -#: src/view/screens/Moderation.tsx:233 +#: src/view/screens/Moderation.tsx:252 msgid "Note: Bluesky is an open and public network. This setting only limits the visibility of your content on the Bluesky app and website, and other apps may not respect this setting. Your content may still be shown to logged-out users by other apps and websites." msgstr "Remarque : Bluesky est un rĆ©seau ouvert et public. Ce paramĆØtre limite uniquement la visibilitĆ© de votre contenu sur l’application et le site Web de Bluesky, et d’autres applications peuvent ne pas respecter ce paramĆØtre. Votre contenu peut toujours ĆŖtre montrĆ© aux personnes non connectĆ©es par d’autres applications et sites Web." @@ -2561,7 +2635,7 @@ msgstr "Plus anciennes rĆ©ponses en premier" msgid "Onboarding reset" msgstr "RĆ©initialiser le didacticiel" -#: src/view/com/composer/Composer.tsx:375 +#: src/view/com/composer/Composer.tsx:382 msgid "One or more images is missing alt text." msgstr "Une ou plusieurs images n’ont pas de texte alt." @@ -2578,8 +2652,12 @@ msgstr "Oups !" msgid "Open" msgstr "" -#: src/view/com/composer/Composer.tsx:470 -#: src/view/com/composer/Composer.tsx:471 +#: src/view/screens/Moderation.tsx:75 +msgid "Open content filtering settings" +msgstr "" + +#: src/view/com/composer/Composer.tsx:477 +#: src/view/com/composer/Composer.tsx:478 msgid "Open emoji picker" msgstr "Ouvrir le sĆ©lecteur d’emoji" @@ -2587,6 +2665,10 @@ msgstr "Ouvrir le sĆ©lecteur d’emoji" msgid "Open links with in-app browser" msgstr "" +#: src/view/screens/Moderation.tsx:92 +msgid "Open muted words settings" +msgstr "" + #: src/view/com/home/HomeHeaderLayoutMobile.tsx:49 msgid "Open navigation" msgstr "Navigation ouverte" @@ -2663,6 +2745,7 @@ msgstr "Ouvre les paramĆØtres de modĆ©ration" msgid "Opens password reset form" msgstr "Ouvre le formulaire de rĆ©initialisation du mot de passe" +#: src/view/com/home/HomeHeaderLayout.web.tsx:60 #: src/view/screens/Feeds.tsx:356 msgid "Opens screen to edit Saved Feeds" msgstr "Ouvre l’écran pour modifier les fils d’actu enregistrĆ©s" @@ -2838,7 +2921,7 @@ msgstr "Dites-nous donc pourquoi vous pensez que cet avertissement de contenu a msgid "Please Verify Your Email" msgstr "Veuillez vĆ©rifier votre e-mail" -#: src/view/com/composer/Composer.tsx:215 +#: src/view/com/composer/Composer.tsx:222 msgid "Please wait for your link card to finish loading" msgstr "Veuillez patienter le temps que votre carte de lien soit chargĆ©e" @@ -2850,8 +2933,8 @@ msgstr "" msgid "Porn" msgstr "Porno" -#: src/view/com/composer/Composer.tsx:350 -#: src/view/com/composer/Composer.tsx:358 +#: src/view/com/composer/Composer.tsx:357 +#: src/view/com/composer/Composer.tsx:365 msgctxt "action" msgid "Post" msgstr "Poster" @@ -2861,7 +2944,7 @@ msgctxt "description" msgid "Post" msgstr "Post" -#: src/view/com/post-thread/PostThreadItem.tsx:173 +#: src/view/com/post-thread/PostThreadItem.tsx:175 msgid "Post by {0}" msgstr "Post de {0}" @@ -2871,11 +2954,11 @@ msgstr "Post de {0}" msgid "Post by @{0}" msgstr "Post de @{0}" -#: src/view/com/util/forms/PostDropdownBtn.tsx:88 +#: src/view/com/util/forms/PostDropdownBtn.tsx:90 msgid "Post deleted" msgstr "Post supprimĆ©" -#: src/view/com/post-thread/PostThread.tsx:461 +#: src/view/com/post-thread/PostThread.tsx:462 msgid "Post hidden" msgstr "Post cachĆ©" @@ -2887,14 +2970,22 @@ msgstr "Langue du post" msgid "Post Languages" msgstr "Langues du post" -#: src/view/com/post-thread/PostThread.tsx:513 +#: src/view/com/post-thread/PostThread.tsx:514 msgid "Post not found" msgstr "Post introuvable" +#: src/components/TagMenu/index.tsx:257 +msgid "posts" +msgstr "" + #: src/view/screens/Profile.tsx:180 msgid "Posts" msgstr "Posts" +#: src/components/dialogs/MutedWords.tsx:77 +msgid "Posts can be muted based on their text, their tags, or both." +msgstr "" + #: src/view/com/posts/FeedErrorMessage.tsx:64 msgid "Posts hidden" msgstr "Posts cachĆ©s" @@ -2959,11 +3050,11 @@ msgstr "Listes publiques et partageables de comptes Ć  masquer ou Ć  bloquer." msgid "Public, shareable lists which can drive feeds." msgstr "Les listes publiques et partageables qui peuvent alimenter les fils d’actu." -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish post" msgstr "Publier le post" -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish reply" msgstr "Publier la rĆ©ponse" @@ -2997,6 +3088,7 @@ msgstr "Fils d’actu recommandĆ©s" msgid "Recommended Users" msgstr "Comptes recommandĆ©s" +#: src/components/dialogs/MutedWords.tsx:249 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/SelfLabel.tsx:83 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -3034,6 +3126,10 @@ msgstr "Supprimer l’image" msgid "Remove image preview" msgstr "Supprimer l’aperƧu d’image" +#: src/components/dialogs/MutedWords.tsx:294 +msgid "Remove mute word from your list" +msgstr "" + #: src/view/com/modals/Repost.tsx:47 msgid "Remove repost" msgstr "Supprimer le repost" @@ -3068,7 +3164,7 @@ msgstr "RĆ©ponses" msgid "Replies to this thread are disabled" msgstr "Les rĆ©ponses Ć  ce fil de discussion sont dĆ©sactivĆ©es" -#: src/view/com/composer/Composer.tsx:348 +#: src/view/com/composer/Composer.tsx:355 msgctxt "action" msgid "Reply" msgstr "RĆ©pondre" @@ -3078,7 +3174,7 @@ msgid "Reply Filters" msgstr "Filtres de rĆ©ponse" #: src/view/com/post/Post.tsx:167 -#: src/view/com/posts/FeedItem.tsx:285 +#: src/view/com/posts/FeedItem.tsx:287 msgctxt "description" msgid "Reply to <0/>" msgstr "RĆ©ponse Ć  <0/>" @@ -3100,7 +3196,7 @@ msgid "Report List" msgstr "Signaler la liste" #: src/view/com/modals/report/SendReportButton.tsx:37 -#: src/view/com/util/forms/PostDropdownBtn.tsx:239 +#: src/view/com/util/forms/PostDropdownBtn.tsx:255 msgid "Report post" msgstr "Signaler le post" @@ -3125,11 +3221,11 @@ msgstr "Republier ou citer" msgid "Reposted By" msgstr "RepubliĆ© par" -#: src/view/com/posts/FeedItem.tsx:205 +#: src/view/com/posts/FeedItem.tsx:207 msgid "Reposted by {0}" msgstr "RepubliĆ© par {0}" -#: src/view/com/posts/FeedItem.tsx:222 +#: src/view/com/posts/FeedItem.tsx:224 msgid "Reposted by <0/>" msgstr "RepubliĆ© par <0/>" @@ -3137,7 +3233,7 @@ msgstr "RepubliĆ© par <0/>" msgid "reposted your post" msgstr "a republiĆ© votre post" -#: src/view/com/post-thread/PostThreadItem.tsx:186 +#: src/view/com/post-thread/PostThreadItem.tsx:188 msgid "Reposts of this post" msgstr "Reposts de ce post" @@ -3288,9 +3384,9 @@ msgstr "Remonter en haut" #: src/view/com/modals/ListAddRemoveUsers.tsx:75 #: src/view/com/util/forms/SearchInput.tsx:67 #: src/view/com/util/forms/SearchInput.tsx:79 -#: src/view/screens/Search/Search.tsx:418 -#: src/view/screens/Search/Search.tsx:645 -#: src/view/screens/Search/Search.tsx:663 +#: src/view/screens/Search/Search.tsx:419 +#: src/view/screens/Search/Search.tsx:668 +#: src/view/screens/Search/Search.tsx:686 #: src/view/shell/bottom-bar/BottomBar.tsx:159 #: src/view/shell/desktop/LeftNav.tsx:324 #: src/view/shell/desktop/Search.tsx:214 @@ -3300,11 +3396,19 @@ msgstr "Remonter en haut" msgid "Search" msgstr "Recherche" -#: src/view/screens/Search/Search.tsx:712 +#: src/view/screens/Search/Search.tsx:735 #: src/view/shell/desktop/Search.tsx:255 msgid "Search for \"{query}\"" msgstr "" +#: src/components/TagMenu/index.tsx:145 +msgid "Search for all posts by @{authorHandle} with tag {tag}" +msgstr "" + +#: src/components/TagMenu/index.tsx:90 +msgid "Search for all posts with tag {tag}" +msgstr "" + #: src/view/com/auth/LoggedOut.tsx:104 #: src/view/com/auth/LoggedOut.tsx:105 #: src/view/com/modals/ListAddRemoveUsers.tsx:70 @@ -3315,6 +3419,22 @@ msgstr "Rechercher des comptes" msgid "Security Step Required" msgstr "Ɖtape de sĆ©curitĆ© requise" +#: src/components/TagMenu/index.web.tsx:50 +msgid "See {truncatedTag} posts" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:67 +msgid "See {truncatedTag} posts by user" +msgstr "" + +#: src/components/TagMenu/index.tsx:128 +msgid "See <0>{tag} posts" +msgstr "" + +#: src/components/TagMenu/index.tsx:189 +msgid "See <0>{tag} posts by this user" +msgstr "" + #: src/view/screens/SavedFeeds.tsx:163 msgid "See this guide" msgstr "Voir ce guide" @@ -3524,7 +3644,7 @@ msgid "Share" msgstr "Partager" #: src/view/com/profile/ProfileHeader.tsx:295 -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 #: src/view/screens/ProfileList.tsx:418 msgid "Share" msgstr "Partager" @@ -3557,9 +3677,9 @@ msgstr "Afficher les intĆ©grations de {0}" msgid "Show follows similar to {0}" msgstr "Afficher les suivis similaires Ć  {0}" -#: src/view/com/post-thread/PostThreadItem.tsx:532 -#: src/view/com/post/Post.tsx:196 -#: src/view/com/posts/FeedItem.tsx:359 +#: src/view/com/post-thread/PostThreadItem.tsx:538 +#: src/view/com/post/Post.tsx:198 +#: src/view/com/posts/FeedItem.tsx:363 msgid "Show More" msgstr "Voir plus" @@ -3727,7 +3847,7 @@ msgstr "" msgid "Something went wrong. Check your email and try again." msgstr "Quelque chose n’a pas marchĆ©. VĆ©rifiez vos e-mails et rĆ©essayez." -#: src/App.native.tsx:61 +#: src/App.native.tsx:63 msgid "Sorry! Your session expired. Please log in again." msgstr "DĆ©solĆ© ! Votre session a expirĆ©. Essayez de vous reconnecter." @@ -3785,7 +3905,7 @@ msgstr "" msgid "Subscribe to this list" msgstr "S’abonner Ć  cette liste" -#: src/view/screens/Search/Search.tsx:373 +#: src/view/screens/Search/Search.tsx:374 msgid "Suggested Follows" msgstr "Suivis suggĆ©rĆ©s" @@ -3829,6 +3949,14 @@ msgstr "SystĆØme" msgid "System log" msgstr "Journal systĆØme" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "tag" +msgstr "" + +#: src/components/TagMenu/index.tsx:74 +msgid "Tag menu: {tag}" +msgstr "" + #: src/view/com/modals/crop-image/CropImage.web.tsx:112 msgid "Tall" msgstr "Grand" @@ -3852,6 +3980,10 @@ msgstr "Conditions gĆ©nĆ©rales" msgid "Terms of Service" msgstr "Conditions d’utilisation" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "text" +msgstr "" + #: src/view/com/modals/AppealLabel.tsx:70 #: src/view/com/modals/report/InputIssueDetails.tsx:51 msgid "Text input field" @@ -3877,7 +4009,7 @@ msgstr "Notre politique de droits d’auteur a Ć©tĆ© dĆ©placĆ©e vers <0/>" msgid "The following steps will help customize your Bluesky experience." msgstr "" -#: src/view/com/post-thread/PostThread.tsx:516 +#: src/view/com/post-thread/PostThread.tsx:517 msgid "The post may have been deleted." msgstr "Ce post a peut-ĆŖtre Ć©tĆ© supprimĆ©." @@ -4043,7 +4175,7 @@ msgstr "Cette liste est vide !" msgid "This name is already in use" msgstr "Ce nom est dĆ©jĆ  utilisĆ©" -#: src/view/com/post-thread/PostThreadItem.tsx:123 +#: src/view/com/post-thread/PostThreadItem.tsx:125 msgid "This post has been deleted." msgstr "Ce post a Ć©tĆ© supprimĆ©." @@ -4067,7 +4199,11 @@ msgstr "" msgid "This warning is only available for posts with media attached." msgstr "Cet avertissement n’est disponible que pour les messages contenant des mĆ©dias." -#: src/view/com/util/forms/PostDropdownBtn.tsx:221 +#: src/components/dialogs/MutedWords.tsx:236 +msgid "This will delete {0} from your muted words. You can always add it back later." +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:237 msgid "This will hide this post from your feeds." msgstr "Cela va masquer ce post de vos fils d’actu." @@ -4084,6 +4220,10 @@ msgstr "Mode arborescent" msgid "Threads Preferences" msgstr "PrĆ©fĆ©rences de fils de discussion" +#: src/components/dialogs/MutedWords.tsx:95 +msgid "Toggle between muted word options." +msgstr "" + #: src/view/com/util/forms/DropdownButton.tsx:246 msgid "Toggle dropdown" msgstr "Activer le menu dĆ©roulant" @@ -4092,9 +4232,9 @@ msgstr "Activer le menu dĆ©roulant" msgid "Transformations" msgstr "Transformations" -#: src/view/com/post-thread/PostThreadItem.tsx:679 -#: src/view/com/post-thread/PostThreadItem.tsx:681 -#: src/view/com/util/forms/PostDropdownBtn.tsx:154 +#: src/view/com/post-thread/PostThreadItem.tsx:685 +#: src/view/com/post-thread/PostThreadItem.tsx:687 +#: src/view/com/util/forms/PostDropdownBtn.tsx:156 msgid "Translate" msgstr "Traduire" @@ -4159,15 +4299,24 @@ msgstr "Malheureusement, vous ne remplissez pas les conditions requises pour cr msgid "Unlike" msgstr "DĆ©liker" +#: src/components/TagMenu/index.tsx:253 #: src/view/screens/ProfileList.tsx:597 msgid "Unmute" msgstr "RĆ©afficher" +#: src/components/TagMenu/index.web.tsx:90 +msgid "Unmute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:326 msgid "Unmute Account" msgstr "RĆ©afficher ce compte" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/TagMenu/index.tsx:210 +msgid "Unmute all {tag} posts" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Unmute thread" msgstr "RĆ©afficher ce fil de discussion" @@ -4368,6 +4517,10 @@ msgstr "" #~ msgid "We recommend \"For You\" by Skygaze:" #~ msgstr "" +#: src/components/dialogs/MutedWords.tsx:161 +msgid "We recommend avoiding common words that appear in many posts, since it can result in no posts being shown." +msgstr "" + #: src/screens/Onboarding/StepAlgoFeeds/index.tsx:124 msgid "We recommend our \"Discover\" feed:" msgstr "" @@ -4396,7 +4549,11 @@ msgstr "Nous sommes ravis de vous accueillir !" msgid "We're sorry, but we were unable to resolve this list. If this persists, please contact the list creator, @{handleOrDid}." msgstr "Nous sommes dĆ©solĆ©s, mais nous n’avons pas pu charger cette liste. Si cela persiste, veuillez contacter l’origine de la liste, @{handleOrDid}." -#: src/view/screens/Search/Search.tsx:253 +#: src/components/dialogs/MutedWords.tsx:182 +msgid "We're sorry, but we weren't able to load your muted words at this time. Please try again." +msgstr "" + +#: src/view/screens/Search/Search.tsx:254 msgid "We're sorry, but your search could not be completed. Please try again in a few minutes." msgstr "Nous sommes dĆ©solĆ©s, mais votre recherche a Ć©tĆ© annulĆ©e. Veuillez rĆ©essayer dans quelques minutes." @@ -4417,7 +4574,7 @@ msgid "What is the issue with this {collectionName}?" msgstr "Quel est le problĆØme avec cette {collectionName} ?" #: src/view/com/auth/SplashScreen.tsx:59 -#: src/view/com/composer/Composer.tsx:279 +#: src/view/com/composer/Composer.tsx:286 msgid "What's up?" msgstr "Quoi de neuf ?" @@ -4438,11 +4595,11 @@ msgstr "Qui peut rĆ©pondre ?" msgid "Wide" msgstr "Large" -#: src/view/com/composer/Composer.tsx:415 +#: src/view/com/composer/Composer.tsx:422 msgid "Write post" msgstr "RĆ©diger un post" -#: src/view/com/composer/Composer.tsx:278 +#: src/view/com/composer/Composer.tsx:285 #: src/view/com/composer/Prompt.tsx:33 msgid "Write your reply" msgstr "RĆ©digez votre rĆ©ponse" @@ -4507,7 +4664,7 @@ msgstr "Vous n’avez encore aucun fil enregistrĆ© !" msgid "You don't have any saved feeds." msgstr "Vous n’avez encore aucun fil enregistrĆ©." -#: src/view/com/post-thread/PostThread.tsx:464 +#: src/view/com/post-thread/PostThread.tsx:465 msgid "You have blocked the author or you have been blocked by the author." msgstr "Vous avez bloquĆ© cet auteur ou vous avez Ć©tĆ© bloquĆ© par celui-ci." @@ -4547,6 +4704,10 @@ msgstr "Vous n’avez encore crƩƩ aucun mot de passe pour l’appli. Vous pouv msgid "You have not muted any accounts yet. To mute an account, go to their profile and selected \"Mute account\" from the menu on their account." msgstr "Vous n’avez encore masquĆ© aucun compte. Pour dĆ©sactiver un compte, allez sur son profil et sĆ©lectionnez Ā« Masquer le compte Ā» dans le menu de son compte." +#: src/components/dialogs/MutedWords.tsx:202 +msgid "You haven't muted any words or tags yet" +msgstr "" + #: src/view/com/modals/ContentFilteringSettings.tsx:175 msgid "You must be 18 or older to enable adult content." msgstr "Vous devez avoir 18 ans ou plus pour activer le contenu pour adultes." @@ -4555,11 +4716,11 @@ msgstr "Vous devez avoir 18 ans ou plus pour activer le contenu pour adultes." msgid "You must be 18 years or older to enable adult content" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:127 +#: src/view/com/util/forms/PostDropdownBtn.tsx:129 msgid "You will no longer receive notifications for this thread" msgstr "Vous ne recevrez plus de notifications pour ce fil de discussion" -#: src/view/com/util/forms/PostDropdownBtn.tsx:130 +#: src/view/com/util/forms/PostDropdownBtn.tsx:132 msgid "You will now receive notifications for this thread" msgstr "Vous recevrez dĆ©sormais des notifications pour ce fil de discussion" @@ -4645,11 +4806,15 @@ msgstr "Votre pseudo complet sera <0>@{0}" #~ msgid "Your invite codes are hidden when logged in using an App Password" #~ msgstr "Vos codes d’invitation sont cachĆ©s lorsque vous ĆŖtes connectĆ© Ć  l’aide d’un mot de passe d’application." +#: src/components/dialogs/MutedWords.tsx:173 +msgid "Your muted words" +msgstr "" + #: src/view/com/modals/ChangePassword.tsx:155 msgid "Your password has been changed successfully!" msgstr "" -#: src/view/com/composer/Composer.tsx:267 +#: src/view/com/composer/Composer.tsx:274 msgid "Your post has been published" msgstr "Votre post a Ć©tĆ© publiĆ©" @@ -4664,7 +4829,7 @@ msgstr "Vos posts, les likes et les blocages sont publics. Les silences (comptes msgid "Your profile" msgstr "Votre profil" -#: src/view/com/composer/Composer.tsx:266 +#: src/view/com/composer/Composer.tsx:273 msgid "Your reply has been published" msgstr "Votre rĆ©ponse a Ć©tĆ© publiĆ©e" diff --git a/src/locale/locales/hi/messages.po b/src/locale/locales/hi/messages.po index 53bcdbe350..7d852d0b5a 100644 --- a/src/locale/locales/hi/messages.po +++ b/src/locale/locales/hi/messages.po @@ -80,7 +80,7 @@ msgid "A new version of the app is available. Please update to continue using th msgstr "ऐप का ą¤ą¤• नया ą¤øą¤‚ą¤øą„ą¤•ą¤°ą¤£ ą¤‰ą¤Ŗą¤²ą¤¬ą„ą¤§ ą¤¹ą„ˆ. ą¤•ą„ƒą¤Ŗą¤Æą¤¾ ऐप का ą¤‰ą¤Ŗą¤Æą„‹ą¤— ą¤œą¤¾ą¤°ą„€ ą¤°ą¤–ą¤Øą„‡ ą¤•ą„‡ ą¤²ą¤æą¤ ą¤…ą¤Ŗą¤”ą„‡ą¤Ÿ ą¤•ą¤°ą„‡ą¤‚ą„¤" #: src/view/com/util/ViewHeader.tsx:83 -#: src/view/screens/Search/Search.tsx:624 +#: src/view/screens/Search/Search.tsx:647 msgid "Access navigation links and settings" msgstr "" @@ -131,6 +131,7 @@ msgstr "" msgid "Account unmuted" msgstr "" +#: src/components/dialogs/MutedWords.tsx:147 #: src/view/com/auth/onboarding/RecommendedFeedsItem.tsx:150 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -172,14 +173,22 @@ msgstr "विवरण ą¤œą„‹ą¤”ą¤¼ą„‡ą¤‚" msgid "Add details to report" msgstr "ą¤°ą¤æą¤Ŗą„‹ą¤°ą„ą¤Ÿ ą¤•ą¤°ą¤Øą„‡ ą¤•ą„‡ ą¤²ą¤æą¤ विवरण ą¤œą„‹ą¤”ą¤¼ą„‡ą¤‚" -#: src/view/com/composer/Composer.tsx:446 +#: src/view/com/composer/Composer.tsx:453 msgid "Add link card" msgstr "लिंक ą¤•ą¤¾ą¤°ą„ą¤” ą¤œą„‹ą¤”ą¤¼ą„‡ą¤‚" -#: src/view/com/composer/Composer.tsx:451 +#: src/view/com/composer/Composer.tsx:458 msgid "Add link card:" msgstr "लिंक ą¤•ą¤¾ą¤°ą„ą¤” ą¤œą„‹ą¤”ą¤¼ą„‡ą¤‚:" +#: src/components/dialogs/MutedWords.tsx:140 +msgid "Add mute word for configured settings" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:74 +msgid "Add muted words and tags" +msgstr "" + #: src/view/com/modals/ChangeHandle.tsx:417 msgid "Add the following DNS record to your domain:" msgstr "ą¤…ą¤Ŗą¤Øą„‡ ą¤”ą„‹ą¤®ą„‡ą¤Ø ą¤®ą„‡ą¤‚ ą¤Øą¤æą¤®ą„ą¤Øą¤²ą¤æą¤–ą¤æą¤¤ DNS ą¤°ą¤æą¤•ą„‰ą¤°ą„ą¤” ą¤œą„‹ą¤”ą¤¼ą„‡ą¤‚:" @@ -303,7 +312,7 @@ msgstr "" msgid "App Passwords" msgstr "ऐप ą¤Ŗą¤¾ą¤øą¤µą¤°ą„ą¤”" -#: src/view/com/util/forms/PostDropdownBtn.tsx:279 +#: src/view/com/util/forms/PostDropdownBtn.tsx:295 msgid "Appeal content warning" msgstr "" @@ -327,15 +336,16 @@ msgstr "ą¤¦ą¤æą¤–ą¤¾ą¤µą¤Ÿ" msgid "Are you sure you want to delete the app password \"{name}\"?" msgstr "ą¤•ą„ą¤Æą¤¾ आप ą¤µą¤¾ą¤•ą¤ˆ ऐप ą¤Ŗą¤¾ą¤øą¤µą¤°ą„ą¤” \"{name}\" हटाना ą¤šą¤¾ą¤¹ą¤¤ą„‡ ą¤¹ą„ˆą¤‚?" -#: src/view/com/composer/Composer.tsx:143 +#: src/view/com/composer/Composer.tsx:150 msgid "Are you sure you'd like to discard this draft?" msgstr "ą¤•ą„ą¤Æą¤¾ आप ą¤µą¤¾ą¤•ą¤ˆ इस ą¤”ą„ą¤°ą¤¾ą¤«ą„ą¤Ÿ ą¤•ą„‹ हटाना करना ą¤šą¤¾ą¤¹ą„‡ą¤‚ą¤—ą„‡?" +#: src/components/dialogs/MutedWords.tsx:233 #: src/view/screens/ProfileList.tsx:365 msgid "Are you sure?" msgstr "ą¤•ą„ą¤Æą¤¾ आप ą¤µą¤¾ą¤øą„ą¤¤ą¤µ ą¤®ą„‡ą¤‚ ą¤‡ą¤øą„‡ करना ą¤šą¤¾ą¤¹ą¤¤ą„‡ ą¤¹ą„ˆą¤‚?" -#: src/view/com/util/forms/PostDropdownBtn.tsx:262 +#: src/view/com/util/forms/PostDropdownBtn.tsx:278 msgid "Are you sure? This cannot be undone." msgstr "ą¤•ą„ą¤Æą¤¾ आप ą¤µą¤¾ą¤øą„ą¤¤ą¤µ ą¤®ą„‡ą¤‚ ą¤‡ą¤øą„‡ करना ą¤šą¤¾ą¤¹ą¤¤ą„‡ ą¤¹ą„ˆą¤‚? ą¤‡ą¤øą„‡ असंपादित ą¤Øą¤¹ą„€ą¤‚ किया जा सकता ą¤¹ą„ˆą„¤" @@ -357,15 +367,15 @@ msgstr "ą¤•ą¤²ą¤¾ą¤¤ą„ą¤®ą¤• या ą¤—ą„ˆą¤°-ą¤•ą¤¾ą¤®ą„ą¤• ą¤Øą¤—ą„ą¤Øą¤¤ #: src/view/com/auth/login/LoginForm.tsx:259 #: src/view/com/auth/login/SetNewPasswordForm.tsx:179 #: src/view/com/modals/report/InputIssueDetails.tsx:46 -#: src/view/com/post-thread/PostThread.tsx:471 -#: src/view/com/post-thread/PostThread.tsx:521 -#: src/view/com/post-thread/PostThread.tsx:529 +#: src/view/com/post-thread/PostThread.tsx:472 +#: src/view/com/post-thread/PostThread.tsx:522 +#: src/view/com/post-thread/PostThread.tsx:530 #: src/view/com/profile/ProfileHeader.tsx:649 #: src/view/com/util/ViewHeader.tsx:81 msgid "Back" msgstr "वापस" -#: src/view/com/post-thread/PostThread.tsx:479 +#: src/view/com/post-thread/PostThread.tsx:480 msgctxt "action" msgid "Back" msgstr "" @@ -413,7 +423,7 @@ msgstr "" msgid "Blocked" msgstr "" -#: src/view/screens/Moderation.tsx:123 +#: src/view/screens/Moderation.tsx:142 msgid "Blocked accounts" msgstr "ą¤¬ą„ą¤²ą„‰ą¤• ą¤•ą¤æą¤ ą¤—ą¤ ą¤–ą¤¾ą¤¤ą„‡" @@ -472,7 +482,7 @@ msgstr "Bluesky ą¤øą¤¾ą¤°ą„ą¤µą¤œą¤Øą¤æą¤• ą¤¹ą„ˆą„¤ą„¤" msgid "Bluesky uses invites to build a healthier community. If you don't know anybody with an invite, you can sign up for the waitlist and we'll send one soon." msgstr "ą¤¬ą„ą¤²ą„‚ą¤øą„ą¤•ą„€ ą¤ą¤• ą¤øą„ą¤µą¤øą„ą¤„ ą¤øą¤®ą„ą¤¦ą¤¾ą¤Æ ą¤¬ą¤Øą¤¾ą¤Øą„‡ ą¤•ą„‡ ą¤²ą¤æą¤ ą¤†ą¤®ą¤‚ą¤¤ą„ą¤°ą¤æą¤¤ करता ą¤¹ą„ˆą„¤ यदि आप ą¤•ą¤æą¤øą„€ ą¤•ą„‹ ą¤†ą¤®ą¤‚ą¤¤ą„ą¤°ą¤æą¤¤ ą¤Øą¤¹ą„€ą¤‚ ą¤•ą¤°ą¤¤ą„‡ ą¤¹ą„ˆą¤‚, ą¤¤ą„‹ आप ą¤Ŗą„ą¤°ą¤¤ą„€ą¤•ą„ą¤·ą¤¾ ą¤øą„‚ą¤šą„€ ą¤•ą„‡ ą¤²ą¤æą¤ साइन अप कर ą¤øą¤•ą¤¤ą„‡ ą¤¹ą„ˆą¤‚ और हम ą¤œą¤²ą„ą¤¦ ą¤¹ą„€ ą¤ą¤• ą¤­ą„‡ą¤œ ą¤¦ą„‡ą¤‚ą¤—ą„‡ą„¤ą„¤" -#: src/view/screens/Moderation.tsx:226 +#: src/view/screens/Moderation.tsx:245 msgid "Bluesky will not show your profile and posts to logged-out users. Other apps may not honor this request. This does not make your account private." msgstr "" @@ -524,8 +534,8 @@ msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must msgstr "ą¤•ą„‡ą¤µą¤² ą¤…ą¤•ą„ą¤·ą¤°, ą¤øą¤‚ą¤–ą„ą¤Æą¤¾, ą¤°ą¤æą¤•ą„ą¤¤ ą¤øą„ą¤„ą¤¾ą¤Ø, ą¤”ą„ˆą¤¶ और ą¤…ą¤‚ą¤”ą¤°ą¤øą„ą¤•ą„‹ą¤° ą¤¹ą„‹ ą¤øą¤•ą¤¤ą„‡ ą¤¹ą„ˆą¤‚ą„¤ कम ą¤øą„‡ कम 4 ą¤…ą¤•ą„ą¤·ą¤° लंबा ą¤¹ą„‹ą¤Øą¤¾ ą¤šą¤¾ą¤¹ą¤æą¤, ą¤²ą„‡ą¤•ą¤æą¤Ø 32 ą¤…ą¤•ą„ą¤·ą¤°ą„‹ą¤‚ ą¤øą„‡ अधिक लंबा ą¤Øą¤¹ą„€ą¤‚ ą¤¹ą„‹ą¤Øą¤¾ ą¤šą¤¾ą¤¹ą¤æą¤ą„¤ą„¤" #: src/components/Prompt.tsx:91 -#: src/view/com/composer/Composer.tsx:300 -#: src/view/com/composer/Composer.tsx:305 +#: src/view/com/composer/Composer.tsx:307 +#: src/view/com/composer/Composer.tsx:312 #: src/view/com/modals/ChangeEmail.tsx:218 #: src/view/com/modals/ChangeEmail.tsx:220 #: src/view/com/modals/ChangePassword.tsx:265 @@ -539,7 +549,7 @@ msgstr "ą¤•ą„‡ą¤µą¤² ą¤…ą¤•ą„ą¤·ą¤°, ą¤øą¤‚ą¤–ą„ą¤Æą¤¾, ą¤°ą¤æą¤•ą„ą¤¤ ą¤øą„ #: src/view/com/modals/VerifyEmail.tsx:247 #: src/view/com/modals/VerifyEmail.tsx:253 #: src/view/com/modals/Waitlist.tsx:142 -#: src/view/screens/Search/Search.tsx:693 +#: src/view/screens/Search/Search.tsx:716 #: src/view/shell/desktop/Search.tsx:238 msgid "Cancel" msgstr "ą¤•ą„ˆą¤‚ą¤øą¤æą¤²" @@ -690,7 +700,7 @@ msgid "Clear all storage data (restart after this)" msgstr "" #: src/view/com/util/forms/SearchInput.tsx:88 -#: src/view/screens/Search/Search.tsx:674 +#: src/view/screens/Search/Search.tsx:697 msgid "Clear search query" msgstr "ą¤–ą„‹ą¤œ ą¤•ą„ą¤µą„‡ą¤°ą„€ साफ़ ą¤•ą¤°ą„‡ą¤‚" @@ -698,6 +708,11 @@ msgstr "ą¤–ą„‹ą¤œ ą¤•ą„ą¤µą„‡ą¤°ą„€ साफ़ ą¤•ą¤°ą„‡ą¤‚" msgid "click here" msgstr "" +#: src/components/RichText.tsx:189 +#: src/components/TagMenu/index.web.tsx:125 +msgid "Click here to open tag menu for {tag}" +msgstr "" + #: src/screens/Onboarding/index.tsx:35 msgid "Climate" msgstr "" @@ -728,11 +743,15 @@ msgstr "छवि बंद ą¤•ą¤°ą„‡ą¤‚" msgid "Close image viewer" msgstr "छवि बंद ą¤•ą¤°ą„‡ą¤‚" -#: src/view/shell/index.web.tsx:49 +#: src/view/shell/index.web.tsx:51 msgid "Close navigation footer" msgstr "ą¤Øą„‡ą¤µą¤æą¤—ą„‡ą¤¶ą¤Ø पाद बंद ą¤•ą¤°ą„‡ą¤‚" -#: src/view/shell/index.web.tsx:50 +#: src/components/TagMenu/index.tsx:266 +msgid "Close this dialog" +msgstr "" + +#: src/view/shell/index.web.tsx:52 msgid "Closes bottom navigation bar" msgstr "" @@ -740,7 +759,7 @@ msgstr "" msgid "Closes password update alert" msgstr "" -#: src/view/com/composer/Composer.tsx:302 +#: src/view/com/composer/Composer.tsx:309 msgid "Closes post composer and discards post draft" msgstr "" @@ -773,7 +792,7 @@ msgstr "" msgid "Complete the challenge" msgstr "" -#: src/view/com/composer/Composer.tsx:417 +#: src/view/com/composer/Composer.tsx:424 msgid "Compose posts up to {MAX_GRAPHEME_LENGTH} characters in length" msgstr "" @@ -837,7 +856,7 @@ msgstr "ą¤•ą¤Øą„‡ą¤•ą„ą¤Ÿą¤æą¤‚ą¤— ..ą„¤" msgid "Contact support" msgstr "" -#: src/view/screens/Moderation.tsx:81 +#: src/view/screens/Moderation.tsx:83 msgid "Content filtering" msgstr "ą¤øą¤¾ą¤®ą¤—ą„ą¤°ą„€ ą¤«ą¤¼ą¤æą¤²ą„ą¤Ÿą¤°ą¤æą¤‚ą¤—" @@ -903,7 +922,7 @@ msgstr "" #: src/view/com/modals/AddAppPasswords.tsx:76 #: src/view/com/modals/InviteCodes.tsx:152 -#: src/view/com/util/forms/PostDropdownBtn.tsx:141 +#: src/view/com/util/forms/PostDropdownBtn.tsx:143 msgid "Copied to clipboard" msgstr "" @@ -919,7 +938,7 @@ msgstr "ą¤•ą„‰ą¤Ŗą„€" msgid "Copy link to list" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 msgid "Copy link to post" msgstr "" @@ -927,7 +946,7 @@ msgstr "" msgid "Copy link to profile" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:168 +#: src/view/com/util/forms/PostDropdownBtn.tsx:170 msgid "Copy post text" msgstr "ą¤Ŗą„‹ą¤øą„ą¤Ÿ ą¤Ÿą„‡ą¤•ą„ą¤øą„ą¤Ÿ ą¤•ą„‰ą¤Ŗą„€ ą¤•ą¤°ą„‡ą¤‚" @@ -983,7 +1002,7 @@ msgstr "" msgid "Created by you" msgstr "" -#: src/view/com/composer/Composer.tsx:448 +#: src/view/com/composer/Composer.tsx:455 msgid "Creates a card with a thumbnail. The card links to {url}" msgstr "" @@ -1060,11 +1079,11 @@ msgstr "ą¤®ą„‡ą¤°ą¤¾ खाता ą¤¹ą¤Ÿą¤¾ą¤ą¤‚" msgid "Delete My Account…" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:257 +#: src/view/com/util/forms/PostDropdownBtn.tsx:273 msgid "Delete post" msgstr "ą¤Ŗą„‹ą¤øą„ą¤Ÿ ą¤•ą„‹ ą¤¹ą¤Ÿą¤¾ą¤ą¤‚" -#: src/view/com/util/forms/PostDropdownBtn.tsx:261 +#: src/view/com/util/forms/PostDropdownBtn.tsx:277 msgid "Delete this post?" msgstr "इस ą¤Ŗą„‹ą¤øą„ą¤Ÿ ą¤•ą„‹ ą¤”ą„€ą¤²ą„€ą¤Ÿ ą¤•ą¤°ą„‡ą¤‚?" @@ -1087,7 +1106,7 @@ msgstr "विवरण" #~ msgid "Developer Tools" #~ msgstr "ą¤”ą„‡ą¤µą¤²ą¤Ŗą¤° उपकरण" -#: src/view/com/composer/Composer.tsx:211 +#: src/view/com/composer/Composer.tsx:218 msgid "Did you want to say anything?" msgstr "" @@ -1095,15 +1114,15 @@ msgstr "" msgid "Dim" msgstr "" -#: src/view/com/composer/Composer.tsx:144 +#: src/view/com/composer/Composer.tsx:151 msgid "Discard" msgstr "" -#: src/view/com/composer/Composer.tsx:138 +#: src/view/com/composer/Composer.tsx:145 msgid "Discard draft" msgstr "ą¤”ą„ą¤°ą¤¾ą¤«ą„ą¤Ÿ ą¤¹ą¤Ÿą¤¾ą¤ą¤‚" -#: src/view/screens/Moderation.tsx:207 +#: src/view/screens/Moderation.tsx:226 msgid "Discourage apps from showing my account to logged-out users" msgstr "" @@ -1182,7 +1201,7 @@ msgstr "" msgid "Download CAR file" msgstr "" -#: src/view/com/composer/text-input/TextInput.web.tsx:247 +#: src/view/com/composer/text-input/TextInput.web.tsx:249 msgid "Drop to add images" msgstr "" @@ -1254,6 +1273,7 @@ msgstr "ą¤®ą„‡ą¤°ą„€ ą¤Ŗą„ą¤°ą„‹ą¤«ą¤¼ą¤¾ą¤‡ą¤² संपादित ą¤•ą¤°ą„‡ msgid "Edit Profile" msgstr "ą¤®ą„‡ą¤°ą„€ ą¤Ŗą„ą¤°ą„‹ą¤«ą¤¼ą¤¾ą¤‡ą¤² संपादित ą¤•ą¤°ą„‡ą¤‚" +#: src/view/com/home/HomeHeaderLayout.web.tsx:59 #: src/view/screens/Feeds.tsx:355 msgid "Edit Saved Feeds" msgstr "ą¤ą¤”ą¤æą¤Ÿ ą¤øą„‡ą¤µą„ą¤” ą¤«ą„€ą¤”" @@ -1336,6 +1356,11 @@ msgstr "" msgid "Enter a name for this App Password" msgstr "" +#: src/components/dialogs/MutedWords.tsx:87 +#: src/components/dialogs/MutedWords.tsx:88 +msgid "Enter a word or tag" +msgstr "" + #: src/view/com/modals/VerifyEmail.tsx:105 msgid "Enter Confirmation Code" msgstr "" @@ -1385,7 +1410,7 @@ msgstr "ą¤…ą¤Ŗą¤Øą„‡ ą¤Æą„‚ą¤œą¤¼ą¤°ą¤Øą„‡ą¤® और ą¤Ŗą¤¾ą¤øą¤µą¤°ą„ą¤” द msgid "Error receiving captcha response." msgstr "" -#: src/view/screens/Search/Search.tsx:109 +#: src/view/screens/Search/Search.tsx:110 msgid "Error:" msgstr "" @@ -1456,7 +1481,7 @@ msgstr "" msgid "Failed to create the list. Check your internet connection and try again." msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:108 +#: src/view/com/util/forms/PostDropdownBtn.tsx:110 msgid "Failed to delete post, please try again" msgstr "" @@ -1478,8 +1503,8 @@ msgid "Feed offline" msgstr "ą¤«ą¤¼ą„€ą¤” ऑफ़लाइन ą¤¹ą„ˆ" #: src/view/com/feeds/FeedPage.tsx:143 -msgid "Feed Preferences" -msgstr "ą¤«ą¤¼ą„€ą¤” ą¤Ŗą„ą¤°ą¤¾ą¤„ą¤®ą¤æą¤•ą¤¤ą¤¾" +#~ msgid "Feed Preferences" +#~ msgstr "ą¤«ą¤¼ą„€ą¤” ą¤Ŗą„ą¤°ą¤¾ą¤„ą¤®ą¤æą¤•ą¤¤ą¤¾" #: src/view/shell/desktop/RightNav.tsx:61 #: src/view/shell/Drawer.tsx:311 @@ -1527,11 +1552,11 @@ msgstr "" msgid "Find accounts to follow" msgstr "" -#: src/view/screens/Search/Search.tsx:439 +#: src/view/screens/Search/Search.tsx:440 msgid "Find users on Bluesky" msgstr "" -#: src/view/screens/Search/Search.tsx:437 +#: src/view/screens/Search/Search.tsx:438 msgid "Find users with the search tool on the right" msgstr "" @@ -1628,6 +1653,7 @@ msgid "Following {0}" msgstr "" #: src/Navigation.tsx:248 +#: src/view/com/home/HomeHeaderLayout.web.tsx:45 #: src/view/com/home/HomeHeaderLayoutMobile.tsx:83 #: src/view/screens/PreferencesFollowingFeed.tsx:104 #: src/view/screens/Settings/index.tsx:543 @@ -1667,7 +1693,7 @@ msgstr "ą¤Ŗą¤¾ą¤øą¤µą¤°ą„ą¤” ą¤­ą„‚ą¤² ą¤—ą¤" msgid "Forgot Password" msgstr "ą¤Ŗą¤¾ą¤øą¤µą¤°ą„ą¤” ą¤­ą„‚ą¤² ą¤—ą¤" -#: src/view/com/posts/FeedItem.tsx:187 +#: src/view/com/posts/FeedItem.tsx:189 msgctxt "from-feed" msgid "From <0/>" msgstr "" @@ -1700,7 +1726,7 @@ msgstr "वापस ą¤œą¤¾ą¤“" msgid "Go back to previous step" msgstr "" -#: src/view/screens/Search/Search.tsx:724 +#: src/view/screens/Search/Search.tsx:747 #: src/view/shell/desktop/Search.tsx:262 msgid "Go to @{queryMaybeHandle}" msgstr "" @@ -1717,6 +1743,10 @@ msgstr "अगला" msgid "Handle" msgstr "ą¤¹ą„ˆą¤‚ą¤”ą¤²" +#: src/components/RichText.tsx:188 +msgid "Hashtag: {tag}" +msgstr "" + #: src/view/com/auth/create/CreateAccount.tsx:208 msgid "Having trouble?" msgstr "" @@ -1755,7 +1785,7 @@ msgctxt "action" msgid "Hide" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +#: src/view/com/util/forms/PostDropdownBtn.tsx:232 msgid "Hide post" msgstr "" @@ -1764,7 +1794,7 @@ msgstr "" msgid "Hide the content" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:220 +#: src/view/com/util/forms/PostDropdownBtn.tsx:236 msgid "Hide this post?" msgstr "" @@ -1913,7 +1943,7 @@ msgstr "" msgid "Input your user handle" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:224 +#: src/view/com/post-thread/PostThreadItem.tsx:226 msgid "Invalid or unsupported post record" msgstr "" @@ -2015,7 +2045,7 @@ msgstr "अधिक ą¤œą¤¾ą¤Øą„‡ą¤‚" msgid "Learn more about this warning" msgstr "इस ą¤šą„‡ą¤¤ą¤¾ą¤µą¤Øą„€ ą¤•ą„‡ ą¤¬ą¤¾ą¤°ą„‡ ą¤®ą„‡ą¤‚ अधिक ą¤œą¤¾ą¤Øą„‡ą¤‚" -#: src/view/screens/Moderation.tsx:243 +#: src/view/screens/Moderation.tsx:262 msgid "Learn more about what is public on Bluesky." msgstr "" @@ -2091,7 +2121,7 @@ msgstr "" msgid "Likes" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:181 +#: src/view/com/post-thread/PostThreadItem.tsx:183 msgid "Likes on this post" msgstr "" @@ -2148,7 +2178,7 @@ msgstr "अधिक ą¤Ŗą„‹ą¤øą„ą¤Ÿ ą¤²ą„‹ą¤” ą¤•ą¤°ą„‡ą¤‚" msgid "Load new notifications" msgstr "नई ą¤øą„‚ą¤šą¤Øą¤¾ą¤ą¤‚ ą¤²ą„‹ą¤” ą¤•ą¤°ą„‡ą¤‚" -#: src/view/com/feeds/FeedPage.tsx:181 +#: src/view/com/feeds/FeedPage.tsx:115 #: src/view/screens/Profile.tsx:440 #: src/view/screens/ProfileFeed.tsx:495 #: src/view/screens/ProfileList.tsx:681 @@ -2174,7 +2204,7 @@ msgstr "" msgid "Log out" msgstr "" -#: src/view/screens/Moderation.tsx:136 +#: src/view/screens/Moderation.tsx:155 msgid "Logged-out visibility" msgstr "" @@ -2186,6 +2216,10 @@ msgstr "उस ą¤–ą¤¾ą¤¤ą„‡ ą¤®ą„‡ą¤‚ ą¤²ą„‰ą¤— इन ą¤•ą¤°ą„‡ą¤‚ ą¤œą„‹ स msgid "Make sure this is where you intend to go!" msgstr "यह ą¤øą„ą¤Øą¤æą¤¶ą„ą¤šą¤æą¤¤ ą¤•ą¤°ą¤Øą„‡ ą¤•ą„‡ ą¤²ą¤æą¤ कि आप कहाँ जाना ą¤šą¤¾ą¤¹ą¤¤ą„‡ ą¤¹ą„ˆą¤‚!" +#: src/components/dialogs/MutedWords.tsx:71 +msgid "Manage your muted words and tags" +msgstr "" + #: src/view/com/auth/create/Step2.tsx:118 msgid "May not be longer than 253 characters" msgstr "" @@ -2207,7 +2241,7 @@ msgid "Mentioned users" msgstr "" #: src/view/com/util/ViewHeader.tsx:81 -#: src/view/screens/Search/Search.tsx:623 +#: src/view/screens/Search/Search.tsx:646 msgid "Menu" msgstr "ą¤®ą„‡ą¤Øą„‚" @@ -2216,7 +2250,7 @@ msgid "Message from server: {0}" msgstr "" #: src/Navigation.tsx:115 -#: src/view/screens/Moderation.tsx:64 +#: src/view/screens/Moderation.tsx:66 #: src/view/screens/Settings/index.tsx:625 #: src/view/shell/desktop/LeftNav.tsx:397 #: src/view/shell/Drawer.tsx:511 @@ -2247,7 +2281,7 @@ msgstr "" msgid "Moderation list updated" msgstr "" -#: src/view/screens/Moderation.tsx:95 +#: src/view/screens/Moderation.tsx:114 msgid "Moderation lists" msgstr "ą¤®ą„‰ą¤”ą¤°ą„‡ą¤¶ą¤Ø ą¤øą„‚ą¤šą¤æą¤Æą¤¾ą¤" @@ -2274,7 +2308,7 @@ msgstr "अधिक ą¤«ą¤¼ą„€ą¤”" msgid "More options" msgstr "अधिक ą¤µą¤æą¤•ą¤²ą„ą¤Ŗ" -#: src/view/com/util/forms/PostDropdownBtn.tsx:299 +#: src/view/com/util/forms/PostDropdownBtn.tsx:315 msgid "More post options" msgstr "ą¤Ŗą„‹ą¤øą„ą¤Ÿ ą¤µą¤æą¤•ą¤²ą„ą¤Ŗ" @@ -2286,6 +2320,14 @@ msgstr "" msgid "Must be at least 3 characters" msgstr "" +#: src/components/TagMenu/index.tsx:253 +msgid "Mute" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:91 +msgid "Mute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:327 msgid "Mute Account" msgstr "खाता ą¤®ą„ą¤Æą„‚ą¤Ÿ ą¤•ą¤°ą„‡ą¤‚" @@ -2294,6 +2336,18 @@ msgstr "खाता ą¤®ą„ą¤Æą„‚ą¤Ÿ ą¤•ą¤°ą„‡ą¤‚" msgid "Mute accounts" msgstr "ą¤–ą¤¾ą¤¤ą„‹ą¤‚ ą¤•ą„‹ ą¤®ą„ą¤Æą„‚ą¤Ÿ ą¤•ą¤°ą„‡ą¤‚" +#: src/components/TagMenu/index.tsx:211 +msgid "Mute all {tag} posts" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:131 +msgid "Mute in tags only" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:116 +msgid "Mute in text & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:491 msgid "Mute list" msgstr "" @@ -2306,15 +2360,27 @@ msgstr "इन ą¤–ą¤¾ą¤¤ą„‹ą¤‚ ą¤•ą„‹ ą¤®ą„ą¤Æą„‚ą¤Ÿ ą¤•ą¤°ą„‡ą¤‚?" msgid "Mute this List" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/dialogs/MutedWords.tsx:109 +msgid "Mute this word in post text and tags" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:124 +msgid "Mute this word in tags only" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Mute thread" msgstr "ą¤„ą„ą¤°ą„‡ą¤” ą¤®ą„ą¤Æą„‚ą¤Ÿ ą¤•ą¤°ą„‡ą¤‚" +#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +msgid "Mute words & tags" +msgstr "" + #: src/view/com/lists/ListCard.tsx:102 msgid "Muted" msgstr "" -#: src/view/screens/Moderation.tsx:109 +#: src/view/screens/Moderation.tsx:128 msgid "Muted accounts" msgstr "ą¤®ą„ą¤Æą„‚ą¤Ÿ ą¤•ą¤æą¤ ą¤—ą¤ ą¤–ą¤¾ą¤¤ą„‡" @@ -2327,6 +2393,10 @@ msgstr "ą¤®ą„ą¤Æą„‚ą¤Ÿ ą¤•ą¤æą¤ ą¤—ą¤ ą¤–ą¤¾ą¤¤ą„‡" msgid "Muted accounts have their posts removed from your feed and from your notifications. Mutes are completely private." msgstr "ą¤®ą„ą¤Æą„‚ą¤Ÿ ą¤•ą¤æą¤ ą¤—ą¤ ą¤–ą¤¾ą¤¤ą„‹ą¤‚ ą¤•ą„€ ą¤Ŗą„‹ą¤øą„ą¤Ÿ ą¤†ą¤Ŗą¤•ą„‡ ą¤«ą¤¼ą„€ą¤” और ą¤†ą¤Ŗą¤•ą„€ ą¤øą„‚ą¤šą¤Øą¤¾ą¤“ą¤‚ ą¤øą„‡ हटा ą¤¦ą„€ ą¤œą¤¾ą¤¤ą„€ ą¤¹ą„ˆą¤‚ą„¤ ą¤®ą„ą¤Æą„‚ą¤Ÿ ą¤Ŗą„‚ą¤°ą„€ तरह ą¤øą„‡ ą¤Øą¤æą¤œą„€ ą¤¹ą„ˆą¤‚." +#: src/view/screens/Moderation.tsx:100 +msgid "Muted words & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:277 msgid "Muting is private. Muted accounts can interact with you, but you will not see their posts or receive notifications from them." msgstr "ą¤®ą„ą¤Æą„‚ą¤Ÿ करना ą¤Øą¤æą¤œą„€ ą¤¹ą„ˆ. ą¤®ą„ą¤Æą„‚ą¤Ÿ ą¤•ą¤æą¤ ą¤—ą¤ ą¤–ą¤¾ą¤¤ą„‡ ą¤†ą¤Ŗą¤•ą„‡ साऄ ą¤‡ą¤‚ą¤Ÿą¤°ą„ˆą¤•ą„ą¤Ÿ कर ą¤øą¤•ą¤¤ą„‡ ą¤¹ą„ˆą¤‚, ą¤²ą„‡ą¤•ą¤æą¤Ø आप ą¤‰ą¤Øą¤•ą„€ ą¤Ŗą„‹ą¤øą„ą¤Ÿ ą¤Øą¤¹ą„€ą¤‚ ą¤¦ą„‡ą¤–ą„‡ą¤‚ą¤—ą„‡ या ą¤‰ą¤Øą¤øą„‡ ą¤øą„‚ą¤šą¤Øą¤¾ą¤ą¤‚ ą¤Ŗą„ą¤°ą¤¾ą¤Ŗą„ą¤¤ ą¤Øą¤¹ą„€ą¤‚ ą¤•ą¤°ą„‡ą¤‚ą¤—ą„‡ą„¤" @@ -2390,6 +2460,10 @@ msgstr "ą¤…ą¤Ŗą¤Øą„‡ ą¤«ą¤¼ą„‰ą¤²ą„‹ą¤…ą¤°ą„ą¤ø और ą¤”ą„‡ą¤Ÿą¤¾ तक प msgid "Never lose access to your followers or data." msgstr "" +#: src/components/dialogs/MutedWords.tsx:244 +msgid "Nevermind" +msgstr "" + #: src/view/screens/Lists.tsx:76 msgctxt "action" msgid "New" @@ -2411,7 +2485,7 @@ msgstr "" msgid "New Password" msgstr "" -#: src/view/com/feeds/FeedPage.tsx:192 +#: src/view/com/feeds/FeedPage.tsx:126 msgctxt "action" msgid "New post" msgstr "" @@ -2496,8 +2570,8 @@ msgid "No results found for \"{query}\"" msgstr "\"{query}\" ą¤•ą„‡ ą¤²ą¤æą¤ ą¤•ą„‹ą¤ˆ परिणाम ą¤Øą¤¹ą„€ą¤‚ मिला" #: src/view/com/modals/ListAddRemoveUsers.tsx:127 -#: src/view/screens/Search/Search.tsx:280 -#: src/view/screens/Search/Search.tsx:308 +#: src/view/screens/Search/Search.tsx:281 +#: src/view/screens/Search/Search.tsx:309 msgid "No results found for {query}" msgstr "{query} ą¤•ą„‡ ą¤²ą¤æą¤ ą¤•ą„‹ą¤ˆ परिणाम ą¤Øą¤¹ą„€ą¤‚ मिला\"" @@ -2523,7 +2597,7 @@ msgstr "" msgid "Not right now" msgstr "" -#: src/view/screens/Moderation.tsx:233 +#: src/view/screens/Moderation.tsx:252 msgid "Note: Bluesky is an open and public network. This setting only limits the visibility of your content on the Bluesky app and website, and other apps may not respect this setting. Your content may still be shown to logged-out users by other apps and websites." msgstr "" @@ -2561,7 +2635,7 @@ msgstr "" msgid "Onboarding reset" msgstr "" -#: src/view/com/composer/Composer.tsx:375 +#: src/view/com/composer/Composer.tsx:382 msgid "One or more images is missing alt text." msgstr "ą¤ą¤• या अधिक छवियाँ alt पाठ याद ą¤†ą¤¤ą„€ ą¤¹ą„ˆą¤‚ą„¤ą„¤" @@ -2578,8 +2652,12 @@ msgstr "" msgid "Open" msgstr "" -#: src/view/com/composer/Composer.tsx:470 -#: src/view/com/composer/Composer.tsx:471 +#: src/view/screens/Moderation.tsx:75 +msgid "Open content filtering settings" +msgstr "" + +#: src/view/com/composer/Composer.tsx:477 +#: src/view/com/composer/Composer.tsx:478 msgid "Open emoji picker" msgstr "" @@ -2587,6 +2665,10 @@ msgstr "" msgid "Open links with in-app browser" msgstr "" +#: src/view/screens/Moderation.tsx:92 +msgid "Open muted words settings" +msgstr "" + #: src/view/com/home/HomeHeaderLayoutMobile.tsx:49 msgid "Open navigation" msgstr "ओपन ą¤Øą„‡ą¤µą¤æą¤—ą„‡ą¤¶ą¤Ø" @@ -2663,6 +2745,7 @@ msgstr "ą¤®ą„‰ą¤”ą¤°ą„‡ą¤¶ą¤Ø ą¤øą„‡ą¤Ÿą¤æą¤‚ą¤—ą„ą¤ø ą¤–ą„‹ą¤²ą„‡ą¤‚" msgid "Opens password reset form" msgstr "" +#: src/view/com/home/HomeHeaderLayout.web.tsx:60 #: src/view/screens/Feeds.tsx:356 msgid "Opens screen to edit Saved Feeds" msgstr "" @@ -2842,7 +2925,7 @@ msgstr "" msgid "Please Verify Your Email" msgstr "" -#: src/view/com/composer/Composer.tsx:215 +#: src/view/com/composer/Composer.tsx:222 msgid "Please wait for your link card to finish loading" msgstr "" @@ -2854,8 +2937,8 @@ msgstr "" msgid "Porn" msgstr "" -#: src/view/com/composer/Composer.tsx:350 -#: src/view/com/composer/Composer.tsx:358 +#: src/view/com/composer/Composer.tsx:357 +#: src/view/com/composer/Composer.tsx:365 msgctxt "action" msgid "Post" msgstr "" @@ -2865,7 +2948,7 @@ msgctxt "description" msgid "Post" msgstr "ą¤Ŗą„‹ą¤øą„ą¤Ÿ" -#: src/view/com/post-thread/PostThreadItem.tsx:173 +#: src/view/com/post-thread/PostThreadItem.tsx:175 msgid "Post by {0}" msgstr "" @@ -2875,11 +2958,11 @@ msgstr "" msgid "Post by @{0}" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:88 +#: src/view/com/util/forms/PostDropdownBtn.tsx:90 msgid "Post deleted" msgstr "" -#: src/view/com/post-thread/PostThread.tsx:461 +#: src/view/com/post-thread/PostThread.tsx:462 msgid "Post hidden" msgstr "ą¤›ą„ą¤Ŗą¤¾ ą¤Ŗą„‹ą¤øą„ą¤Ÿ" @@ -2891,14 +2974,22 @@ msgstr "ą¤Ŗą„‹ą¤øą„ą¤Ÿ भाषा" msgid "Post Languages" msgstr "ą¤Ŗą„‹ą¤øą„ą¤Ÿ भाषा" -#: src/view/com/post-thread/PostThread.tsx:513 +#: src/view/com/post-thread/PostThread.tsx:514 msgid "Post not found" msgstr "ą¤Ŗą„‹ą¤øą„ą¤Ÿ ą¤Øą¤¹ą„€ą¤‚ मिला" +#: src/components/TagMenu/index.tsx:257 +msgid "posts" +msgstr "" + #: src/view/screens/Profile.tsx:180 msgid "Posts" msgstr "" +#: src/components/dialogs/MutedWords.tsx:77 +msgid "Posts can be muted based on their text, their tags, or both." +msgstr "" + #: src/view/com/posts/FeedErrorMessage.tsx:64 msgid "Posts hidden" msgstr "" @@ -2963,11 +3054,11 @@ msgstr "" msgid "Public, shareable lists which can drive feeds." msgstr "ą¤øą¤¾ą¤°ą„ą¤µą¤œą¤Øą¤æą¤•, ą¤øą¤¾ą¤ą¤¾ ą¤•ą¤°ą¤Øą„‡ ą¤Æą„‹ą¤—ą„ą¤Æ ą¤øą„‚ą¤šą¤æą¤Æą¤¾ą¤ ą¤œą„‹ ą¤«ą¤¼ą„€ą¤” चला ą¤øą¤•ą¤¤ą„€ ą¤¹ą„ˆą¤‚ą„¤" -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish post" msgstr "" -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish reply" msgstr "" @@ -3001,6 +3092,7 @@ msgstr "ą¤…ą¤Øą„ą¤¶ą¤‚ą¤øą¤æą¤¤ ą¤«ą¤¼ą„€ą¤”" msgid "Recommended Users" msgstr "ą¤…ą¤Øą„ą¤¶ą¤‚ą¤øą¤æą¤¤ ą¤²ą„‹ą¤—" +#: src/components/dialogs/MutedWords.tsx:249 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/SelfLabel.tsx:83 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -3038,6 +3130,10 @@ msgstr "छवि ą¤Øą¤æą¤•ą¤¾ą¤²ą„‡ą¤‚" msgid "Remove image preview" msgstr "छवि ą¤Ŗą„‚ą¤°ą„ą¤µą¤¾ą¤µą¤²ą„‹ą¤•ą¤Ø ą¤Øą¤æą¤•ą¤¾ą¤²ą„‡ą¤‚" +#: src/components/dialogs/MutedWords.tsx:294 +msgid "Remove mute word from your list" +msgstr "" + #: src/view/com/modals/Repost.tsx:47 msgid "Remove repost" msgstr "" @@ -3072,7 +3168,7 @@ msgstr "" msgid "Replies to this thread are disabled" msgstr "" -#: src/view/com/composer/Composer.tsx:348 +#: src/view/com/composer/Composer.tsx:355 msgctxt "action" msgid "Reply" msgstr "" @@ -3082,7 +3178,7 @@ msgid "Reply Filters" msgstr "ą¤«ą¤æą¤²ą„ą¤Ÿą¤°" #: src/view/com/post/Post.tsx:167 -#: src/view/com/posts/FeedItem.tsx:285 +#: src/view/com/posts/FeedItem.tsx:287 msgctxt "description" msgid "Reply to <0/>" msgstr "" @@ -3104,7 +3200,7 @@ msgid "Report List" msgstr "ą¤°ą¤æą¤Ŗą„‹ą¤°ą„ą¤Ÿ ą¤øą„‚ą¤šą„€" #: src/view/com/modals/report/SendReportButton.tsx:37 -#: src/view/com/util/forms/PostDropdownBtn.tsx:239 +#: src/view/com/util/forms/PostDropdownBtn.tsx:255 msgid "Report post" msgstr "ą¤°ą¤æą¤Ŗą„‹ą¤°ą„ą¤Ÿ ą¤Ŗą„‹ą¤øą„ą¤Ÿ" @@ -3129,11 +3225,11 @@ msgstr "ą¤Ŗą„‹ą¤øą„ą¤Ÿ ą¤¦ą„‹ą¤¬ą¤¾ą¤°ą¤¾ ą¤Ŗą„‹ą¤øą„ą¤Ÿ ą¤•ą¤°ą„‡ą¤‚ या msgid "Reposted By" msgstr "ą¤¦ą„ą¤µą¤¾ą¤°ą¤¾ ą¤¦ą„‹ą¤¬ą¤¾ą¤°ą¤¾ ą¤Ŗą„‹ą¤øą„ą¤Ÿ किया गया" -#: src/view/com/posts/FeedItem.tsx:205 +#: src/view/com/posts/FeedItem.tsx:207 msgid "Reposted by {0}" msgstr "" -#: src/view/com/posts/FeedItem.tsx:222 +#: src/view/com/posts/FeedItem.tsx:224 msgid "Reposted by <0/>" msgstr "" @@ -3141,7 +3237,7 @@ msgstr "" msgid "reposted your post" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:186 +#: src/view/com/post-thread/PostThreadItem.tsx:188 msgid "Reposts of this post" msgstr "" @@ -3292,9 +3388,9 @@ msgstr "" #: src/view/com/modals/ListAddRemoveUsers.tsx:75 #: src/view/com/util/forms/SearchInput.tsx:67 #: src/view/com/util/forms/SearchInput.tsx:79 -#: src/view/screens/Search/Search.tsx:418 -#: src/view/screens/Search/Search.tsx:645 -#: src/view/screens/Search/Search.tsx:663 +#: src/view/screens/Search/Search.tsx:419 +#: src/view/screens/Search/Search.tsx:668 +#: src/view/screens/Search/Search.tsx:686 #: src/view/shell/bottom-bar/BottomBar.tsx:159 #: src/view/shell/desktop/LeftNav.tsx:324 #: src/view/shell/desktop/Search.tsx:214 @@ -3304,11 +3400,19 @@ msgstr "" msgid "Search" msgstr "ą¤–ą„‹ą¤œ" -#: src/view/screens/Search/Search.tsx:712 +#: src/view/screens/Search/Search.tsx:735 #: src/view/shell/desktop/Search.tsx:255 msgid "Search for \"{query}\"" msgstr "" +#: src/components/TagMenu/index.tsx:145 +msgid "Search for all posts by @{authorHandle} with tag {tag}" +msgstr "" + +#: src/components/TagMenu/index.tsx:90 +msgid "Search for all posts with tag {tag}" +msgstr "" + #: src/view/com/auth/LoggedOut.tsx:104 #: src/view/com/auth/LoggedOut.tsx:105 #: src/view/com/modals/ListAddRemoveUsers.tsx:70 @@ -3319,6 +3423,22 @@ msgstr "" msgid "Security Step Required" msgstr "ą¤øą„ą¤°ą¤•ą„ą¤·ą¤¾ चरण ą¤†ą¤µą¤¶ą„ą¤Æą¤•" +#: src/components/TagMenu/index.web.tsx:50 +msgid "See {truncatedTag} posts" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:67 +msgid "See {truncatedTag} posts by user" +msgstr "" + +#: src/components/TagMenu/index.tsx:128 +msgid "See <0>{tag} posts" +msgstr "" + +#: src/components/TagMenu/index.tsx:189 +msgid "See <0>{tag} posts by this user" +msgstr "" + #: src/view/screens/SavedFeeds.tsx:163 msgid "See this guide" msgstr "" @@ -3528,7 +3648,7 @@ msgid "Share" msgstr "" #: src/view/com/profile/ProfileHeader.tsx:295 -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 #: src/view/screens/ProfileList.tsx:418 msgid "Share" msgstr "ą¤¶ą„‡ą¤Æą¤°" @@ -3561,9 +3681,9 @@ msgstr "" msgid "Show follows similar to {0}" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:532 -#: src/view/com/post/Post.tsx:196 -#: src/view/com/posts/FeedItem.tsx:359 +#: src/view/com/post-thread/PostThreadItem.tsx:538 +#: src/view/com/post/Post.tsx:198 +#: src/view/com/posts/FeedItem.tsx:363 msgid "Show More" msgstr "" @@ -3731,7 +3851,7 @@ msgstr "" msgid "Something went wrong. Check your email and try again." msgstr "" -#: src/App.native.tsx:61 +#: src/App.native.tsx:63 msgid "Sorry! Your session expired. Please log in again." msgstr "" @@ -3789,7 +3909,7 @@ msgstr "" msgid "Subscribe to this list" msgstr "इस ą¤øą„‚ą¤šą„€ ą¤•ą„‹ ą¤øą¤¬ą„ą¤øą¤•ą„ą¤°ą¤¾ą¤‡ą¤¬ ą¤•ą¤°ą„‡ą¤‚" -#: src/view/screens/Search/Search.tsx:373 +#: src/view/screens/Search/Search.tsx:374 msgid "Suggested Follows" msgstr "ą¤…ą¤Øą„ą¤¶ą¤‚ą¤øą¤æą¤¤ ą¤²ą„‹ą¤—" @@ -3833,6 +3953,14 @@ msgstr "ą¤Ŗą„ą¤°ą¤£ą¤¾ą¤²ą„€" msgid "System log" msgstr "ą¤øą¤æą¤øą„ą¤Ÿą¤® ą¤²ą„‰ą¤—" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "tag" +msgstr "" + +#: src/components/TagMenu/index.tsx:74 +msgid "Tag menu: {tag}" +msgstr "" + #: src/view/com/modals/crop-image/CropImage.web.tsx:112 msgid "Tall" msgstr "लंबा" @@ -3856,6 +3984,10 @@ msgstr "ą¤¶ą¤°ą„ą¤¤ą„‡ą¤‚" msgid "Terms of Service" msgstr "ą¤øą„‡ą¤µą¤¾ ą¤•ą„€ ą¤¶ą¤°ą„ą¤¤ą„‡ą¤‚" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "text" +msgstr "" + #: src/view/com/modals/AppealLabel.tsx:70 #: src/view/com/modals/report/InputIssueDetails.tsx:51 msgid "Text input field" @@ -3881,7 +4013,7 @@ msgstr "ą¤•ą„‰ą¤Ŗą„€ą¤°ą¤¾ą¤‡ą¤Ÿ ą¤Øą„€ą¤¤ą¤æ ą¤•ą„‹ <0/> पर ą¤øą„ą¤„ą¤¾ą¤Ø msgid "The following steps will help customize your Bluesky experience." msgstr "" -#: src/view/com/post-thread/PostThread.tsx:516 +#: src/view/com/post-thread/PostThread.tsx:517 msgid "The post may have been deleted." msgstr "ą¤¹ą„‹ सकता ą¤¹ą„ˆ कि यह ą¤Ŗą„‹ą¤øą„ą¤Ÿ हटा ą¤¦ą„€ ą¤—ą¤ˆ ą¤¹ą„‹ą„¤" @@ -4047,7 +4179,7 @@ msgstr "" msgid "This name is already in use" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:123 +#: src/view/com/post-thread/PostThreadItem.tsx:125 msgid "This post has been deleted." msgstr "इस ą¤Ŗą„‹ą¤øą„ą¤Ÿ ą¤•ą„‹ हटा दिया गया ą¤¹ą„ˆą„¤ą„¤" @@ -4071,7 +4203,11 @@ msgstr "" msgid "This warning is only available for posts with media attached." msgstr "यह ą¤šą„‡ą¤¤ą¤¾ą¤µą¤Øą„€ ą¤•ą„‡ą¤µą¤² ą¤®ą„€ą¤”ą¤æą¤Æą¤¾ ą¤øą¤‚ą¤²ą¤—ą„ą¤Ø ą¤Ŗą„‹ą¤øą„ą¤Ÿ ą¤•ą„‡ ą¤²ą¤æą¤ ą¤‰ą¤Ŗą¤²ą¤¬ą„ą¤§ ą¤¹ą„ˆą„¤" -#: src/view/com/util/forms/PostDropdownBtn.tsx:221 +#: src/components/dialogs/MutedWords.tsx:236 +msgid "This will delete {0} from your muted words. You can always add it back later." +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:237 msgid "This will hide this post from your feeds." msgstr "" @@ -4088,6 +4224,10 @@ msgstr "ą¤„ą„ą¤°ą„‡ą¤” ą¤®ą„‹ą¤”" msgid "Threads Preferences" msgstr "" +#: src/components/dialogs/MutedWords.tsx:95 +msgid "Toggle between muted word options." +msgstr "" + #: src/view/com/util/forms/DropdownButton.tsx:246 msgid "Toggle dropdown" msgstr "ą¤”ą„ą¤°ą„‰ą¤Ŗą¤”ą¤¾ą¤‰ą¤Ø ą¤Ÿą„‰ą¤—ą¤² ą¤•ą¤°ą„‡ą¤‚" @@ -4096,9 +4236,9 @@ msgstr "ą¤”ą„ą¤°ą„‰ą¤Ŗą¤”ą¤¾ą¤‰ą¤Ø ą¤Ÿą„‰ą¤—ą¤² ą¤•ą¤°ą„‡ą¤‚" msgid "Transformations" msgstr "ą¤Ŗą¤°ą¤æą¤µą¤°ą„ą¤¤ą¤Ø" -#: src/view/com/post-thread/PostThreadItem.tsx:679 -#: src/view/com/post-thread/PostThreadItem.tsx:681 -#: src/view/com/util/forms/PostDropdownBtn.tsx:154 +#: src/view/com/post-thread/PostThreadItem.tsx:685 +#: src/view/com/post-thread/PostThreadItem.tsx:687 +#: src/view/com/util/forms/PostDropdownBtn.tsx:156 msgid "Translate" msgstr "ą¤…ą¤Øą„ą¤µą¤¾ą¤¦" @@ -4163,15 +4303,24 @@ msgstr "" msgid "Unlike" msgstr "" +#: src/components/TagMenu/index.tsx:253 #: src/view/screens/ProfileList.tsx:597 msgid "Unmute" msgstr "" +#: src/components/TagMenu/index.web.tsx:90 +msgid "Unmute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:326 msgid "Unmute Account" msgstr "ą¤…ą¤Øą¤®ą„ą¤Æą„‚ą¤Ÿ खाता" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/TagMenu/index.tsx:210 +msgid "Unmute all {tag} posts" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Unmute thread" msgstr "ą¤„ą„ą¤°ą„‡ą¤” ą¤•ą„‹ ą¤…ą¤Øą¤®ą„ą¤Æą„‚ą¤Ÿ ą¤•ą¤°ą„‡ą¤‚" @@ -4372,6 +4521,10 @@ msgstr "" #~ msgid "We recommend \"For You\" by Skygaze:" #~ msgstr "" +#: src/components/dialogs/MutedWords.tsx:161 +msgid "We recommend avoiding common words that appear in many posts, since it can result in no posts being shown." +msgstr "" + #: src/screens/Onboarding/StepAlgoFeeds/index.tsx:124 msgid "We recommend our \"Discover\" feed:" msgstr "" @@ -4400,7 +4553,11 @@ msgstr "हम ą¤†ą¤Ŗą¤•ą„‡ ą¤¹ą¤®ą¤¾ą¤°ą„€ ą¤øą„‡ą¤µą¤¾ ą¤®ą„‡ą¤‚ शामि msgid "We're sorry, but we were unable to resolve this list. If this persists, please contact the list creator, @{handleOrDid}." msgstr "" -#: src/view/screens/Search/Search.tsx:253 +#: src/components/dialogs/MutedWords.tsx:182 +msgid "We're sorry, but we weren't able to load your muted words at this time. Please try again." +msgstr "" + +#: src/view/screens/Search/Search.tsx:254 msgid "We're sorry, but your search could not be completed. Please try again in a few minutes." msgstr "" @@ -4421,7 +4578,7 @@ msgid "What is the issue with this {collectionName}?" msgstr "इस {collectionName} ą¤•ą„‡ साऄ ą¤•ą„ą¤Æą¤¾ ą¤®ą„ą¤¦ą„ą¤¦ą¤¾ ą¤¹ą„ˆ?" #: src/view/com/auth/SplashScreen.tsx:59 -#: src/view/com/composer/Composer.tsx:279 +#: src/view/com/composer/Composer.tsx:286 msgid "What's up?" msgstr "" @@ -4442,11 +4599,11 @@ msgstr "" msgid "Wide" msgstr "ą¤šą„Œą¤”ą¤¼ą¤¾" -#: src/view/com/composer/Composer.tsx:415 +#: src/view/com/composer/Composer.tsx:422 msgid "Write post" msgstr "ą¤Ŗą„‹ą¤øą„ą¤Ÿ ą¤²ą¤æą¤–ą„‹" -#: src/view/com/composer/Composer.tsx:278 +#: src/view/com/composer/Composer.tsx:285 #: src/view/com/composer/Prompt.tsx:33 msgid "Write your reply" msgstr "अपना जवाब ą¤¦ą„‡ą¤‚" @@ -4511,7 +4668,7 @@ msgstr "" msgid "You don't have any saved feeds." msgstr "ą¤†ą¤Ŗą¤•ą„‡ पास ą¤•ą„‹ą¤ˆ ą¤øą¤¹ą„‡ą¤œą„€ ą¤—ą¤ˆ ą¤«ą¤¼ą„€ą¤” ą¤Øą¤¹ą„€ą¤‚ ą¤¹ą„ˆ." -#: src/view/com/post-thread/PostThread.tsx:464 +#: src/view/com/post-thread/PostThread.tsx:465 msgid "You have blocked the author or you have been blocked by the author." msgstr "ą¤†ą¤Ŗą¤Øą„‡ ą¤²ą„‡ą¤–ą¤• ą¤•ą„‹ ą¤…ą¤µą¤°ą„ą¤¦ą„ą¤§ किया ą¤¹ą„ˆ या ą¤†ą¤Ŗą¤Øą„‡ ą¤²ą„‡ą¤–ą¤• ą¤¦ą„ą¤µą¤¾ą¤°ą¤¾ ą¤…ą¤µą¤°ą„ą¤¦ą„ą¤§ किया ą¤¹ą„ˆą„¤ą„¤" @@ -4551,6 +4708,10 @@ msgstr "ą¤†ą¤Ŗą¤Øą„‡ ą¤…ą¤­ą„€ तक ą¤•ą„‹ą¤ˆ ऐप ą¤Ŗą¤¾ą¤øą¤µą¤°ą„ą¤” न msgid "You have not muted any accounts yet. To mute an account, go to their profile and selected \"Mute account\" from the menu on their account." msgstr "ą¤†ą¤Ŗą¤Øą„‡ ą¤…ą¤­ą„€ तक ą¤•ą„‹ą¤ˆ खाता ą¤®ą„ą¤Æą„‚ą¤Ÿ ą¤Øą¤¹ą„€ą¤‚ किया ą¤¹ą„ˆ. ą¤•ą¤æą¤øą„€ ą¤–ą¤¾ą¤¤ą„‡ ą¤•ą„‹ ą¤®ą„ą¤Æą„‚ą¤Ÿ ą¤•ą¤°ą¤Øą„‡ ą¤•ą„‡ ą¤²ą¤æą¤, ą¤‰ą¤Øą¤•ą„€ ą¤Ŗą„ą¤°ą„‹ą¤«ą¤¼ą¤¾ą¤‡ą¤² पर ą¤œą¤¾ą¤ą¤‚ और ą¤‰ą¤Øą¤•ą„‡ ą¤–ą¤¾ą¤¤ą„‡ ą¤•ą„‡ ą¤®ą„‡ą¤Øą„‚ ą¤øą„‡ \"खाता ą¤®ą„ą¤Æą„‚ą¤Ÿ ą¤•ą¤°ą„‡ą¤‚\" ą¤šą„ą¤Øą„‡ą¤‚ą„¤" +#: src/components/dialogs/MutedWords.tsx:202 +msgid "You haven't muted any words or tags yet" +msgstr "" + #: src/view/com/modals/ContentFilteringSettings.tsx:175 msgid "You must be 18 or older to enable adult content." msgstr "" @@ -4559,11 +4720,11 @@ msgstr "" msgid "You must be 18 years or older to enable adult content" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:127 +#: src/view/com/util/forms/PostDropdownBtn.tsx:129 msgid "You will no longer receive notifications for this thread" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:130 +#: src/view/com/util/forms/PostDropdownBtn.tsx:132 msgid "You will now receive notifications for this thread" msgstr "" @@ -4649,11 +4810,15 @@ msgstr "" #~ msgid "Your invite codes are hidden when logged in using an App Password" #~ msgstr "" +#: src/components/dialogs/MutedWords.tsx:173 +msgid "Your muted words" +msgstr "" + #: src/view/com/modals/ChangePassword.tsx:155 msgid "Your password has been changed successfully!" msgstr "" -#: src/view/com/composer/Composer.tsx:267 +#: src/view/com/composer/Composer.tsx:274 msgid "Your post has been published" msgstr "" @@ -4668,7 +4833,7 @@ msgstr "ą¤†ą¤Ŗą¤•ą„€ ą¤Ŗą„‹ą¤øą„ą¤Ÿ, पसंद और ą¤¬ą„ą¤²ą„‰ą¤• सा msgid "Your profile" msgstr "ą¤†ą¤Ŗą¤•ą„€ ą¤Ŗą„ą¤°ą„‹ą¤«ą¤¼ą¤¾ą¤‡ą¤²" -#: src/view/com/composer/Composer.tsx:266 +#: src/view/com/composer/Composer.tsx:273 msgid "Your reply has been published" msgstr "" diff --git a/src/locale/locales/id/messages.po b/src/locale/locales/id/messages.po index 5697638a0f..4135b9f19d 100644 --- a/src/locale/locales/id/messages.po +++ b/src/locale/locales/id/messages.po @@ -92,7 +92,7 @@ msgid "A new version of the app is available. Please update to continue using th msgstr "Versi baru dari aplikasi ini telah tersedia. Harap perbarui untuk terus menggunakan aplikasi." #: src/view/com/util/ViewHeader.tsx:83 -#: src/view/screens/Search/Search.tsx:624 +#: src/view/screens/Search/Search.tsx:647 msgid "Access navigation links and settings" msgstr "Akses tautan navigasi dan pengaturan" @@ -143,6 +143,7 @@ msgstr "Akun batal diblokir" msgid "Account unmuted" msgstr "Akun batal dibisukan" +#: src/components/dialogs/MutedWords.tsx:147 #: src/view/com/auth/onboarding/RecommendedFeedsItem.tsx:150 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -184,14 +185,22 @@ msgstr "Tambahkan detail" msgid "Add details to report" msgstr "Tambahkan detail ke laporan" -#: src/view/com/composer/Composer.tsx:446 +#: src/view/com/composer/Composer.tsx:453 msgid "Add link card" msgstr "Tambahkan kartu tautan" -#: src/view/com/composer/Composer.tsx:451 +#: src/view/com/composer/Composer.tsx:458 msgid "Add link card:" msgstr "Tambahkan kartu tautan:" +#: src/components/dialogs/MutedWords.tsx:140 +msgid "Add mute word for configured settings" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:74 +msgid "Add muted words and tags" +msgstr "" + #: src/view/com/modals/ChangeHandle.tsx:417 msgid "Add the following DNS record to your domain:" msgstr "Tambahkan DNS record berikut ke domain Anda:" @@ -315,7 +324,7 @@ msgstr "Pengaturan kata sandi aplikasi" msgid "App Passwords" msgstr "Kata sandi Aplikasi" -#: src/view/com/util/forms/PostDropdownBtn.tsx:279 +#: src/view/com/util/forms/PostDropdownBtn.tsx:295 msgid "Appeal content warning" msgstr "Ajukan banding peringatan konten" @@ -342,15 +351,16 @@ msgstr "Tampilan" msgid "Are you sure you want to delete the app password \"{name}\"?" msgstr "Anda yakin untuk menghapus kata sandi aplikasi \"{name}\"?" -#: src/view/com/composer/Composer.tsx:143 +#: src/view/com/composer/Composer.tsx:150 msgid "Are you sure you'd like to discard this draft?" msgstr "Anda yakin untuk membuang draf ini?" +#: src/components/dialogs/MutedWords.tsx:233 #: src/view/screens/ProfileList.tsx:365 msgid "Are you sure?" msgstr "Anda yakin?" -#: src/view/com/util/forms/PostDropdownBtn.tsx:262 +#: src/view/com/util/forms/PostDropdownBtn.tsx:278 msgid "Are you sure? This cannot be undone." msgstr "Anda yakin? Ini tidak dapat dibatalkan." @@ -372,15 +382,15 @@ msgstr "Ketelanjangan artistik atau non-erotis." #: src/view/com/auth/login/LoginForm.tsx:259 #: src/view/com/auth/login/SetNewPasswordForm.tsx:179 #: src/view/com/modals/report/InputIssueDetails.tsx:46 -#: src/view/com/post-thread/PostThread.tsx:471 -#: src/view/com/post-thread/PostThread.tsx:521 -#: src/view/com/post-thread/PostThread.tsx:529 +#: src/view/com/post-thread/PostThread.tsx:472 +#: src/view/com/post-thread/PostThread.tsx:522 +#: src/view/com/post-thread/PostThread.tsx:530 #: src/view/com/profile/ProfileHeader.tsx:649 #: src/view/com/util/ViewHeader.tsx:81 msgid "Back" msgstr "Kembali" -#: src/view/com/post-thread/PostThread.tsx:479 +#: src/view/com/post-thread/PostThread.tsx:480 msgctxt "action" msgid "Back" msgstr "Kembali" @@ -428,7 +438,7 @@ msgstr "Blokir Daftar ini" msgid "Blocked" msgstr "Diblokir" -#: src/view/screens/Moderation.tsx:123 +#: src/view/screens/Moderation.tsx:142 msgid "Blocked accounts" msgstr "Akun yang diblokir" @@ -487,7 +497,7 @@ msgstr "Bluesky bersifat publik." msgid "Bluesky uses invites to build a healthier community. If you don't know anybody with an invite, you can sign up for the waitlist and we'll send one soon." msgstr "Bluesky menggunakan undangan untuk membangun komunitas yang sehat. Jika Anda tidak tahu orang lain yang memiliki undangan, Anda bisa mendaftar di daftar tunggu dan kami akan segera mengirimkan undangannya." -#: src/view/screens/Moderation.tsx:226 +#: src/view/screens/Moderation.tsx:245 msgid "Bluesky will not show your profile and posts to logged-out users. Other apps may not honor this request. This does not make your account private." msgstr "Bluesky tidak akan menampilkan profil dan postingan Anda ke pengguna yang tidak login. Aplikasi lain mungkin tidak menghormati permintaan ini. Ini tidak membuat akun Anda menjadi privat." @@ -539,8 +549,8 @@ msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must msgstr "Hanya dapat terdiri dari huruf, angka, spasi, tanda hubung dan garis bawah. Minimal 4 karakter, namun tidak boleh lebih dari 32 karakter." #: src/components/Prompt.tsx:91 -#: src/view/com/composer/Composer.tsx:300 -#: src/view/com/composer/Composer.tsx:305 +#: src/view/com/composer/Composer.tsx:307 +#: src/view/com/composer/Composer.tsx:312 #: src/view/com/modals/ChangeEmail.tsx:218 #: src/view/com/modals/ChangeEmail.tsx:220 #: src/view/com/modals/ChangePassword.tsx:265 @@ -554,7 +564,7 @@ msgstr "Hanya dapat terdiri dari huruf, angka, spasi, tanda hubung dan garis baw #: src/view/com/modals/VerifyEmail.tsx:247 #: src/view/com/modals/VerifyEmail.tsx:253 #: src/view/com/modals/Waitlist.tsx:142 -#: src/view/screens/Search/Search.tsx:693 +#: src/view/screens/Search/Search.tsx:716 #: src/view/shell/desktop/Search.tsx:238 msgid "Cancel" msgstr "Batal" @@ -711,7 +721,7 @@ msgid "Clear all storage data (restart after this)" msgstr "Hapus semua data penyimpanan (mulai ulang setelah ini)" #: src/view/com/util/forms/SearchInput.tsx:88 -#: src/view/screens/Search/Search.tsx:674 +#: src/view/screens/Search/Search.tsx:697 msgid "Clear search query" msgstr "Hapus kueri pencarian" @@ -719,6 +729,11 @@ msgstr "Hapus kueri pencarian" msgid "click here" msgstr "klik di sini" +#: src/components/RichText.tsx:189 +#: src/components/TagMenu/index.web.tsx:125 +msgid "Click here to open tag menu for {tag}" +msgstr "" + #: src/screens/Onboarding/index.tsx:35 msgid "Climate" msgstr "" @@ -749,11 +764,15 @@ msgstr "Tutup gambar" msgid "Close image viewer" msgstr "Tutup penampil gambar" -#: src/view/shell/index.web.tsx:49 +#: src/view/shell/index.web.tsx:51 msgid "Close navigation footer" msgstr "Tutup footer navigasi" -#: src/view/shell/index.web.tsx:50 +#: src/components/TagMenu/index.tsx:266 +msgid "Close this dialog" +msgstr "" + +#: src/view/shell/index.web.tsx:52 msgid "Closes bottom navigation bar" msgstr "Menutup bilah navigasi bawah" @@ -761,7 +780,7 @@ msgstr "Menutup bilah navigasi bawah" msgid "Closes password update alert" msgstr "Menutup peringatan pembaruan kata sandi" -#: src/view/com/composer/Composer.tsx:302 +#: src/view/com/composer/Composer.tsx:309 msgid "Closes post composer and discards post draft" msgstr "Menutup penyusun postingan dan membuang draf" @@ -794,7 +813,7 @@ msgstr "" msgid "Complete the challenge" msgstr "" -#: src/view/com/composer/Composer.tsx:417 +#: src/view/com/composer/Composer.tsx:424 msgid "Compose posts up to {MAX_GRAPHEME_LENGTH} characters in length" msgstr "Buat postingan dengan panjang hingga {MAX_GRAPHEME_LENGTH} karakter" @@ -858,7 +877,7 @@ msgstr "Menghubungkan..." msgid "Contact support" msgstr "" -#: src/view/screens/Moderation.tsx:81 +#: src/view/screens/Moderation.tsx:83 msgid "Content filtering" msgstr "Penyaring Konten" @@ -924,7 +943,7 @@ msgstr "Menyalin versi build ke papan klip" #: src/view/com/modals/AddAppPasswords.tsx:76 #: src/view/com/modals/InviteCodes.tsx:152 -#: src/view/com/util/forms/PostDropdownBtn.tsx:141 +#: src/view/com/util/forms/PostDropdownBtn.tsx:143 msgid "Copied to clipboard" msgstr "Disalin ke papan klip" @@ -940,7 +959,7 @@ msgstr "Salin" msgid "Copy link to list" msgstr "Salin tautan ke daftar" -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 msgid "Copy link to post" msgstr "Salin tautan ke postingan" @@ -948,7 +967,7 @@ msgstr "Salin tautan ke postingan" msgid "Copy link to profile" msgstr "Salin tautan ke profil" -#: src/view/com/util/forms/PostDropdownBtn.tsx:168 +#: src/view/com/util/forms/PostDropdownBtn.tsx:170 msgid "Copy post text" msgstr "Salin teks postingan" @@ -1004,7 +1023,7 @@ msgstr "Dibuat oleh <0/>" msgid "Created by you" msgstr "Dibuat oleh Anda" -#: src/view/com/composer/Composer.tsx:448 +#: src/view/com/composer/Composer.tsx:455 msgid "Creates a card with a thumbnail. The card links to {url}" msgstr "Buat kartu dengan gambar kecil. Tautan kartu ke {url}" @@ -1085,11 +1104,11 @@ msgstr "Hapus akun saya" msgid "Delete My Account…" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:257 +#: src/view/com/util/forms/PostDropdownBtn.tsx:273 msgid "Delete post" msgstr "Hapus postingan" -#: src/view/com/util/forms/PostDropdownBtn.tsx:261 +#: src/view/com/util/forms/PostDropdownBtn.tsx:277 msgid "Delete this post?" msgstr "Hapus postingan ini?" @@ -1116,7 +1135,7 @@ msgstr "Deskripsi" #~ msgid "Developer Tools" #~ msgstr "Alat Pengembang" -#: src/view/com/composer/Composer.tsx:211 +#: src/view/com/composer/Composer.tsx:218 msgid "Did you want to say anything?" msgstr "Apakah Anda ingin mengatakan sesuatu?" @@ -1124,15 +1143,15 @@ msgstr "Apakah Anda ingin mengatakan sesuatu?" msgid "Dim" msgstr "" -#: src/view/com/composer/Composer.tsx:144 +#: src/view/com/composer/Composer.tsx:151 msgid "Discard" msgstr "Buang" -#: src/view/com/composer/Composer.tsx:138 +#: src/view/com/composer/Composer.tsx:145 msgid "Discard draft" msgstr "Buang draf" -#: src/view/screens/Moderation.tsx:207 +#: src/view/screens/Moderation.tsx:226 msgid "Discourage apps from showing my account to logged-out users" msgstr "Cegah aplikasi untuk menampilkan akun saya ke pengguna yang tidak login" @@ -1211,7 +1230,7 @@ msgstr "" msgid "Download CAR file" msgstr "" -#: src/view/com/composer/text-input/TextInput.web.tsx:247 +#: src/view/com/composer/text-input/TextInput.web.tsx:249 msgid "Drop to add images" msgstr "" @@ -1283,6 +1302,7 @@ msgstr "Edit profil" msgid "Edit Profile" msgstr "Edit Profil" +#: src/view/com/home/HomeHeaderLayout.web.tsx:59 #: src/view/screens/Feeds.tsx:355 msgid "Edit Saved Feeds" msgstr "Edit Feed Tersimpan" @@ -1365,6 +1385,11 @@ msgstr "Akhir feed" msgid "Enter a name for this App Password" msgstr "Masukkan nama untuk Sandi Aplikasi ini" +#: src/components/dialogs/MutedWords.tsx:87 +#: src/components/dialogs/MutedWords.tsx:88 +msgid "Enter a word or tag" +msgstr "" + #: src/view/com/modals/VerifyEmail.tsx:105 msgid "Enter Confirmation Code" msgstr "Masukkan Kode Konfirmasi" @@ -1418,7 +1443,7 @@ msgstr "Masukkan nama pengguna dan kata sandi Anda" msgid "Error receiving captcha response." msgstr "" -#: src/view/screens/Search/Search.tsx:109 +#: src/view/screens/Search/Search.tsx:110 msgid "Error:" msgstr "Eror:" @@ -1489,7 +1514,7 @@ msgstr "Gagal membuat kata sandi aplikasi." msgid "Failed to create the list. Check your internet connection and try again." msgstr "Gagal membuat daftar. Periksa koneksi internet Anda dan coba lagi." -#: src/view/com/util/forms/PostDropdownBtn.tsx:108 +#: src/view/com/util/forms/PostDropdownBtn.tsx:110 msgid "Failed to delete post, please try again" msgstr "Gagal menghapus postingan, silakan coba lagi" @@ -1511,8 +1536,8 @@ msgid "Feed offline" msgstr "Feed offline" #: src/view/com/feeds/FeedPage.tsx:143 -msgid "Feed Preferences" -msgstr "Preferensi Feed" +#~ msgid "Feed Preferences" +#~ msgstr "Preferensi Feed" #: src/view/shell/desktop/RightNav.tsx:61 #: src/view/shell/Drawer.tsx:311 @@ -1560,11 +1585,11 @@ msgstr "" msgid "Find accounts to follow" msgstr "Temukan akun untuk diikuti" -#: src/view/screens/Search/Search.tsx:439 +#: src/view/screens/Search/Search.tsx:440 msgid "Find users on Bluesky" msgstr "Temukan pengguna di Bluesky" -#: src/view/screens/Search/Search.tsx:437 +#: src/view/screens/Search/Search.tsx:438 msgid "Find users with the search tool on the right" msgstr "Temukan pengguna dengan alat pencarian di sebelah kanan" @@ -1668,6 +1693,7 @@ msgid "Following {0}" msgstr "Mengikuti {0}" #: src/Navigation.tsx:248 +#: src/view/com/home/HomeHeaderLayout.web.tsx:45 #: src/view/com/home/HomeHeaderLayoutMobile.tsx:83 #: src/view/screens/PreferencesFollowingFeed.tsx:104 #: src/view/screens/Settings/index.tsx:543 @@ -1707,7 +1733,7 @@ msgstr "Lupa kata sandi" msgid "Forgot Password" msgstr "Lupa Kata Sandi" -#: src/view/com/posts/FeedItem.tsx:187 +#: src/view/com/posts/FeedItem.tsx:189 msgctxt "from-feed" msgid "From <0/>" msgstr "Dari <0/>" @@ -1740,7 +1766,7 @@ msgstr "Kembali" msgid "Go back to previous step" msgstr "" -#: src/view/screens/Search/Search.tsx:724 +#: src/view/screens/Search/Search.tsx:747 #: src/view/shell/desktop/Search.tsx:262 msgid "Go to @{queryMaybeHandle}" msgstr "" @@ -1757,6 +1783,10 @@ msgstr "Berikutnya" msgid "Handle" msgstr "Handle" +#: src/components/RichText.tsx:188 +msgid "Hashtag: {tag}" +msgstr "" + #: src/view/com/auth/create/CreateAccount.tsx:208 msgid "Having trouble?" msgstr "" @@ -1799,7 +1829,7 @@ msgctxt "action" msgid "Hide" msgstr "Sembunyikan" -#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +#: src/view/com/util/forms/PostDropdownBtn.tsx:232 msgid "Hide post" msgstr "Sembunyikan postingan" @@ -1808,7 +1838,7 @@ msgstr "Sembunyikan postingan" msgid "Hide the content" msgstr "Sembunyikan konten" -#: src/view/com/util/forms/PostDropdownBtn.tsx:220 +#: src/view/com/util/forms/PostDropdownBtn.tsx:236 msgid "Hide this post?" msgstr "Sembunyikan postingan ini?" @@ -1969,7 +1999,7 @@ msgstr "Masukkan kata sandi Anda" msgid "Input your user handle" msgstr "Masukkan handle pengguna Anda" -#: src/view/com/post-thread/PostThreadItem.tsx:224 +#: src/view/com/post-thread/PostThreadItem.tsx:226 msgid "Invalid or unsupported post record" msgstr "Catatan posting tidak valid atau tidak didukung" @@ -2071,7 +2101,7 @@ msgstr "Pelajari Lebih Lanjut" msgid "Learn more about this warning" msgstr "Pelajari lebih lanjut tentang peringatan ini" -#: src/view/screens/Moderation.tsx:243 +#: src/view/screens/Moderation.tsx:262 msgid "Learn more about what is public on Bluesky." msgstr "Pelajari lebih lanjut tentang apa yang publik di Bluesky." @@ -2155,7 +2185,7 @@ msgstr "menyukai postingan Anda" msgid "Likes" msgstr "Suka" -#: src/view/com/post-thread/PostThreadItem.tsx:181 +#: src/view/com/post-thread/PostThreadItem.tsx:183 msgid "Likes on this post" msgstr "Suka pada postingan ini" @@ -2212,7 +2242,7 @@ msgstr "Muat postingan lainnya" msgid "Load new notifications" msgstr "Muat notifikasi baru" -#: src/view/com/feeds/FeedPage.tsx:181 +#: src/view/com/feeds/FeedPage.tsx:115 #: src/view/screens/Profile.tsx:440 #: src/view/screens/ProfileFeed.tsx:495 #: src/view/screens/ProfileList.tsx:681 @@ -2238,7 +2268,7 @@ msgstr "Catatan" msgid "Log out" msgstr "" -#: src/view/screens/Moderation.tsx:136 +#: src/view/screens/Moderation.tsx:155 msgid "Logged-out visibility" msgstr "Visibilitas pengguna yang tidak login" @@ -2253,6 +2283,10 @@ msgstr "Masuk ke akun yang tidak ada di daftar" msgid "Make sure this is where you intend to go!" msgstr "Pastikan ini adalah website yang Anda tuju!" +#: src/components/dialogs/MutedWords.tsx:71 +msgid "Manage your muted words and tags" +msgstr "" + #: src/view/com/auth/create/Step2.tsx:118 msgid "May not be longer than 253 characters" msgstr "" @@ -2274,7 +2308,7 @@ msgid "Mentioned users" msgstr "Pengguna yang disebutkan" #: src/view/com/util/ViewHeader.tsx:81 -#: src/view/screens/Search/Search.tsx:623 +#: src/view/screens/Search/Search.tsx:646 msgid "Menu" msgstr "Menu" @@ -2286,7 +2320,7 @@ msgid "Message from server: {0}" msgstr "Pesan dari server: {0}" #: src/Navigation.tsx:115 -#: src/view/screens/Moderation.tsx:64 +#: src/view/screens/Moderation.tsx:66 #: src/view/screens/Settings/index.tsx:625 #: src/view/shell/desktop/LeftNav.tsx:397 #: src/view/shell/Drawer.tsx:511 @@ -2317,7 +2351,7 @@ msgstr "Daftar moderasi dibuat" msgid "Moderation list updated" msgstr "Daftar moderasi diperbarui" -#: src/view/screens/Moderation.tsx:95 +#: src/view/screens/Moderation.tsx:114 msgid "Moderation lists" msgstr "Daftar moderasi" @@ -2344,7 +2378,7 @@ msgstr "Feed lainnya" msgid "More options" msgstr "Pilihan lainnya" -#: src/view/com/util/forms/PostDropdownBtn.tsx:299 +#: src/view/com/util/forms/PostDropdownBtn.tsx:315 msgid "More post options" msgstr "Opsi posting lainnya" @@ -2356,6 +2390,14 @@ msgstr "Balasan yang paling disukai lebih dulu" msgid "Must be at least 3 characters" msgstr "" +#: src/components/TagMenu/index.tsx:253 +msgid "Mute" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:91 +msgid "Mute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:327 msgid "Mute Account" msgstr "Bisukan Akun" @@ -2364,6 +2406,18 @@ msgstr "Bisukan Akun" msgid "Mute accounts" msgstr "Bisukan akun" +#: src/components/TagMenu/index.tsx:211 +msgid "Mute all {tag} posts" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:131 +msgid "Mute in tags only" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:116 +msgid "Mute in text & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:491 msgid "Mute list" msgstr "Daftar akun yang dibisukan" @@ -2376,15 +2430,27 @@ msgstr "Bisukan akun ini?" msgid "Mute this List" msgstr "Bisukan Daftar ini" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/dialogs/MutedWords.tsx:109 +msgid "Mute this word in post text and tags" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:124 +msgid "Mute this word in tags only" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Mute thread" msgstr "Bisukan utasan" +#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +msgid "Mute words & tags" +msgstr "" + #: src/view/com/lists/ListCard.tsx:102 msgid "Muted" msgstr "Dibisukan" -#: src/view/screens/Moderation.tsx:109 +#: src/view/screens/Moderation.tsx:128 msgid "Muted accounts" msgstr "Akun yang dibisukan" @@ -2397,6 +2463,10 @@ msgstr "Akun yang Dibisukan" msgid "Muted accounts have their posts removed from your feed and from your notifications. Mutes are completely private." msgstr "Postingan dari akun yang dibisukan akan dihilangkan dari feed dan notifikasi Anda. Pembisuan ini bersifat privat." +#: src/view/screens/Moderation.tsx:100 +msgid "Muted words & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:277 msgid "Muting is private. Muted accounts can interact with you, but you will not see their posts or receive notifications from them." msgstr "Pembisuan akun bersifat privat. Akun yang dibisukan tetap dapat berinteraksi dengan Anda, namun Anda tidak akan melihat postingan atau notifikasi dari mereka." @@ -2460,6 +2530,10 @@ msgstr "Tidak akan lagi kehilangan akses ke data dan pengikut Anda." msgid "Never lose access to your followers or data." msgstr "" +#: src/components/dialogs/MutedWords.tsx:244 +msgid "Nevermind" +msgstr "" + #: src/view/screens/Lists.tsx:76 msgctxt "action" msgid "New" @@ -2481,7 +2555,7 @@ msgstr "Kata sandi baru" msgid "New Password" msgstr "" -#: src/view/com/feeds/FeedPage.tsx:192 +#: src/view/com/feeds/FeedPage.tsx:126 msgctxt "action" msgid "New post" msgstr "Postingan baru" @@ -2569,8 +2643,8 @@ msgid "No results found for \"{query}\"" msgstr "Tidak ada hasil ditemukan untuk \"{query}\"" #: src/view/com/modals/ListAddRemoveUsers.tsx:127 -#: src/view/screens/Search/Search.tsx:280 -#: src/view/screens/Search/Search.tsx:308 +#: src/view/screens/Search/Search.tsx:281 +#: src/view/screens/Search/Search.tsx:309 msgid "No results found for {query}" msgstr "Tidak ada hasil ditemukan untuk {query}" @@ -2596,7 +2670,7 @@ msgstr "Tidak ditemukan" msgid "Not right now" msgstr "Jangan sekarang" -#: src/view/screens/Moderation.tsx:233 +#: src/view/screens/Moderation.tsx:252 msgid "Note: Bluesky is an open and public network. This setting only limits the visibility of your content on the Bluesky app and website, and other apps may not respect this setting. Your content may still be shown to logged-out users by other apps and websites." msgstr "Catatan: Bluesky merupakan jaringan terbuka dan publik. Pengaturan ini hanya akan membatasi visibilitas konten Anda pada aplikasi dan website Bluesky, dan aplikasi lain mungkin tidak mengindahkan pengaturan ini. Konten Anda mungkin tetap ditampilkan kepada pengguna yang tidak login oleh aplikasi dan website lain." @@ -2634,7 +2708,7 @@ msgstr "Balasan terlama terlebih dahulu" msgid "Onboarding reset" msgstr "Atur ulang orientasi" -#: src/view/com/composer/Composer.tsx:375 +#: src/view/com/composer/Composer.tsx:382 msgid "One or more images is missing alt text." msgstr "Satu atau lebih gambar belum ada teks alt." @@ -2651,8 +2725,12 @@ msgstr "Uups!" msgid "Open" msgstr "" -#: src/view/com/composer/Composer.tsx:470 -#: src/view/com/composer/Composer.tsx:471 +#: src/view/screens/Moderation.tsx:75 +msgid "Open content filtering settings" +msgstr "" + +#: src/view/com/composer/Composer.tsx:477 +#: src/view/com/composer/Composer.tsx:478 msgid "Open emoji picker" msgstr "Buka pemilih emoji" @@ -2660,6 +2738,10 @@ msgstr "Buka pemilih emoji" msgid "Open links with in-app browser" msgstr "Buka tautan dengan browser dalam aplikasi" +#: src/view/screens/Moderation.tsx:92 +msgid "Open muted words settings" +msgstr "" + #: src/view/com/home/HomeHeaderLayoutMobile.tsx:49 msgid "Open navigation" msgstr "Buka navigasi" @@ -2736,6 +2818,7 @@ msgstr "Buka pengaturan moderasi" msgid "Opens password reset form" msgstr "Membuka formulir pengaturan ulang kata sandi" +#: src/view/com/home/HomeHeaderLayout.web.tsx:60 #: src/view/screens/Feeds.tsx:356 msgid "Opens screen to edit Saved Feeds" msgstr "Membuka layar untuk mengedit Umpan Tersimpan" @@ -2918,7 +3001,7 @@ msgstr "Mohon beri tahu kami mengapa menurut Anda peringatan konten ini salah di msgid "Please Verify Your Email" msgstr "Mohon Verifikasi Email Anda" -#: src/view/com/composer/Composer.tsx:215 +#: src/view/com/composer/Composer.tsx:222 msgid "Please wait for your link card to finish loading" msgstr "Harap tunggu hingga kartu tautan Anda selesai dimuat" @@ -2930,8 +3013,8 @@ msgstr "" msgid "Porn" msgstr "Pornografi" -#: src/view/com/composer/Composer.tsx:350 -#: src/view/com/composer/Composer.tsx:358 +#: src/view/com/composer/Composer.tsx:357 +#: src/view/com/composer/Composer.tsx:365 msgctxt "action" msgid "Post" msgstr "Posting" @@ -2944,7 +3027,7 @@ msgstr "Posting" #~ msgid "Post" #~ msgstr "Posting" -#: src/view/com/post-thread/PostThreadItem.tsx:173 +#: src/view/com/post-thread/PostThreadItem.tsx:175 msgid "Post by {0}" msgstr "Postingan oleh {0}" @@ -2954,11 +3037,11 @@ msgstr "Postingan oleh {0}" msgid "Post by @{0}" msgstr "Postingan oleh @{0}" -#: src/view/com/util/forms/PostDropdownBtn.tsx:88 +#: src/view/com/util/forms/PostDropdownBtn.tsx:90 msgid "Post deleted" msgstr "Postingan dihapus" -#: src/view/com/post-thread/PostThread.tsx:461 +#: src/view/com/post-thread/PostThread.tsx:462 msgid "Post hidden" msgstr "Postingan disembunyikan" @@ -2970,14 +3053,22 @@ msgstr "Bahasa postingan" msgid "Post Languages" msgstr "Bahasa Postingan" -#: src/view/com/post-thread/PostThread.tsx:513 +#: src/view/com/post-thread/PostThread.tsx:514 msgid "Post not found" msgstr "Postingan tidak ditemukan" +#: src/components/TagMenu/index.tsx:257 +msgid "posts" +msgstr "" + #: src/view/screens/Profile.tsx:180 msgid "Posts" msgstr "Postingan" +#: src/components/dialogs/MutedWords.tsx:77 +msgid "Posts can be muted based on their text, their tags, or both." +msgstr "" + #: src/view/com/posts/FeedErrorMessage.tsx:64 msgid "Posts hidden" msgstr "Postingan disembunyikan" @@ -3042,11 +3133,11 @@ msgstr "Daftar publik yang dapat dibagikan oleh pengguna untuk dibisukan atau di msgid "Public, shareable lists which can drive feeds." msgstr "Publik, daftar yang dapat dibagikan dan dapat berimbas ke feed." -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish post" msgstr "Publikasikan postingan" -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish reply" msgstr "Publikasikan balasan" @@ -3083,6 +3174,7 @@ msgstr "Feed Direkomendasikan" msgid "Recommended Users" msgstr "Pengguna Direkomendasikan" +#: src/components/dialogs/MutedWords.tsx:249 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/SelfLabel.tsx:83 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -3120,6 +3212,10 @@ msgstr "Hapus gambar" msgid "Remove image preview" msgstr "Hapus pratinjau gambar" +#: src/components/dialogs/MutedWords.tsx:294 +msgid "Remove mute word from your list" +msgstr "" + #: src/view/com/modals/Repost.tsx:47 msgid "Remove repost" msgstr "Hapus postingan ulang" @@ -3154,7 +3250,7 @@ msgstr "Balasan" msgid "Replies to this thread are disabled" msgstr "Balasan ke utas ini dinonaktifkan" -#: src/view/com/composer/Composer.tsx:348 +#: src/view/com/composer/Composer.tsx:355 msgctxt "action" msgid "Reply" msgstr "Balas" @@ -3164,7 +3260,7 @@ msgid "Reply Filters" msgstr "Penyaring Balasan" #: src/view/com/post/Post.tsx:167 -#: src/view/com/posts/FeedItem.tsx:285 +#: src/view/com/posts/FeedItem.tsx:287 msgctxt "description" msgid "Reply to <0/>" msgstr "Balas ke <0/>" @@ -3186,7 +3282,7 @@ msgid "Report List" msgstr "Laporkan Daftar" #: src/view/com/modals/report/SendReportButton.tsx:37 -#: src/view/com/util/forms/PostDropdownBtn.tsx:239 +#: src/view/com/util/forms/PostDropdownBtn.tsx:255 msgid "Report post" msgstr "Laporkan postingan" @@ -3215,7 +3311,7 @@ msgstr "Posting ulang atau kutip postingan" msgid "Reposted By" msgstr "" -#: src/view/com/posts/FeedItem.tsx:205 +#: src/view/com/posts/FeedItem.tsx:207 msgid "Reposted by {0}" msgstr "" @@ -3223,7 +3319,7 @@ msgstr "" #~ msgid "Reposted by {0})" #~ msgstr "Diposting ulang oleh {0})" -#: src/view/com/posts/FeedItem.tsx:222 +#: src/view/com/posts/FeedItem.tsx:224 msgid "Reposted by <0/>" msgstr "Diposting ulang oleh <0/>" @@ -3231,7 +3327,7 @@ msgstr "Diposting ulang oleh <0/>" msgid "reposted your post" msgstr "posting ulang posting Anda" -#: src/view/com/post-thread/PostThreadItem.tsx:186 +#: src/view/com/post-thread/PostThreadItem.tsx:188 msgid "Reposts of this post" msgstr "Posting ulang postingan ini" @@ -3382,9 +3478,9 @@ msgstr "Gulir ke atas" #: src/view/com/modals/ListAddRemoveUsers.tsx:75 #: src/view/com/util/forms/SearchInput.tsx:67 #: src/view/com/util/forms/SearchInput.tsx:79 -#: src/view/screens/Search/Search.tsx:418 -#: src/view/screens/Search/Search.tsx:645 -#: src/view/screens/Search/Search.tsx:663 +#: src/view/screens/Search/Search.tsx:419 +#: src/view/screens/Search/Search.tsx:668 +#: src/view/screens/Search/Search.tsx:686 #: src/view/shell/bottom-bar/BottomBar.tsx:159 #: src/view/shell/desktop/LeftNav.tsx:324 #: src/view/shell/desktop/Search.tsx:214 @@ -3394,11 +3490,19 @@ msgstr "Gulir ke atas" msgid "Search" msgstr "Cari" -#: src/view/screens/Search/Search.tsx:712 +#: src/view/screens/Search/Search.tsx:735 #: src/view/shell/desktop/Search.tsx:255 msgid "Search for \"{query}\"" msgstr "" +#: src/components/TagMenu/index.tsx:145 +msgid "Search for all posts by @{authorHandle} with tag {tag}" +msgstr "" + +#: src/components/TagMenu/index.tsx:90 +msgid "Search for all posts with tag {tag}" +msgstr "" + #: src/view/com/auth/LoggedOut.tsx:104 #: src/view/com/auth/LoggedOut.tsx:105 #: src/view/com/modals/ListAddRemoveUsers.tsx:70 @@ -3409,6 +3513,22 @@ msgstr "Cari pengguna" msgid "Security Step Required" msgstr "Langkah Keamanan Diperlukan" +#: src/components/TagMenu/index.web.tsx:50 +msgid "See {truncatedTag} posts" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:67 +msgid "See {truncatedTag} posts by user" +msgstr "" + +#: src/components/TagMenu/index.tsx:128 +msgid "See <0>{tag} posts" +msgstr "" + +#: src/components/TagMenu/index.tsx:189 +msgid "See <0>{tag} posts by this user" +msgstr "" + #: src/view/screens/SavedFeeds.tsx:163 msgid "See this guide" msgstr "Lihat panduan ini" @@ -3625,7 +3745,7 @@ msgid "Share" msgstr "Bagikan" #: src/view/com/profile/ProfileHeader.tsx:295 -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 #: src/view/screens/ProfileList.tsx:418 msgid "Share" msgstr "Bagikan" @@ -3658,9 +3778,9 @@ msgstr "Tampilkan embed dari {0}" msgid "Show follows similar to {0}" msgstr "Tampilkan berikut ini mirip dengan {0}" -#: src/view/com/post-thread/PostThreadItem.tsx:532 -#: src/view/com/post/Post.tsx:196 -#: src/view/com/posts/FeedItem.tsx:359 +#: src/view/com/post-thread/PostThreadItem.tsx:538 +#: src/view/com/post/Post.tsx:198 +#: src/view/com/posts/FeedItem.tsx:363 msgid "Show More" msgstr "Tampilkan Lebih Lanjut" @@ -3828,7 +3948,7 @@ msgstr "" msgid "Something went wrong. Check your email and try again." msgstr "Ada yang tidak beres. Periksa email Anda dan coba lagi." -#: src/App.native.tsx:61 +#: src/App.native.tsx:63 msgid "Sorry! Your session expired. Please log in again." msgstr "Maaf! Sesi Anda telah berakhir. Silakan masuk lagi." @@ -3890,7 +4010,7 @@ msgstr "" msgid "Subscribe to this list" msgstr "Langganan ke daftar ini" -#: src/view/screens/Search/Search.tsx:373 +#: src/view/screens/Search/Search.tsx:374 msgid "Suggested Follows" msgstr "Saran untuk Diikuti" @@ -3934,6 +4054,14 @@ msgstr "Sistem" msgid "System log" msgstr "Log sistem" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "tag" +msgstr "" + +#: src/components/TagMenu/index.tsx:74 +msgid "Tag menu: {tag}" +msgstr "" + #: src/view/com/modals/crop-image/CropImage.web.tsx:112 msgid "Tall" msgstr "Tinggi" @@ -3957,6 +4085,10 @@ msgstr "Ketentuan" msgid "Terms of Service" msgstr "Ketentuan Layanan" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "text" +msgstr "" + #: src/view/com/modals/AppealLabel.tsx:70 #: src/view/com/modals/report/InputIssueDetails.tsx:51 msgid "Text input field" @@ -3982,7 +4114,7 @@ msgstr "Kebijakan Hak Cipta telah dipindahkan ke <0/>" msgid "The following steps will help customize your Bluesky experience." msgstr "" -#: src/view/com/post-thread/PostThread.tsx:516 +#: src/view/com/post-thread/PostThread.tsx:517 msgid "The post may have been deleted." msgstr "Postingan mungkin telah dihapus." @@ -4162,7 +4294,7 @@ msgstr "Daftar ini kosong!" msgid "This name is already in use" msgstr "Nama ini sudah digunakan" -#: src/view/com/post-thread/PostThreadItem.tsx:123 +#: src/view/com/post-thread/PostThreadItem.tsx:125 msgid "This post has been deleted." msgstr "Postingan ini telah dihapus." @@ -4186,7 +4318,11 @@ msgstr "" msgid "This warning is only available for posts with media attached." msgstr "Peringatan ini hanya tersedia untuk postingan dengan lampiran media." -#: src/view/com/util/forms/PostDropdownBtn.tsx:221 +#: src/components/dialogs/MutedWords.tsx:236 +msgid "This will delete {0} from your muted words. You can always add it back later." +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:237 msgid "This will hide this post from your feeds." msgstr "Ini akan menyembunyikan postingan ini dari feed Anda." @@ -4203,6 +4339,10 @@ msgstr "Mode Utasan" msgid "Threads Preferences" msgstr "Preferensi Utas" +#: src/components/dialogs/MutedWords.tsx:95 +msgid "Toggle between muted word options." +msgstr "" + #: src/view/com/util/forms/DropdownButton.tsx:246 msgid "Toggle dropdown" msgstr "Beralih dropdown" @@ -4211,9 +4351,9 @@ msgstr "Beralih dropdown" msgid "Transformations" msgstr "Transformasi" -#: src/view/com/post-thread/PostThreadItem.tsx:679 -#: src/view/com/post-thread/PostThreadItem.tsx:681 -#: src/view/com/util/forms/PostDropdownBtn.tsx:154 +#: src/view/com/post-thread/PostThreadItem.tsx:685 +#: src/view/com/post-thread/PostThreadItem.tsx:687 +#: src/view/com/util/forms/PostDropdownBtn.tsx:156 msgid "Translate" msgstr "Terjemahkan" @@ -4281,15 +4421,24 @@ msgstr "Sayangnya, Anda tidak memenuhi syarat untuk membuat akun." msgid "Unlike" msgstr "Tidak suka" +#: src/components/TagMenu/index.tsx:253 #: src/view/screens/ProfileList.tsx:597 msgid "Unmute" msgstr "Bunyikan" +#: src/components/TagMenu/index.web.tsx:90 +msgid "Unmute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:326 msgid "Unmute Account" msgstr "Bunyikan Akun" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/TagMenu/index.tsx:210 +msgid "Unmute all {tag} posts" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Unmute thread" msgstr "Bunyikan utasan" @@ -4494,6 +4643,10 @@ msgstr "" #~ msgid "We recommend \"For You\" by Skygaze:" #~ msgstr "" +#: src/components/dialogs/MutedWords.tsx:161 +msgid "We recommend avoiding common words that appear in many posts, since it can result in no posts being shown." +msgstr "" + #: src/screens/Onboarding/StepAlgoFeeds/index.tsx:124 msgid "We recommend our \"Discover\" feed:" msgstr "" @@ -4522,7 +4675,11 @@ msgstr "Kami sangat senang Anda bergabung dengan kami!" msgid "We're sorry, but we were unable to resolve this list. If this persists, please contact the list creator, @{handleOrDid}." msgstr "Mohon maaf, kami tidak dapat menyelesaikan daftar ini. Jika hal ini terus berlanjut, silakan hubungi pembuat daftar, @{handleOrDid}." -#: src/view/screens/Search/Search.tsx:253 +#: src/components/dialogs/MutedWords.tsx:182 +msgid "We're sorry, but we weren't able to load your muted words at this time. Please try again." +msgstr "" + +#: src/view/screens/Search/Search.tsx:254 msgid "We're sorry, but your search could not be completed. Please try again in a few minutes." msgstr "Maaf, pencarian Anda tidak dapat dilakukan. Mohon coba lagi dalam beberapa menit." @@ -4546,7 +4703,7 @@ msgstr "Apa yang bermasalah dengan {collectionName}?" #~ msgstr "Apa selanjutnya?" #: src/view/com/auth/SplashScreen.tsx:59 -#: src/view/com/composer/Composer.tsx:279 +#: src/view/com/composer/Composer.tsx:286 msgid "What's up?" msgstr "Apa kabar?" @@ -4567,11 +4724,11 @@ msgstr "Siapa yang dapat membalas" msgid "Wide" msgstr "Lebar" -#: src/view/com/composer/Composer.tsx:415 +#: src/view/com/composer/Composer.tsx:422 msgid "Write post" msgstr "Tulis postingan" -#: src/view/com/composer/Composer.tsx:278 +#: src/view/com/composer/Composer.tsx:285 #: src/view/com/composer/Prompt.tsx:33 msgid "Write your reply" msgstr "Tulis balasan Anda" @@ -4640,7 +4797,7 @@ msgstr "Anda tidak memiliki feed yang disimpan!" msgid "You don't have any saved feeds." msgstr "Anda tidak memiliki feed yang disimpan." -#: src/view/com/post-thread/PostThread.tsx:464 +#: src/view/com/post-thread/PostThread.tsx:465 msgid "You have blocked the author or you have been blocked by the author." msgstr "Anda telah memblokir atau diblokir oleh penulis ini." @@ -4680,6 +4837,10 @@ msgstr "Anda belum membuat kata sandi aplikasi. Anda dapat membuatnya dengan men msgid "You have not muted any accounts yet. To mute an account, go to their profile and selected \"Mute account\" from the menu on their account." msgstr "Anda belum membisukan akun lain. Untuk membisukan akun, kunjungi profil mereka dan pilih \"Bisukan akun\" pada menu di akun mereka." +#: src/components/dialogs/MutedWords.tsx:202 +msgid "You haven't muted any words or tags yet" +msgstr "" + #: src/view/com/modals/ContentFilteringSettings.tsx:175 msgid "You must be 18 or older to enable adult content." msgstr "Anda harus berusia 18 tahun atau lebih untuk mengaktifkan konten dewasa." @@ -4688,11 +4849,11 @@ msgstr "Anda harus berusia 18 tahun atau lebih untuk mengaktifkan konten dewasa. msgid "You must be 18 years or older to enable adult content" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:127 +#: src/view/com/util/forms/PostDropdownBtn.tsx:129 msgid "You will no longer receive notifications for this thread" msgstr "Anda tidak akan lagi menerima notifikasi untuk utas ini" -#: src/view/com/util/forms/PostDropdownBtn.tsx:130 +#: src/view/com/util/forms/PostDropdownBtn.tsx:132 msgid "You will now receive notifications for this thread" msgstr "Anda sekarang akan menerima notifikasi untuk utas ini" @@ -4782,11 +4943,15 @@ msgstr "Handle lengkap Anda akan menjadi <0>@{0}" #~ msgid "Your invite codes are hidden when logged in using an App Password" #~ msgstr "Kode undangan Anda disembunyikan saat masuk menggunakan Kata Sandi Aplikasi" +#: src/components/dialogs/MutedWords.tsx:173 +msgid "Your muted words" +msgstr "" + #: src/view/com/modals/ChangePassword.tsx:155 msgid "Your password has been changed successfully!" msgstr "" -#: src/view/com/composer/Composer.tsx:267 +#: src/view/com/composer/Composer.tsx:274 msgid "Your post has been published" msgstr "Postingan Anda telah dipublikasikan" @@ -4801,7 +4966,7 @@ msgstr "Postingan, suka, dan blokir Anda bersifat publik. Bisukan bersifat priva msgid "Your profile" msgstr "Profil Anda" -#: src/view/com/composer/Composer.tsx:266 +#: src/view/com/composer/Composer.tsx:273 msgid "Your reply has been published" msgstr "Balasan Anda telah dipublikasikan" diff --git a/src/locale/locales/it/messages.po b/src/locale/locales/it/messages.po index bfa796a4fc..ac09dc1073 100644 --- a/src/locale/locales/it/messages.po +++ b/src/locale/locales/it/messages.po @@ -84,7 +84,7 @@ msgid "A new version of the app is available. Please update to continue using th msgstr "ƈ disponibile una nuova versione dell'app. Aggiorna per continuare a utilizzarla." #: src/view/com/util/ViewHeader.tsx:83 -#: src/view/screens/Search/Search.tsx:624 +#: src/view/screens/Search/Search.tsx:647 msgid "Access navigation links and settings" msgstr "Accedi alle impostazioni di navigazione" @@ -135,6 +135,7 @@ msgstr "Account sbloccato" msgid "Account unmuted" msgstr "Account non silenziato" +#: src/components/dialogs/MutedWords.tsx:147 #: src/view/com/auth/onboarding/RecommendedFeedsItem.tsx:150 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -176,14 +177,22 @@ msgstr "Aggiungi i dettagli" msgid "Add details to report" msgstr "Aggiungi dettagli da segnalare" -#: src/view/com/composer/Composer.tsx:446 +#: src/view/com/composer/Composer.tsx:453 msgid "Add link card" msgstr "Aggiungi la scheda collegata al link" -#: src/view/com/composer/Composer.tsx:451 +#: src/view/com/composer/Composer.tsx:458 msgid "Add link card:" msgstr "Aggiungi la scheda relazionata al link:" +#: src/components/dialogs/MutedWords.tsx:140 +msgid "Add mute word for configured settings" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:74 +msgid "Add muted words and tags" +msgstr "" + #: src/view/com/modals/ChangeHandle.tsx:417 msgid "Add the following DNS record to your domain:" msgstr "Aggiungi il seguente record DNS al tuo dominio:" @@ -303,7 +312,7 @@ msgstr "Impostazioni della password dell'app" msgid "App Passwords" msgstr "Passwords dell'App" -#: src/view/com/util/forms/PostDropdownBtn.tsx:279 +#: src/view/com/util/forms/PostDropdownBtn.tsx:295 msgid "Appeal content warning" msgstr "Ricorso contro l'avviso sui contenuti" @@ -330,15 +339,16 @@ msgstr "Aspetto" msgid "Are you sure you want to delete the app password \"{name}\"?" msgstr "Conferma di voler eliminare la password dell'app \"{name}\"?" -#: src/view/com/composer/Composer.tsx:143 +#: src/view/com/composer/Composer.tsx:150 msgid "Are you sure you'd like to discard this draft?" msgstr "Conferma di voler eliminare questa bozza?" +#: src/components/dialogs/MutedWords.tsx:233 #: src/view/screens/ProfileList.tsx:365 msgid "Are you sure?" msgstr "Confermi?" -#: src/view/com/util/forms/PostDropdownBtn.tsx:262 +#: src/view/com/util/forms/PostDropdownBtn.tsx:278 msgid "Are you sure? This cannot be undone." msgstr "Vuoi proseguire? Questa operazione non può essere annullata." @@ -360,15 +370,15 @@ msgstr "NuditĆ  artistica o non erotica." #: src/view/com/auth/login/LoginForm.tsx:259 #: src/view/com/auth/login/SetNewPasswordForm.tsx:179 #: src/view/com/modals/report/InputIssueDetails.tsx:46 -#: src/view/com/post-thread/PostThread.tsx:471 -#: src/view/com/post-thread/PostThread.tsx:521 -#: src/view/com/post-thread/PostThread.tsx:529 +#: src/view/com/post-thread/PostThread.tsx:472 +#: src/view/com/post-thread/PostThread.tsx:522 +#: src/view/com/post-thread/PostThread.tsx:530 #: src/view/com/profile/ProfileHeader.tsx:649 #: src/view/com/util/ViewHeader.tsx:81 msgid "Back" msgstr "Indietro" -#: src/view/com/post-thread/PostThread.tsx:479 +#: src/view/com/post-thread/PostThread.tsx:480 msgctxt "action" msgid "Back" msgstr "Indietro" @@ -416,7 +426,7 @@ msgstr "Blocca questa Lista" msgid "Blocked" msgstr "Bloccato" -#: src/view/screens/Moderation.tsx:123 +#: src/view/screens/Moderation.tsx:142 msgid "Blocked accounts" msgstr "Accounts bloccati" @@ -475,7 +485,7 @@ msgstr "Bluesky ĆØ pubblico." msgid "Bluesky uses invites to build a healthier community. If you don't know anybody with an invite, you can sign up for the waitlist and we'll send one soon." msgstr "Bluesky utilizza gli inviti per costruire una comunitĆ  più sana. Se non conosci nessuno con un invito, puoi iscriverti alla lista d'attesa e te ne invieremo uno al più presto." -#: src/view/screens/Moderation.tsx:226 +#: src/view/screens/Moderation.tsx:245 msgid "Bluesky will not show your profile and posts to logged-out users. Other apps may not honor this request. This does not make your account private." msgstr "Bluesky non mostrerĆ  il tuo profilo e i tuoi post agli utenti disconnessi. Altre app potrebbero non rispettare questa richiesta. Questo non rende il tuo account privato." @@ -527,8 +537,8 @@ msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must msgstr "Può contenere solo lettere, numeri, spazi, trattini e trattini bassi. Deve contenere almeno 4 caratteri, ma non più di 32 caratteri." #: src/components/Prompt.tsx:91 -#: src/view/com/composer/Composer.tsx:300 -#: src/view/com/composer/Composer.tsx:305 +#: src/view/com/composer/Composer.tsx:307 +#: src/view/com/composer/Composer.tsx:312 #: src/view/com/modals/ChangeEmail.tsx:218 #: src/view/com/modals/ChangeEmail.tsx:220 #: src/view/com/modals/ChangePassword.tsx:265 @@ -542,7 +552,7 @@ msgstr "Può contenere solo lettere, numeri, spazi, trattini e trattini bassi. D #: src/view/com/modals/VerifyEmail.tsx:247 #: src/view/com/modals/VerifyEmail.tsx:253 #: src/view/com/modals/Waitlist.tsx:142 -#: src/view/screens/Search/Search.tsx:693 +#: src/view/screens/Search/Search.tsx:716 #: src/view/shell/desktop/Search.tsx:238 msgid "Cancel" msgstr "Cancella" @@ -695,7 +705,7 @@ msgid "Clear all storage data (restart after this)" msgstr "Cancella tutti i dati in archivio (poi ricomincia)" #: src/view/com/util/forms/SearchInput.tsx:88 -#: src/view/screens/Search/Search.tsx:674 +#: src/view/screens/Search/Search.tsx:697 msgid "Clear search query" msgstr "Annulla la ricerca" @@ -703,6 +713,11 @@ msgstr "Annulla la ricerca" msgid "click here" msgstr "clicca qui" +#: src/components/RichText.tsx:189 +#: src/components/TagMenu/index.web.tsx:125 +msgid "Click here to open tag menu for {tag}" +msgstr "" + #: src/screens/Onboarding/index.tsx:35 msgid "Climate" msgstr "" @@ -733,11 +748,15 @@ msgstr "Chiudi l'immagine" msgid "Close image viewer" msgstr "Chiudi il visualizzatore di immagini" -#: src/view/shell/index.web.tsx:49 +#: src/view/shell/index.web.tsx:51 msgid "Close navigation footer" msgstr "Chiudi la navigazione del footer" -#: src/view/shell/index.web.tsx:50 +#: src/components/TagMenu/index.tsx:266 +msgid "Close this dialog" +msgstr "" + +#: src/view/shell/index.web.tsx:52 msgid "Closes bottom navigation bar" msgstr "Chiude la barra di navigazione in basso" @@ -745,7 +764,7 @@ msgstr "Chiude la barra di navigazione in basso" msgid "Closes password update alert" msgstr "Chiude l'avviso di aggiornamento della password" -#: src/view/com/composer/Composer.tsx:302 +#: src/view/com/composer/Composer.tsx:309 msgid "Closes post composer and discards post draft" msgstr "Chiude l'editore del post ed elimina la bozza del post" @@ -778,7 +797,7 @@ msgstr "" msgid "Complete the challenge" msgstr "" -#: src/view/com/composer/Composer.tsx:417 +#: src/view/com/composer/Composer.tsx:424 msgid "Compose posts up to {MAX_GRAPHEME_LENGTH} characters in length" msgstr "Componi un post fino a {MAX_GRAPHEME_LENGTH} caratteri" @@ -842,7 +861,7 @@ msgstr "Connessione in corso..." msgid "Contact support" msgstr "Contatta il supporto" -#: src/view/screens/Moderation.tsx:81 +#: src/view/screens/Moderation.tsx:83 msgid "Content filtering" msgstr "Filtro dei contenuti" @@ -908,7 +927,7 @@ msgstr "Versione di build copiata nella clipboard" #: src/view/com/modals/AddAppPasswords.tsx:76 #: src/view/com/modals/InviteCodes.tsx:152 -#: src/view/com/util/forms/PostDropdownBtn.tsx:141 +#: src/view/com/util/forms/PostDropdownBtn.tsx:143 msgid "Copied to clipboard" msgstr "Copiato nel clipboard" @@ -924,7 +943,7 @@ msgstr "Copia" msgid "Copy link to list" msgstr "Copia il link alla lista" -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 msgid "Copy link to post" msgstr "Copia il link al post" @@ -932,7 +951,7 @@ msgstr "Copia il link al post" msgid "Copy link to profile" msgstr "Copia il link al profilo" -#: src/view/com/util/forms/PostDropdownBtn.tsx:168 +#: src/view/com/util/forms/PostDropdownBtn.tsx:170 msgid "Copy post text" msgstr "Copia il testo del post" @@ -988,7 +1007,7 @@ msgstr "Creato da <0/>" msgid "Created by you" msgstr "Creato da te" -#: src/view/com/composer/Composer.tsx:448 +#: src/view/com/composer/Composer.tsx:455 msgid "Creates a card with a thumbnail. The card links to {url}" msgstr "Crea una scheda con una miniatura. La scheda si collega a {url}" @@ -1065,11 +1084,11 @@ msgstr "Cancella il mio account" msgid "Delete My Account…" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:257 +#: src/view/com/util/forms/PostDropdownBtn.tsx:273 msgid "Delete post" msgstr "Elimina il post" -#: src/view/com/util/forms/PostDropdownBtn.tsx:261 +#: src/view/com/util/forms/PostDropdownBtn.tsx:277 msgid "Delete this post?" msgstr "Elimina questo post?" @@ -1095,7 +1114,7 @@ msgstr "Descrizione" #~ msgid "Developer Tools" #~ msgstr "Strumenti per sviluppatori" -#: src/view/com/composer/Composer.tsx:211 +#: src/view/com/composer/Composer.tsx:218 msgid "Did you want to say anything?" msgstr "Volevi dire qualcosa?" @@ -1103,15 +1122,15 @@ msgstr "Volevi dire qualcosa?" msgid "Dim" msgstr "" -#: src/view/com/composer/Composer.tsx:144 +#: src/view/com/composer/Composer.tsx:151 msgid "Discard" msgstr "Scartare" -#: src/view/com/composer/Composer.tsx:138 +#: src/view/com/composer/Composer.tsx:145 msgid "Discard draft" msgstr "Scarta la bozza" -#: src/view/screens/Moderation.tsx:207 +#: src/view/screens/Moderation.tsx:226 msgid "Discourage apps from showing my account to logged-out users" msgstr "Scoraggia le app dal mostrare il mio account agli utenti disconnessi" @@ -1190,7 +1209,7 @@ msgstr "" msgid "Download CAR file" msgstr "" -#: src/view/com/composer/text-input/TextInput.web.tsx:247 +#: src/view/com/composer/text-input/TextInput.web.tsx:249 msgid "Drop to add images" msgstr "" @@ -1262,6 +1281,7 @@ msgstr "Modifica il profilo" msgid "Edit Profile" msgstr "Modifica il Profilo" +#: src/view/com/home/HomeHeaderLayout.web.tsx:59 #: src/view/screens/Feeds.tsx:355 msgid "Edit Saved Feeds" msgstr "Modifica i feeds memorizzati" @@ -1344,6 +1364,11 @@ msgstr "Fine del feed" msgid "Enter a name for this App Password" msgstr "Inserisci un nome per questa password dell'app" +#: src/components/dialogs/MutedWords.tsx:87 +#: src/components/dialogs/MutedWords.tsx:88 +msgid "Enter a word or tag" +msgstr "" + #: src/view/com/modals/VerifyEmail.tsx:105 msgid "Enter Confirmation Code" msgstr "Inserire il codice di conferma" @@ -1396,7 +1421,7 @@ msgstr "Inserisci il tuo nome di utente e la tua password" msgid "Error receiving captcha response." msgstr "" -#: src/view/screens/Search/Search.tsx:109 +#: src/view/screens/Search/Search.tsx:110 msgid "Error:" msgstr "Errore:" @@ -1467,7 +1492,7 @@ msgstr "Impossibile creare la password dell'app." msgid "Failed to create the list. Check your internet connection and try again." msgstr "Impossibile creare l'elenco. Controlla la connessione Internet e riprova." -#: src/view/com/util/forms/PostDropdownBtn.tsx:108 +#: src/view/com/util/forms/PostDropdownBtn.tsx:110 msgid "Failed to delete post, please try again" msgstr "Non possiamo eliminare il post, riprova di nuovo" @@ -1489,8 +1514,8 @@ msgid "Feed offline" msgstr "Feed offline" #: src/view/com/feeds/FeedPage.tsx:143 -msgid "Feed Preferences" -msgstr "Preferenze del feed" +#~ msgid "Feed Preferences" +#~ msgstr "Preferenze del feed" #: src/view/shell/desktop/RightNav.tsx:61 #: src/view/shell/Drawer.tsx:311 @@ -1530,11 +1555,11 @@ msgstr "" msgid "Find accounts to follow" msgstr "Trova account da seguire" -#: src/view/screens/Search/Search.tsx:439 +#: src/view/screens/Search/Search.tsx:440 msgid "Find users on Bluesky" msgstr "Trova utenti su Bluesky" -#: src/view/screens/Search/Search.tsx:437 +#: src/view/screens/Search/Search.tsx:438 msgid "Find users with the search tool on the right" msgstr "Trova gli utenti con lo strumento di ricerca sulla destra" @@ -1634,6 +1659,7 @@ msgid "Following {0}" msgstr "Seguiti {0}" #: src/Navigation.tsx:248 +#: src/view/com/home/HomeHeaderLayout.web.tsx:45 #: src/view/com/home/HomeHeaderLayoutMobile.tsx:83 #: src/view/screens/PreferencesFollowingFeed.tsx:104 #: src/view/screens/Settings/index.tsx:543 @@ -1673,7 +1699,7 @@ msgstr "Ho dimenticato il password" msgid "Forgot Password" msgstr "Ho dimenticato il Password" -#: src/view/com/posts/FeedItem.tsx:187 +#: src/view/com/posts/FeedItem.tsx:189 msgctxt "from-feed" msgid "From <0/>" msgstr "Da <0/>" @@ -1706,7 +1732,7 @@ msgstr "Torna Indietro" msgid "Go back to previous step" msgstr "" -#: src/view/screens/Search/Search.tsx:724 +#: src/view/screens/Search/Search.tsx:747 #: src/view/shell/desktop/Search.tsx:262 msgid "Go to @{queryMaybeHandle}" msgstr "Vai a @{queryMaybeHandle}" @@ -1723,6 +1749,10 @@ msgstr "Seguente" msgid "Handle" msgstr "Nome Utente" +#: src/components/RichText.tsx:188 +msgid "Hashtag: {tag}" +msgstr "" + #: src/view/com/auth/create/CreateAccount.tsx:208 msgid "Having trouble?" msgstr "Ci sono problemi?" @@ -1761,7 +1791,7 @@ msgctxt "action" msgid "Hide" msgstr "Nascondi" -#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +#: src/view/com/util/forms/PostDropdownBtn.tsx:232 msgid "Hide post" msgstr "Nascondi il messaggio" @@ -1770,7 +1800,7 @@ msgstr "Nascondi il messaggio" msgid "Hide the content" msgstr "Nascondere il contenuto" -#: src/view/com/util/forms/PostDropdownBtn.tsx:220 +#: src/view/com/util/forms/PostDropdownBtn.tsx:236 msgid "Hide this post?" msgstr "Vuoi nascondere questo post?" @@ -1922,7 +1952,7 @@ msgstr "Inserisci la tua password" msgid "Input your user handle" msgstr "Inserisci il tuo identificatore" -#: src/view/com/post-thread/PostThreadItem.tsx:224 +#: src/view/com/post-thread/PostThreadItem.tsx:226 msgid "Invalid or unsupported post record" msgstr "Protocollo del post non valido o non supportato" @@ -2024,7 +2054,7 @@ msgstr "Ulteriori Informazioni" msgid "Learn more about this warning" msgstr "Ulteriori informazioni su questo avviso" -#: src/view/screens/Moderation.tsx:243 +#: src/view/screens/Moderation.tsx:262 msgid "Learn more about what is public on Bluesky." msgstr "Scopri cosa ĆØ pubblico su Bluesky." @@ -2104,7 +2134,7 @@ msgstr "ĆØ piaciuto il tuo post" msgid "Likes" msgstr "Mi piace" -#: src/view/com/post-thread/PostThreadItem.tsx:181 +#: src/view/com/post-thread/PostThreadItem.tsx:183 msgid "Likes on this post" msgstr "Mi Piace in questo post" @@ -2161,7 +2191,7 @@ msgstr "Carica più post" msgid "Load new notifications" msgstr "Carica più notifiche" -#: src/view/com/feeds/FeedPage.tsx:181 +#: src/view/com/feeds/FeedPage.tsx:115 #: src/view/screens/Profile.tsx:440 #: src/view/screens/ProfileFeed.tsx:495 #: src/view/screens/ProfileList.tsx:681 @@ -2187,7 +2217,7 @@ msgstr "Log" msgid "Log out" msgstr "" -#: src/view/screens/Moderation.tsx:136 +#: src/view/screens/Moderation.tsx:155 msgid "Logged-out visibility" msgstr "VisibilitĆ  degli utenti non connettati" @@ -2202,6 +2232,10 @@ msgstr "Accedi all'account che non ĆØ nella lista" msgid "Make sure this is where you intend to go!" msgstr "Assicurati che questo sia dove intendi andare!" +#: src/components/dialogs/MutedWords.tsx:71 +msgid "Manage your muted words and tags" +msgstr "" + #: src/view/com/auth/create/Step2.tsx:118 msgid "May not be longer than 253 characters" msgstr "" @@ -2223,7 +2257,7 @@ msgid "Mentioned users" msgstr "Utenti menzionati" #: src/view/com/util/ViewHeader.tsx:81 -#: src/view/screens/Search/Search.tsx:623 +#: src/view/screens/Search/Search.tsx:646 msgid "Menu" msgstr "Menù" @@ -2235,7 +2269,7 @@ msgid "Message from server: {0}" msgstr "Messaggio dal server: {0}" #: src/Navigation.tsx:115 -#: src/view/screens/Moderation.tsx:64 +#: src/view/screens/Moderation.tsx:66 #: src/view/screens/Settings/index.tsx:625 #: src/view/shell/desktop/LeftNav.tsx:397 #: src/view/shell/Drawer.tsx:511 @@ -2266,7 +2300,7 @@ msgstr "Lista di moderazione creata" msgid "Moderation list updated" msgstr "Lista di moderazione aggiornata" -#: src/view/screens/Moderation.tsx:95 +#: src/view/screens/Moderation.tsx:114 msgid "Moderation lists" msgstr "Liste di moderazione" @@ -2293,7 +2327,7 @@ msgstr "Altri feed" msgid "More options" msgstr "Altre opzioni" -#: src/view/com/util/forms/PostDropdownBtn.tsx:299 +#: src/view/com/util/forms/PostDropdownBtn.tsx:315 msgid "More post options" msgstr "Altre impostazioni per il post" @@ -2305,6 +2339,14 @@ msgstr "Dai prioritĆ  alle risposte con più likes" msgid "Must be at least 3 characters" msgstr "" +#: src/components/TagMenu/index.tsx:253 +msgid "Mute" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:91 +msgid "Mute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:327 msgid "Mute Account" msgstr "Silenziare Account" @@ -2313,6 +2355,18 @@ msgstr "Silenziare Account" msgid "Mute accounts" msgstr "Silenziare accounts" +#: src/components/TagMenu/index.tsx:211 +msgid "Mute all {tag} posts" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:131 +msgid "Mute in tags only" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:116 +msgid "Mute in text & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:491 msgid "Mute list" msgstr "Silenziare la lista" @@ -2325,15 +2379,27 @@ msgstr "Vuoi silenziare queste liste?" msgid "Mute this List" msgstr "Silenzia questa Lista" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/dialogs/MutedWords.tsx:109 +msgid "Mute this word in post text and tags" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:124 +msgid "Mute this word in tags only" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Mute thread" msgstr "Silenzia questa discussione" +#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +msgid "Mute words & tags" +msgstr "" + #: src/view/com/lists/ListCard.tsx:102 msgid "Muted" msgstr "Silenziato" -#: src/view/screens/Moderation.tsx:109 +#: src/view/screens/Moderation.tsx:128 msgid "Muted accounts" msgstr "Account silenziato" @@ -2346,6 +2412,10 @@ msgstr "Accounts Silenziati" msgid "Muted accounts have their posts removed from your feed and from your notifications. Mutes are completely private." msgstr "I post degli account silenziati verranno rimossi dal tuo feed e dalle tue notifiche. Silenziare ĆØ completamente privato." +#: src/view/screens/Moderation.tsx:100 +msgid "Muted words & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:277 msgid "Muting is private. Muted accounts can interact with you, but you will not see their posts or receive notifications from them." msgstr "Silenziare un account ĆØ privato. Gli account silenziati possono interagire con te, ma non vedrai i loro post nĆ© riceverai le loro notifiche." @@ -2409,6 +2479,10 @@ msgstr "Non perdere mai l'accesso ai tuoi follower e ai tuoi dati." msgid "Never lose access to your followers or data." msgstr "" +#: src/components/dialogs/MutedWords.tsx:244 +msgid "Nevermind" +msgstr "" + #: src/view/screens/Lists.tsx:76 msgctxt "action" msgid "New" @@ -2430,7 +2504,7 @@ msgstr "Nuovo Password" msgid "New Password" msgstr "" -#: src/view/com/feeds/FeedPage.tsx:192 +#: src/view/com/feeds/FeedPage.tsx:126 msgctxt "action" msgid "New post" msgstr "Nuovo Post" @@ -2518,8 +2592,8 @@ msgid "No results found for \"{query}\"" msgstr "Nessun risultato trovato per \"{query}\"" #: src/view/com/modals/ListAddRemoveUsers.tsx:127 -#: src/view/screens/Search/Search.tsx:280 -#: src/view/screens/Search/Search.tsx:308 +#: src/view/screens/Search/Search.tsx:281 +#: src/view/screens/Search/Search.tsx:309 msgid "No results found for {query}" msgstr "Nessun risultato trovato per {query}" @@ -2545,7 +2619,7 @@ msgstr "Non trovato" msgid "Not right now" msgstr "Non adesso" -#: src/view/screens/Moderation.tsx:233 +#: src/view/screens/Moderation.tsx:252 msgid "Note: Bluesky is an open and public network. This setting only limits the visibility of your content on the Bluesky app and website, and other apps may not respect this setting. Your content may still be shown to logged-out users by other apps and websites." msgstr "Nota: Bluesky ĆØ una rete aperta e pubblica. Questa impostazione limita solo la visibilitĆ  dei tuoi contenuti sull'app e sul sito Web di Bluesky e altre app potrebbero non rispettare questa impostazione. I tuoi contenuti potrebbero comunque essere mostrati agli utenti disconnessi da altre app e siti web." @@ -2583,7 +2657,7 @@ msgstr "Prima le risposte più vecchie" msgid "Onboarding reset" msgstr "Reimpostazione dell'onboarding" -#: src/view/com/composer/Composer.tsx:375 +#: src/view/com/composer/Composer.tsx:382 msgid "One or more images is missing alt text." msgstr "A una o più immagini manca il testo alternativo." @@ -2600,8 +2674,12 @@ msgstr "Ops!" msgid "Open" msgstr "" -#: src/view/com/composer/Composer.tsx:470 -#: src/view/com/composer/Composer.tsx:471 +#: src/view/screens/Moderation.tsx:75 +msgid "Open content filtering settings" +msgstr "" + +#: src/view/com/composer/Composer.tsx:477 +#: src/view/com/composer/Composer.tsx:478 msgid "Open emoji picker" msgstr "Apri il selettore emoji" @@ -2609,6 +2687,10 @@ msgstr "Apri il selettore emoji" msgid "Open links with in-app browser" msgstr "Apri i links con il navigatore della app" +#: src/view/screens/Moderation.tsx:92 +msgid "Open muted words settings" +msgstr "" + #: src/view/com/home/HomeHeaderLayoutMobile.tsx:49 msgid "Open navigation" msgstr "Apri la navigazione" @@ -2685,6 +2767,7 @@ msgstr "Apre le impostazioni di moderazione" msgid "Opens password reset form" msgstr "Apre il modulo di reimpostazione della password" +#: src/view/com/home/HomeHeaderLayout.web.tsx:60 #: src/view/screens/Feeds.tsx:356 msgid "Opens screen to edit Saved Feeds" msgstr "Apre la schermata per modificare i feed salvati" @@ -2863,7 +2946,7 @@ msgstr "Spiegaci perchĆ© ritieni che questo avviso sui contenuti sia stato appli msgid "Please Verify Your Email" msgstr "Verifica la tua email" -#: src/view/com/composer/Composer.tsx:215 +#: src/view/com/composer/Composer.tsx:222 msgid "Please wait for your link card to finish loading" msgstr "Attendi il caricamento della scheda di collegamento" @@ -2875,8 +2958,8 @@ msgstr "" msgid "Porn" msgstr "Porno" -#: src/view/com/composer/Composer.tsx:350 -#: src/view/com/composer/Composer.tsx:358 +#: src/view/com/composer/Composer.tsx:357 +#: src/view/com/composer/Composer.tsx:365 msgctxt "action" msgid "Post" msgstr "Post" @@ -2889,7 +2972,7 @@ msgstr "Post" #~ msgid "Post" #~ msgstr "Publicació" -#: src/view/com/post-thread/PostThreadItem.tsx:173 +#: src/view/com/post-thread/PostThreadItem.tsx:175 msgid "Post by {0}" msgstr "Pubblicato da {0}" @@ -2899,11 +2982,11 @@ msgstr "Pubblicato da {0}" msgid "Post by @{0}" msgstr "Pubblicato da @{0}" -#: src/view/com/util/forms/PostDropdownBtn.tsx:88 +#: src/view/com/util/forms/PostDropdownBtn.tsx:90 msgid "Post deleted" msgstr "Post eliminato" -#: src/view/com/post-thread/PostThread.tsx:461 +#: src/view/com/post-thread/PostThread.tsx:462 msgid "Post hidden" msgstr "Post nascosto" @@ -2915,14 +2998,22 @@ msgstr "Lingua del post" msgid "Post Languages" msgstr "Lingue del post" -#: src/view/com/post-thread/PostThread.tsx:513 +#: src/view/com/post-thread/PostThread.tsx:514 msgid "Post not found" msgstr "Post non trovato" +#: src/components/TagMenu/index.tsx:257 +msgid "posts" +msgstr "" + #: src/view/screens/Profile.tsx:180 msgid "Posts" msgstr "Post" +#: src/components/dialogs/MutedWords.tsx:77 +msgid "Posts can be muted based on their text, their tags, or both." +msgstr "" + #: src/view/com/posts/FeedErrorMessage.tsx:64 msgid "Posts hidden" msgstr "Post nascosto" @@ -2987,11 +3078,11 @@ msgstr "Elenchi pubblici e condivisibili di utenti da disattivare o bloccare in msgid "Public, shareable lists which can drive feeds." msgstr "Elenchi pubblici e condivisibili che possono gestire i feeds." -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish post" msgstr "Pubblica il post" -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish reply" msgstr "Pubblica la risposta" @@ -3028,6 +3119,7 @@ msgstr "Feeds consigliati" msgid "Recommended Users" msgstr "Utenti consigliati" +#: src/components/dialogs/MutedWords.tsx:249 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/SelfLabel.tsx:83 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -3065,6 +3157,10 @@ msgstr "Rimuovi l'immagine" msgid "Remove image preview" msgstr "Rimuovi l'anteprima dell'immagine" +#: src/components/dialogs/MutedWords.tsx:294 +msgid "Remove mute word from your list" +msgstr "" + #: src/view/com/modals/Repost.tsx:47 msgid "Remove repost" msgstr "Rimuovi la ripubblicazione" @@ -3099,7 +3195,7 @@ msgstr "Risposte" msgid "Replies to this thread are disabled" msgstr "Le risposte a questo thread sono disabilitate" -#: src/view/com/composer/Composer.tsx:348 +#: src/view/com/composer/Composer.tsx:355 msgctxt "action" msgid "Reply" msgstr "Rispondi" @@ -3109,7 +3205,7 @@ msgid "Reply Filters" msgstr "Filtri di risposta" #: src/view/com/post/Post.tsx:167 -#: src/view/com/posts/FeedItem.tsx:285 +#: src/view/com/posts/FeedItem.tsx:287 msgctxt "description" msgid "Reply to <0/>" msgstr "Rispondi a <0/>" @@ -3131,7 +3227,7 @@ msgid "Report List" msgstr "Segnala la lista" #: src/view/com/modals/report/SendReportButton.tsx:37 -#: src/view/com/util/forms/PostDropdownBtn.tsx:239 +#: src/view/com/util/forms/PostDropdownBtn.tsx:255 msgid "Report post" msgstr "Segnala il post" @@ -3160,7 +3256,7 @@ msgstr "Ripubblicare o citare il post" msgid "Reposted By" msgstr "" -#: src/view/com/posts/FeedItem.tsx:205 +#: src/view/com/posts/FeedItem.tsx:207 msgid "Reposted by {0}" msgstr "" @@ -3168,7 +3264,7 @@ msgstr "" #~ msgid "Reposted by {0})" #~ msgstr "Ripubblicato da {0})" -#: src/view/com/posts/FeedItem.tsx:222 +#: src/view/com/posts/FeedItem.tsx:224 msgid "Reposted by <0/>" msgstr "Ripubblicato da <0/>" @@ -3176,7 +3272,7 @@ msgstr "Ripubblicato da <0/>" msgid "reposted your post" msgstr "ripubblicato il tuo post" -#: src/view/com/post-thread/PostThreadItem.tsx:186 +#: src/view/com/post-thread/PostThreadItem.tsx:188 msgid "Reposts of this post" msgstr "Ripubblicazione di questo post" @@ -3327,9 +3423,9 @@ msgstr "Scorri verso l'alto" #: src/view/com/modals/ListAddRemoveUsers.tsx:75 #: src/view/com/util/forms/SearchInput.tsx:67 #: src/view/com/util/forms/SearchInput.tsx:79 -#: src/view/screens/Search/Search.tsx:418 -#: src/view/screens/Search/Search.tsx:645 -#: src/view/screens/Search/Search.tsx:663 +#: src/view/screens/Search/Search.tsx:419 +#: src/view/screens/Search/Search.tsx:668 +#: src/view/screens/Search/Search.tsx:686 #: src/view/shell/bottom-bar/BottomBar.tsx:159 #: src/view/shell/desktop/LeftNav.tsx:324 #: src/view/shell/desktop/Search.tsx:214 @@ -3339,11 +3435,19 @@ msgstr "Scorri verso l'alto" msgid "Search" msgstr "Cerca" -#: src/view/screens/Search/Search.tsx:712 +#: src/view/screens/Search/Search.tsx:735 #: src/view/shell/desktop/Search.tsx:255 msgid "Search for \"{query}\"" msgstr "Cerca \"{query}\"" +#: src/components/TagMenu/index.tsx:145 +msgid "Search for all posts by @{authorHandle} with tag {tag}" +msgstr "" + +#: src/components/TagMenu/index.tsx:90 +msgid "Search for all posts with tag {tag}" +msgstr "" + #: src/view/com/auth/LoggedOut.tsx:104 #: src/view/com/auth/LoggedOut.tsx:105 #: src/view/com/modals/ListAddRemoveUsers.tsx:70 @@ -3354,6 +3458,22 @@ msgstr "Cerca utenti" msgid "Security Step Required" msgstr "Passaggio di sicurezza obbligatorio" +#: src/components/TagMenu/index.web.tsx:50 +msgid "See {truncatedTag} posts" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:67 +msgid "See {truncatedTag} posts by user" +msgstr "" + +#: src/components/TagMenu/index.tsx:128 +msgid "See <0>{tag} posts" +msgstr "" + +#: src/components/TagMenu/index.tsx:189 +msgid "See <0>{tag} posts by this user" +msgstr "" + #: src/view/screens/SavedFeeds.tsx:163 msgid "See this guide" msgstr "Consulta questa guida" @@ -3562,7 +3682,7 @@ msgid "Share" msgstr "Condividi" #: src/view/com/profile/ProfileHeader.tsx:295 -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 #: src/view/screens/ProfileList.tsx:418 msgid "Share" msgstr "Condividi" @@ -3595,9 +3715,9 @@ msgstr "Mostra incorporamenti di {0}" msgid "Show follows similar to {0}" msgstr "Mostra follows simile a {0}" -#: src/view/com/post-thread/PostThreadItem.tsx:532 -#: src/view/com/post/Post.tsx:196 -#: src/view/com/posts/FeedItem.tsx:359 +#: src/view/com/post-thread/PostThreadItem.tsx:538 +#: src/view/com/post/Post.tsx:198 +#: src/view/com/posts/FeedItem.tsx:363 msgid "Show More" msgstr "Mostra di più" @@ -3765,7 +3885,7 @@ msgstr "" msgid "Something went wrong. Check your email and try again." msgstr "Qualcosa ĆØ andato storto. Controlla la tua email e riprova." -#: src/App.native.tsx:61 +#: src/App.native.tsx:63 msgid "Sorry! Your session expired. Please log in again." msgstr "Scusa! La tua sessione ĆØ scaduta. Per favore accedi di nuovo." @@ -3823,7 +3943,7 @@ msgstr "" msgid "Subscribe to this list" msgstr "Iscriviti alla lista" -#: src/view/screens/Search/Search.tsx:373 +#: src/view/screens/Search/Search.tsx:374 msgid "Suggested Follows" msgstr "Followers suggeriti" @@ -3867,6 +3987,14 @@ msgstr "Sistema" msgid "System log" msgstr "Registro di sistema" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "tag" +msgstr "" + +#: src/components/TagMenu/index.tsx:74 +msgid "Tag menu: {tag}" +msgstr "" + #: src/view/com/modals/crop-image/CropImage.web.tsx:112 msgid "Tall" msgstr "Alto" @@ -3890,6 +4018,10 @@ msgstr "Termini" msgid "Terms of Service" msgstr "Termini di servizio" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "text" +msgstr "" + #: src/view/com/modals/AppealLabel.tsx:70 #: src/view/com/modals/report/InputIssueDetails.tsx:51 msgid "Text input field" @@ -3915,7 +4047,7 @@ msgstr "La politica sul copyright ĆØ stata spostata a <0/>" msgid "The following steps will help customize your Bluesky experience." msgstr "" -#: src/view/com/post-thread/PostThread.tsx:516 +#: src/view/com/post-thread/PostThread.tsx:517 msgid "The post may have been deleted." msgstr "Il post potrebbe essere stato cancellato." @@ -4090,7 +4222,7 @@ msgstr "La lista ĆØ vuota!" msgid "This name is already in use" msgstr "Questo nome ĆØ giĆ  in uso" -#: src/view/com/post-thread/PostThreadItem.tsx:123 +#: src/view/com/post-thread/PostThreadItem.tsx:125 msgid "This post has been deleted." msgstr "Questo post ĆØ stato cancellato." @@ -4114,7 +4246,11 @@ msgstr "" msgid "This warning is only available for posts with media attached." msgstr "Questo avviso ĆØ disponibile solo per i post con contenuti multimediali allegati." -#: src/view/com/util/forms/PostDropdownBtn.tsx:221 +#: src/components/dialogs/MutedWords.tsx:236 +msgid "This will delete {0} from your muted words. You can always add it back later." +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:237 msgid "This will hide this post from your feeds." msgstr "Questo nasconderĆ  il post dai tuoi feeds." @@ -4131,6 +4267,10 @@ msgstr "ModalitĆ  discussione" msgid "Threads Preferences" msgstr "Preferenze per le discussioni" +#: src/components/dialogs/MutedWords.tsx:95 +msgid "Toggle between muted word options." +msgstr "" + #: src/view/com/util/forms/DropdownButton.tsx:246 msgid "Toggle dropdown" msgstr "Attiva/disattiva il menu a discesa" @@ -4139,9 +4279,9 @@ msgstr "Attiva/disattiva il menu a discesa" msgid "Transformations" msgstr "Trasformazioni" -#: src/view/com/post-thread/PostThreadItem.tsx:679 -#: src/view/com/post-thread/PostThreadItem.tsx:681 -#: src/view/com/util/forms/PostDropdownBtn.tsx:154 +#: src/view/com/post-thread/PostThreadItem.tsx:685 +#: src/view/com/post-thread/PostThreadItem.tsx:687 +#: src/view/com/util/forms/PostDropdownBtn.tsx:156 msgid "Translate" msgstr "Tradurre" @@ -4209,15 +4349,24 @@ msgstr "Sfortunatamente, non soddisfi i requisiti per creare un account." msgid "Unlike" msgstr "Togli Mi piace" +#: src/components/TagMenu/index.tsx:253 #: src/view/screens/ProfileList.tsx:597 msgid "Unmute" msgstr "Riattiva" +#: src/components/TagMenu/index.web.tsx:90 +msgid "Unmute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:326 msgid "Unmute Account" msgstr "Riattiva questo account" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/TagMenu/index.tsx:210 +msgid "Unmute all {tag} posts" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Unmute thread" msgstr "Riattiva questa discussione" @@ -4414,6 +4563,10 @@ msgstr "" msgid "We ran out of posts from your follows. Here's the latest from <0/>." msgstr "Abbiamo esaurito i posts dei tuoi follower. Ecco le ultime novitĆ  da <0/>." +#: src/components/dialogs/MutedWords.tsx:161 +msgid "We recommend avoiding common words that appear in many posts, since it can result in no posts being shown." +msgstr "" + #: src/screens/Onboarding/StepAlgoFeeds/index.tsx:124 msgid "We recommend our \"Discover\" feed:" msgstr "" @@ -4442,7 +4595,11 @@ msgstr "Siamo felici che tu ti unisca a noi!" msgid "We're sorry, but we were unable to resolve this list. If this persists, please contact the list creator, @{handleOrDid}." msgstr "Siamo spiacenti, ma non siamo riusciti a risolvere questa lista. Se il problema persiste, contatta il creatore della lista, @{handleOrDid}." -#: src/view/screens/Search/Search.tsx:253 +#: src/components/dialogs/MutedWords.tsx:182 +msgid "We're sorry, but we weren't able to load your muted words at this time. Please try again." +msgstr "" + +#: src/view/screens/Search/Search.tsx:254 msgid "We're sorry, but your search could not be completed. Please try again in a few minutes." msgstr "Siamo spiacenti, ma non ĆØ stato possibile completare la ricerca. Riprova tra qualche minuto." @@ -4466,7 +4623,7 @@ msgstr "Qual ĆØ il problema con questo {collectionName}?" #~ msgstr "ĀæQuĆ© sigue?" #: src/view/com/auth/SplashScreen.tsx:59 -#: src/view/com/composer/Composer.tsx:279 +#: src/view/com/composer/Composer.tsx:286 msgid "What's up?" msgstr "Come va?" @@ -4487,11 +4644,11 @@ msgstr "Chi può rispondere" msgid "Wide" msgstr "Largo" -#: src/view/com/composer/Composer.tsx:415 +#: src/view/com/composer/Composer.tsx:422 msgid "Write post" msgstr "Scrivi un post" -#: src/view/com/composer/Composer.tsx:278 +#: src/view/com/composer/Composer.tsx:285 #: src/view/com/composer/Prompt.tsx:33 msgid "Write your reply" msgstr "Scrivi la tua risposta" @@ -4551,7 +4708,7 @@ msgstr "Non hai salvato nessun feed!" msgid "You don't have any saved feeds." msgstr "Non hai salvato nessun feed." -#: src/view/com/post-thread/PostThread.tsx:464 +#: src/view/com/post-thread/PostThread.tsx:465 msgid "You have blocked the author or you have been blocked by the author." msgstr "Hai bloccato l'autore o sei stato bloccato dall'autore." @@ -4591,6 +4748,10 @@ msgstr "Non hai ancora creato alcuna password per l'app. Puoi crearne uno premen msgid "You have not muted any accounts yet. To mute an account, go to their profile and selected \"Mute account\" from the menu on their account." msgstr "Non hai ancora disattivato alcun account. Per disattivare un account, vai al suo profilo e seleziona \"Disattiva account\" dal menu del account." +#: src/components/dialogs/MutedWords.tsx:202 +msgid "You haven't muted any words or tags yet" +msgstr "" + #: src/view/com/modals/ContentFilteringSettings.tsx:175 msgid "You must be 18 or older to enable adult content." msgstr "Devi avere almeno 18 anni per abilitare i contenuti per adulti." @@ -4599,11 +4760,11 @@ msgstr "Devi avere almeno 18 anni per abilitare i contenuti per adulti." msgid "You must be 18 years or older to enable adult content" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:127 +#: src/view/com/util/forms/PostDropdownBtn.tsx:129 msgid "You will no longer receive notifications for this thread" msgstr "Non riceverai più notifiche per questo filo di discussione" -#: src/view/com/util/forms/PostDropdownBtn.tsx:130 +#: src/view/com/util/forms/PostDropdownBtn.tsx:132 msgid "You will now receive notifications for this thread" msgstr "Adesso riceverai le notifiche per questa discussione" @@ -4691,11 +4852,15 @@ msgstr "Il tuo nome di utente completo sarĆ  <0>@{0}" #~ msgid "Your invite codes are hidden when logged in using an App Password" #~ msgstr "I tuoi codici di invito vengono celati quando accedi utilizzando una password per l'app" +#: src/components/dialogs/MutedWords.tsx:173 +msgid "Your muted words" +msgstr "" + #: src/view/com/modals/ChangePassword.tsx:155 msgid "Your password has been changed successfully!" msgstr "" -#: src/view/com/composer/Composer.tsx:267 +#: src/view/com/composer/Composer.tsx:274 msgid "Your post has been published" msgstr "Il tuo post ĆØ stato pubblicato" @@ -4710,7 +4875,7 @@ msgstr "I tuoi post, i tuoi Mi piace e i tuoi blocchi sono pubblici. I conti sil msgid "Your profile" msgstr "Il tuo profilo" -#: src/view/com/composer/Composer.tsx:266 +#: src/view/com/composer/Composer.tsx:273 msgid "Your reply has been published" msgstr "La tua risposta ĆØ stata pubblicata" diff --git a/src/locale/locales/ja/messages.po b/src/locale/locales/ja/messages.po index a0ad5ffb8d..21f2e5e0fc 100644 --- a/src/locale/locales/ja/messages.po +++ b/src/locale/locales/ja/messages.po @@ -93,7 +93,7 @@ msgid "A new version of the app is available. Please update to continue using th msgstr "ę–°ć—ć„ćƒćƒ¼ć‚øćƒ§ćƒ³ć®ć‚¢ćƒ—ćƒŖćŒåˆ©ē”ØåÆčƒ½ć§ć™ć€‚ē¶™ē¶šć—ć¦ä½æē”Øć™ć‚‹ćŸć‚ć«ćÆć‚¢ćƒƒćƒ—ćƒ‡ćƒ¼ćƒˆć—ć¦ćć ć•ć„ć€‚" #: src/view/com/util/ViewHeader.tsx:83 -#: src/view/screens/Search/Search.tsx:624 +#: src/view/screens/Search/Search.tsx:647 msgid "Access navigation links and settings" msgstr "ćƒŠćƒ“ć‚²ćƒ¼ć‚·ćƒ§ćƒ³ćƒŖćƒ³ć‚ÆćØčØ­å®šć«ć‚¢ć‚Æć‚»ć‚¹" @@ -144,6 +144,7 @@ msgstr "ć‚¢ć‚«ć‚¦ćƒ³ćƒˆć®ćƒ–ćƒ­ćƒƒć‚Æć‚’č§£é™¤ć—ć¾ć—ćŸ" msgid "Account unmuted" msgstr "ć‚¢ć‚«ć‚¦ćƒ³ćƒˆć®ćƒŸćƒ„ćƒ¼ćƒˆć‚’č§£é™¤ć—ć¾ć—ćŸ" +#: src/components/dialogs/MutedWords.tsx:147 #: src/view/com/auth/onboarding/RecommendedFeedsItem.tsx:150 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -185,14 +186,22 @@ msgstr "č©³ē“°ć‚’čæ½åŠ " msgid "Add details to report" msgstr "ćƒ¬ćƒćƒ¼ćƒˆć«č©³ē“°ć‚’čæ½åŠ " -#: src/view/com/composer/Composer.tsx:446 +#: src/view/com/composer/Composer.tsx:453 msgid "Add link card" msgstr "ćƒŖćƒ³ć‚Æć‚«ćƒ¼ćƒ‰ć‚’čæ½åŠ " -#: src/view/com/composer/Composer.tsx:451 +#: src/view/com/composer/Composer.tsx:458 msgid "Add link card:" msgstr "ćƒŖćƒ³ć‚Æć‚«ćƒ¼ćƒ‰ć‚’čæ½åŠ ļ¼š" +#: src/components/dialogs/MutedWords.tsx:140 +msgid "Add mute word for configured settings" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:74 +msgid "Add muted words and tags" +msgstr "" + #: src/view/com/modals/ChangeHandle.tsx:417 msgid "Add the following DNS record to your domain:" msgstr "ꬔ恮DNSćƒ¬ć‚³ćƒ¼ćƒ‰ć‚’ćƒ‰ćƒ”ć‚¤ćƒ³ć«čæ½åŠ ć—ć¦ćć ć•ć„ļ¼š" @@ -316,7 +325,7 @@ msgstr "ć‚¢ćƒ—ćƒŖćƒ‘ć‚¹ćƒÆćƒ¼ćƒ‰ć®čØ­å®š" msgid "App Passwords" msgstr "ć‚¢ćƒ—ćƒŖćƒ‘ć‚¹ćƒÆćƒ¼ćƒ‰" -#: src/view/com/util/forms/PostDropdownBtn.tsx:279 +#: src/view/com/util/forms/PostDropdownBtn.tsx:295 msgid "Appeal content warning" msgstr "ć‚³ćƒ³ćƒ†ćƒ³ćƒ„ć®č­¦å‘Šć«ē•°č­°ć‚’ē”³ć—ē«‹ć¦ć‚‹" @@ -344,15 +353,16 @@ msgstr "čƒŒę™Æ" msgid "Are you sure you want to delete the app password \"{name}\"?" msgstr "ć‚¢ćƒ—ćƒŖćƒ‘ć‚¹ćƒÆćƒ¼ćƒ‰ć€Œ{name}ć€ć‚’ęœ¬å½“ć«å‰Šé™¤ć—ć¾ć™ć‹ļ¼Ÿ" -#: src/view/com/composer/Composer.tsx:143 +#: src/view/com/composer/Composer.tsx:150 msgid "Are you sure you'd like to discard this draft?" msgstr "ęœ¬å½“ć«ć“ć®äø‹ę›øćć‚’ē “ę£„ć—ć¾ć™ć‹ļ¼Ÿ" +#: src/components/dialogs/MutedWords.tsx:233 #: src/view/screens/ProfileList.tsx:365 msgid "Are you sure?" msgstr "ęœ¬å½“ć«ć‚ˆć‚ć—ć„ć§ć™ć‹ļ¼Ÿ" -#: src/view/com/util/forms/PostDropdownBtn.tsx:262 +#: src/view/com/util/forms/PostDropdownBtn.tsx:278 msgid "Are you sure? This cannot be undone." msgstr "ęœ¬å½“ć«ć‚ˆć‚ć—ć„ć§ć™ć‹ļ¼Ÿć“ć‚ŒćÆå…ƒć«ęˆ»ć›ć¾ć›ć‚“ć€‚" @@ -374,15 +384,15 @@ msgstr "čŠøč”“ēš„ć¾ćŸćÆę€§ēš„ć§ćÆćŖć„ćƒŒćƒ¼ćƒ‰ć€‚" #: src/view/com/auth/login/LoginForm.tsx:259 #: src/view/com/auth/login/SetNewPasswordForm.tsx:179 #: src/view/com/modals/report/InputIssueDetails.tsx:46 -#: src/view/com/post-thread/PostThread.tsx:471 -#: src/view/com/post-thread/PostThread.tsx:521 -#: src/view/com/post-thread/PostThread.tsx:529 +#: src/view/com/post-thread/PostThread.tsx:472 +#: src/view/com/post-thread/PostThread.tsx:522 +#: src/view/com/post-thread/PostThread.tsx:530 #: src/view/com/profile/ProfileHeader.tsx:649 #: src/view/com/util/ViewHeader.tsx:81 msgid "Back" msgstr "ęˆ»ć‚‹" -#: src/view/com/post-thread/PostThread.tsx:479 +#: src/view/com/post-thread/PostThread.tsx:480 msgctxt "action" msgid "Back" msgstr "ęˆ»ć‚‹" @@ -430,7 +440,7 @@ msgstr "ć“ć®ćƒŖć‚¹ćƒˆć‚’ćƒ–ćƒ­ćƒƒć‚Æ" msgid "Blocked" msgstr "ćƒ–ćƒ­ćƒƒć‚Æć•ć‚Œć¦ć„ć¾ć™" -#: src/view/screens/Moderation.tsx:123 +#: src/view/screens/Moderation.tsx:142 msgid "Blocked accounts" msgstr "ćƒ–ćƒ­ćƒƒć‚Æäø­ć®ć‚¢ć‚«ć‚¦ćƒ³ćƒˆ" @@ -489,7 +499,7 @@ msgstr "BlueskyćÆćƒ‘ćƒ–ćƒŖćƒƒć‚Æć§ć™ć€‚" msgid "Bluesky uses invites to build a healthier community. If you don't know anybody with an invite, you can sign up for the waitlist and we'll send one soon." msgstr "BlueskyćÆć‚ˆć‚Šå„å…ØćŖć‚³ćƒŸćƒ„ćƒ‹ćƒ†ć‚£ćƒ¼ć‚’ę§‹ēÆ‰ć™ć‚‹ćŸć‚ć«ę‹›å¾…ēŠ¶ć‚’ä½æē”Øć—ć¾ć™ć€‚ę‹›å¾…ēŠ¶ć‚’ćŠęŒć”ć§ćŖć„å “åˆć€Waitlistć«ćŠē”³ć—č¾¼ćæć„ćŸć ććØę‹›å¾…ēŠ¶ć‚’ćŠé€ć‚Šć—ć¾ć™ć€‚" -#: src/view/screens/Moderation.tsx:226 +#: src/view/screens/Moderation.tsx:245 msgid "Bluesky will not show your profile and posts to logged-out users. Other apps may not honor this request. This does not make your account private." msgstr "BlueskyćÆćƒ­ć‚°ć‚¢ć‚¦ćƒˆć—ćŸćƒ¦ćƒ¼ć‚¶ćƒ¼ć«ć‚ćŖćŸć®ćƒ—ćƒ­ćƒ•ć‚£ćƒ¼ćƒ«ć‚„ęŠ•ēØæć‚’č”Øē¤ŗć—ć¾ć›ć‚“ć€‚ä»–ć®ć‚¢ćƒ—ćƒŖćÆć“ć®ćƒŖć‚Æć‚Øć‚¹ćƒˆć«åæœć˜ćŖć„å “åˆćŒć‚ć‚Šć¾ć™ć€‚ć“ć®čØ­å®šćÆć‚ćŖćŸć®ć‚¢ć‚«ć‚¦ćƒ³ćƒˆć‚’éžå…¬é–‹ć«ć™ć‚‹ć‚‚ć®ć§ćÆć‚ć‚Šć¾ć›ć‚“ć€‚" @@ -541,8 +551,8 @@ msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must msgstr "č‹±ę•°å­—ć€ć‚¹ćƒšćƒ¼ć‚¹ć€ćƒć‚¤ćƒ•ćƒ³ć€ć‚¢ćƒ³ćƒ€ćƒ¼ć‚¹ć‚³ć‚¢ć®ćæćŒä½æē”ØåÆčƒ½ć§ć™ć€‚é•·ć•ćÆ4ę–‡å­—ä»„äøŠ32ę–‡å­—ä»„äø‹ć§ć‚ć‚‹åæ…č¦ćŒć‚ć‚Šć¾ć™ć€‚" #: src/components/Prompt.tsx:91 -#: src/view/com/composer/Composer.tsx:300 -#: src/view/com/composer/Composer.tsx:305 +#: src/view/com/composer/Composer.tsx:307 +#: src/view/com/composer/Composer.tsx:312 #: src/view/com/modals/ChangeEmail.tsx:218 #: src/view/com/modals/ChangeEmail.tsx:220 #: src/view/com/modals/ChangePassword.tsx:265 @@ -556,7 +566,7 @@ msgstr "č‹±ę•°å­—ć€ć‚¹ćƒšćƒ¼ć‚¹ć€ćƒć‚¤ćƒ•ćƒ³ć€ć‚¢ćƒ³ćƒ€ćƒ¼ć‚¹ć‚³ć‚¢ć®ćæćŒ #: src/view/com/modals/VerifyEmail.tsx:247 #: src/view/com/modals/VerifyEmail.tsx:253 #: src/view/com/modals/Waitlist.tsx:142 -#: src/view/screens/Search/Search.tsx:693 +#: src/view/screens/Search/Search.tsx:716 #: src/view/shell/desktop/Search.tsx:238 msgid "Cancel" msgstr "ć‚­ćƒ£ćƒ³ć‚»ćƒ«" @@ -715,7 +725,7 @@ msgid "Clear all storage data (restart after this)" msgstr "ć™ć¹ć¦ć®ć‚¹ćƒˆćƒ¬ćƒ¼ć‚øćƒ‡ćƒ¼ć‚æć‚’ć‚ÆćƒŖć‚¢ļ¼ˆć“ć®å¾Œå†čµ·å‹•ć—ć¾ć™ļ¼‰" #: src/view/com/util/forms/SearchInput.tsx:88 -#: src/view/screens/Search/Search.tsx:674 +#: src/view/screens/Search/Search.tsx:697 msgid "Clear search query" msgstr "ę¤œē“¢ć‚Æć‚ØćƒŖć‚’ć‚ÆćƒŖć‚¢" @@ -723,6 +733,11 @@ msgstr "ę¤œē“¢ć‚Æć‚ØćƒŖć‚’ć‚ÆćƒŖć‚¢" msgid "click here" msgstr "ć“ć”ć‚‰ć‚’ć‚ÆćƒŖćƒƒć‚Æ" +#: src/components/RichText.tsx:189 +#: src/components/TagMenu/index.web.tsx:125 +msgid "Click here to open tag menu for {tag}" +msgstr "" + #: src/screens/Onboarding/index.tsx:35 msgid "Climate" msgstr "ę°—č±”" @@ -753,11 +768,15 @@ msgstr "ē”»åƒć‚’é–‰ć˜ć‚‹" msgid "Close image viewer" msgstr "ē”»åƒćƒ“ćƒ„ćƒ¼ć‚¢ć‚’é–‰ć˜ć‚‹" -#: src/view/shell/index.web.tsx:49 +#: src/view/shell/index.web.tsx:51 msgid "Close navigation footer" msgstr "ćƒŠćƒ“ć‚²ćƒ¼ć‚·ćƒ§ćƒ³ćƒ•ćƒƒć‚æćƒ¼ć‚’é–‰ć˜ć‚‹" -#: src/view/shell/index.web.tsx:50 +#: src/components/TagMenu/index.tsx:266 +msgid "Close this dialog" +msgstr "" + +#: src/view/shell/index.web.tsx:52 msgid "Closes bottom navigation bar" msgstr "äø‹éƒØć®ćƒŠćƒ“ć‚²ćƒ¼ć‚·ćƒ§ćƒ³ćƒćƒ¼ć‚’é–‰ć˜ć‚‹" @@ -765,7 +784,7 @@ msgstr "äø‹éƒØć®ćƒŠćƒ“ć‚²ćƒ¼ć‚·ćƒ§ćƒ³ćƒćƒ¼ć‚’é–‰ć˜ć‚‹" msgid "Closes password update alert" msgstr "ćƒ‘ć‚¹ćƒÆćƒ¼ćƒ‰ę›“ę–°ć‚¢ćƒ©ćƒ¼ćƒˆć‚’é–‰ć˜ć‚‹" -#: src/view/com/composer/Composer.tsx:302 +#: src/view/com/composer/Composer.tsx:309 msgid "Closes post composer and discards post draft" msgstr "ęŠ•ēØæć®ē·Øé›†ē”»é¢ć‚’é–‰ć˜ć€äø‹ę›øćć‚’å‰Šé™¤ć™ć‚‹" @@ -798,7 +817,7 @@ msgstr "åˆęœŸčØ­å®šć‚’å®Œäŗ†ć—ć¦ć‚¢ć‚«ć‚¦ćƒ³ćƒˆć‚’ä½æć„å§‹ć‚ć‚‹" msgid "Complete the challenge" msgstr "" -#: src/view/com/composer/Composer.tsx:417 +#: src/view/com/composer/Composer.tsx:424 msgid "Compose posts up to {MAX_GRAPHEME_LENGTH} characters in length" msgstr "{MAX_GRAPHEME_LENGTH}ę–‡å­—ć¾ć§ć®ęŠ•ēØæć‚’ä½œęˆ" @@ -862,7 +881,7 @@ msgstr "ęŽ„ē¶šäø­..." msgid "Contact support" msgstr "ć‚µćƒćƒ¼ćƒˆć«é€£ēµ”" -#: src/view/screens/Moderation.tsx:81 +#: src/view/screens/Moderation.tsx:83 msgid "Content filtering" msgstr "ć‚³ćƒ³ćƒ†ćƒ³ćƒ„ć®ćƒ•ć‚£ćƒ«ć‚æćƒŖćƒ³ć‚°" @@ -928,7 +947,7 @@ msgstr "ćƒ“ćƒ«ćƒ‰ćƒćƒ¼ć‚øćƒ§ćƒ³ć‚’ć‚ÆćƒŖćƒƒćƒ—ćƒœćƒ¼ćƒ‰ć«ć‚³ćƒ”ćƒ¼ć—ć¾ć—ćŸ #: src/view/com/modals/AddAppPasswords.tsx:76 #: src/view/com/modals/InviteCodes.tsx:152 -#: src/view/com/util/forms/PostDropdownBtn.tsx:141 +#: src/view/com/util/forms/PostDropdownBtn.tsx:143 msgid "Copied to clipboard" msgstr "ć‚ÆćƒŖćƒƒćƒ—ćƒœćƒ¼ćƒ‰ć«ć‚³ćƒ”ćƒ¼ć—ć¾ć—ćŸ" @@ -944,7 +963,7 @@ msgstr "ć‚³ćƒ”ćƒ¼" msgid "Copy link to list" msgstr "ćƒŖć‚¹ćƒˆćøć®ćƒŖćƒ³ć‚Æć‚’ć‚³ćƒ”ćƒ¼" -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 msgid "Copy link to post" msgstr "ęŠ•ēØæćøć®ćƒŖćƒ³ć‚Æć‚’ć‚³ćƒ”ćƒ¼" @@ -952,7 +971,7 @@ msgstr "ęŠ•ēØæćøć®ćƒŖćƒ³ć‚Æć‚’ć‚³ćƒ”ćƒ¼" msgid "Copy link to profile" msgstr "ćƒ—ćƒ­ćƒ•ć‚£ćƒ¼ćƒ«ćøć®ćƒŖćƒ³ć‚Æć‚’ć‚³ćƒ”ćƒ¼" -#: src/view/com/util/forms/PostDropdownBtn.tsx:168 +#: src/view/com/util/forms/PostDropdownBtn.tsx:170 msgid "Copy post text" msgstr "ęŠ•ēØæć®ćƒ†ć‚­ć‚¹ćƒˆć‚’ć‚³ćƒ”ćƒ¼" @@ -1008,7 +1027,7 @@ msgstr "ä½œęˆč€…ļ¼š<0/>" msgid "Created by you" msgstr "ä½œęˆč€…ļ¼šć‚ćŖćŸ" -#: src/view/com/composer/Composer.tsx:448 +#: src/view/com/composer/Composer.tsx:455 msgid "Creates a card with a thumbnail. The card links to {url}" msgstr "ć‚µćƒ ćƒć‚¤ćƒ«ä»˜ćć®ć‚«ćƒ¼ćƒ‰ć‚’ä½œęˆć—ć¾ć™ć€‚ćć®ć‚«ćƒ¼ćƒ‰ćÆę¬”ć®ć‚¢ćƒ‰ćƒ¬ć‚¹ćøćƒŖćƒ³ć‚Æć—ć¾ć™ļ¼š{url}" @@ -1089,11 +1108,11 @@ msgstr "ćƒžć‚¤ć‚¢ć‚«ć‚¦ćƒ³ćƒˆć‚’å‰Šé™¤" msgid "Delete My Account…" msgstr "ćƒžć‚¤ć‚¢ć‚«ć‚¦ćƒ³ćƒˆć‚’å‰Šé™¤ā€¦" -#: src/view/com/util/forms/PostDropdownBtn.tsx:257 +#: src/view/com/util/forms/PostDropdownBtn.tsx:273 msgid "Delete post" msgstr "ęŠ•ēØæć‚’å‰Šé™¤" -#: src/view/com/util/forms/PostDropdownBtn.tsx:261 +#: src/view/com/util/forms/PostDropdownBtn.tsx:277 msgid "Delete this post?" msgstr "ć“ć®ęŠ•ēØæć‚’å‰Šé™¤ć—ć¾ć™ć‹ļ¼Ÿ" @@ -1120,7 +1139,7 @@ msgstr "čŖ¬ę˜Ž" #~ msgid "Developer Tools" #~ msgstr "é–‹ē™ŗč€…ćƒ„ćƒ¼ćƒ«" -#: src/view/com/composer/Composer.tsx:211 +#: src/view/com/composer/Composer.tsx:218 msgid "Did you want to say anything?" msgstr "ćŖć«ć‹čØ€ć„ćŸć„ć“ćØćÆć‚ć£ćŸļ¼Ÿ" @@ -1128,15 +1147,15 @@ msgstr "ćŖć«ć‹čØ€ć„ćŸć„ć“ćØćÆć‚ć£ćŸļ¼Ÿ" msgid "Dim" msgstr "ć‚°ćƒ¬ćƒ¼" -#: src/view/com/composer/Composer.tsx:144 +#: src/view/com/composer/Composer.tsx:151 msgid "Discard" msgstr "砓棄" -#: src/view/com/composer/Composer.tsx:138 +#: src/view/com/composer/Composer.tsx:145 msgid "Discard draft" msgstr "äø‹ę›øćć‚’ē “ę£„" -#: src/view/screens/Moderation.tsx:207 +#: src/view/screens/Moderation.tsx:226 msgid "Discourage apps from showing my account to logged-out users" msgstr "ć‚¢ćƒ—ćƒŖćŒćƒ­ć‚°ć‚¢ć‚¦ćƒˆć—ćŸćƒ¦ćƒ¼ć‚¶ćƒ¼ć«č‡Ŗåˆ†ć®ć‚¢ć‚«ć‚¦ćƒ³ćƒˆć‚’č”Øē¤ŗć—ćŖć„ć‚ˆć†ć«ć™ć‚‹" @@ -1215,7 +1234,7 @@ msgstr "" msgid "Download CAR file" msgstr "" -#: src/view/com/composer/text-input/TextInput.web.tsx:247 +#: src/view/com/composer/text-input/TextInput.web.tsx:249 msgid "Drop to add images" msgstr "ćƒ‰ćƒ­ćƒƒćƒ—ć—ć¦ē”»åƒć‚’čæ½åŠ ć™ć‚‹" @@ -1287,6 +1306,7 @@ msgstr "ćƒ—ćƒ­ćƒ•ć‚£ćƒ¼ćƒ«ć‚’ē·Øé›†" msgid "Edit Profile" msgstr "ćƒ—ćƒ­ćƒ•ć‚£ćƒ¼ćƒ«ć‚’ē·Øé›†" +#: src/view/com/home/HomeHeaderLayout.web.tsx:59 #: src/view/screens/Feeds.tsx:355 msgid "Edit Saved Feeds" msgstr "äæå­˜ć•ć‚ŒćŸćƒ•ć‚£ćƒ¼ćƒ‰ć‚’ē·Øé›†" @@ -1369,6 +1389,11 @@ msgstr "ćƒ•ć‚£ćƒ¼ćƒ‰ć®ēµ‚ć‚ć‚Š" msgid "Enter a name for this App Password" msgstr "ć“ć®ć‚¢ćƒ—ćƒŖćƒ‘ć‚¹ćƒÆćƒ¼ćƒ‰ć®åå‰ć‚’å…„åŠ›" +#: src/components/dialogs/MutedWords.tsx:87 +#: src/components/dialogs/MutedWords.tsx:88 +msgid "Enter a word or tag" +msgstr "" + #: src/view/com/modals/VerifyEmail.tsx:105 msgid "Enter Confirmation Code" msgstr "ē¢ŗčŖć‚³ćƒ¼ćƒ‰ć‚’å…„åŠ›ć—ć¦ćć ć•ć„" @@ -1422,7 +1447,7 @@ msgstr "ćƒ¦ćƒ¼ć‚¶ćƒ¼åćØćƒ‘ć‚¹ćƒÆćƒ¼ćƒ‰ć‚’å…„åŠ›ć—ć¦ćć ć•ć„" msgid "Error receiving captcha response." msgstr "" -#: src/view/screens/Search/Search.tsx:109 +#: src/view/screens/Search/Search.tsx:110 msgid "Error:" msgstr "ć‚Øćƒ©ćƒ¼ļ¼š" @@ -1493,7 +1518,7 @@ msgstr "ć‚¢ćƒ—ćƒŖćƒ‘ć‚¹ćƒÆćƒ¼ćƒ‰ć®ä½œęˆć«å¤±ę•—ć—ć¾ć—ćŸć€‚" msgid "Failed to create the list. Check your internet connection and try again." msgstr "ćƒŖć‚¹ćƒˆć®ä½œęˆć«å¤±ę•—ć—ć¾ć—ćŸć€‚ć‚¤ćƒ³ć‚æćƒ¼ćƒćƒƒćƒˆćøć®ęŽ„ē¶šć‚’ē¢ŗčŖć®äøŠć€ć‚‚ć†äø€åŗ¦ćŠč©¦ć—ćć ć•ć„ć€‚" -#: src/view/com/util/forms/PostDropdownBtn.tsx:108 +#: src/view/com/util/forms/PostDropdownBtn.tsx:110 msgid "Failed to delete post, please try again" msgstr "ęŠ•ēØæć®å‰Šé™¤ć«å¤±ę•—ć—ć¾ć—ćŸć€‚ć‚‚ć†äø€åŗ¦ćŠč©¦ć—ćć ć•ć„ć€‚" @@ -1515,8 +1540,8 @@ msgid "Feed offline" msgstr "ćƒ•ć‚£ćƒ¼ćƒ‰ćÆć‚Ŗćƒ•ćƒ©ć‚¤ćƒ³ć§ć™" #: src/view/com/feeds/FeedPage.tsx:143 -msgid "Feed Preferences" -msgstr "ćƒ•ć‚£ćƒ¼ćƒ‰ć®čØ­å®š" +#~ msgid "Feed Preferences" +#~ msgstr "ćƒ•ć‚£ćƒ¼ćƒ‰ć®čØ­å®š" #: src/view/shell/desktop/RightNav.tsx:61 #: src/view/shell/Drawer.tsx:311 @@ -1564,11 +1589,11 @@ msgstr "ęœ€å¾Œć«" msgid "Find accounts to follow" msgstr "ćƒ•ć‚©ćƒ­ćƒ¼ć™ć‚‹ć‚¢ć‚«ć‚¦ćƒ³ćƒˆć‚’ęŽ¢ć™" -#: src/view/screens/Search/Search.tsx:439 +#: src/view/screens/Search/Search.tsx:440 msgid "Find users on Bluesky" msgstr "Blueskyć§ćƒ¦ćƒ¼ć‚¶ćƒ¼ć‚’ę¤œē“¢" -#: src/view/screens/Search/Search.tsx:437 +#: src/view/screens/Search/Search.tsx:438 msgid "Find users with the search tool on the right" msgstr "å³å“ć®ę¤œē“¢ćƒ„ćƒ¼ćƒ«ć§ćƒ¦ćƒ¼ć‚¶ćƒ¼ć‚’ę¤œē“¢" @@ -1673,6 +1698,7 @@ msgid "Following {0}" msgstr "{0}ć‚’ćƒ•ć‚©ćƒ­ćƒ¼ć—ć¦ć„ć¾ć™" #: src/Navigation.tsx:248 +#: src/view/com/home/HomeHeaderLayout.web.tsx:45 #: src/view/com/home/HomeHeaderLayoutMobile.tsx:83 #: src/view/screens/PreferencesFollowingFeed.tsx:104 #: src/view/screens/Settings/index.tsx:543 @@ -1712,7 +1738,7 @@ msgstr "ćƒ‘ć‚¹ćƒÆćƒ¼ćƒ‰ć‚’åæ˜ć‚ŒćŸ" msgid "Forgot Password" msgstr "ćƒ‘ć‚¹ćƒÆćƒ¼ćƒ‰ć‚’åæ˜ć‚ŒćŸ" -#: src/view/com/posts/FeedItem.tsx:187 +#: src/view/com/posts/FeedItem.tsx:189 msgctxt "from-feed" msgid "From <0/>" msgstr "<0/>恋悉" @@ -1745,7 +1771,7 @@ msgstr "ęˆ»ć‚‹" msgid "Go back to previous step" msgstr "å‰ć®ć‚¹ćƒ†ćƒƒćƒ—ć«ęˆ»ć‚‹" -#: src/view/screens/Search/Search.tsx:724 +#: src/view/screens/Search/Search.tsx:747 #: src/view/shell/desktop/Search.tsx:262 msgid "Go to @{queryMaybeHandle}" msgstr "@{queryMaybeHandle}へ" @@ -1762,6 +1788,10 @@ msgstr "欔へ" msgid "Handle" msgstr "ćƒćƒ³ćƒ‰ćƒ«" +#: src/components/RichText.tsx:188 +msgid "Hashtag: {tag}" +msgstr "" + #: src/view/com/auth/create/CreateAccount.tsx:208 msgid "Having trouble?" msgstr "ä½•ć‹å•é”ŒćŒē™ŗē”Ÿć—ć¾ć—ćŸć‹ļ¼Ÿ" @@ -1804,7 +1834,7 @@ msgctxt "action" msgid "Hide" msgstr "éžč”Øē¤ŗ" -#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +#: src/view/com/util/forms/PostDropdownBtn.tsx:232 msgid "Hide post" msgstr "ęŠ•ēØæć‚’éžč”Øē¤ŗ" @@ -1813,7 +1843,7 @@ msgstr "ęŠ•ēØæć‚’éžč”Øē¤ŗ" msgid "Hide the content" msgstr "ć‚³ćƒ³ćƒ†ćƒ³ćƒ„ć‚’éžč”Øē¤ŗ" -#: src/view/com/util/forms/PostDropdownBtn.tsx:220 +#: src/view/com/util/forms/PostDropdownBtn.tsx:236 msgid "Hide this post?" msgstr "ć“ć®ęŠ•ēØæć‚’éžč”Øē¤ŗć«ć—ć¾ć™ć‹ļ¼Ÿ" @@ -1975,7 +2005,7 @@ msgstr "ć‚ćŖćŸć®ćƒ‘ć‚¹ćƒÆćƒ¼ćƒ‰ć‚’å…„åŠ›" msgid "Input your user handle" msgstr "ć‚ćŖćŸć®ćƒ¦ćƒ¼ć‚¶ćƒ¼ćƒćƒ³ćƒ‰ćƒ«ć‚’å…„åŠ›" -#: src/view/com/post-thread/PostThreadItem.tsx:224 +#: src/view/com/post-thread/PostThreadItem.tsx:226 msgid "Invalid or unsupported post record" msgstr "ē„”åŠ¹ć¾ćŸćÆć‚µćƒćƒ¼ćƒˆć•ć‚Œć¦ć„ćŖć„ęŠ•ēØæć®ćƒ¬ć‚³ćƒ¼ćƒ‰" @@ -2077,7 +2107,7 @@ msgstr "詳瓰" msgid "Learn more about this warning" msgstr "ć“ć®č­¦å‘Šć®č©³ē“°" -#: src/view/screens/Moderation.tsx:243 +#: src/view/screens/Moderation.tsx:262 msgid "Learn more about what is public on Bluesky." msgstr "Blueskyć§å…¬é–‹ć•ć‚Œć¦ć„ć‚‹å†…å®¹ćÆć“ć”ć‚‰ć‚’å‚ē…§ć—ć¦ćć ć•ć„ć€‚" @@ -2161,7 +2191,7 @@ msgstr "ć‚ćŖćŸć®ęŠ•ēØæćŒć„ć„ć­ć•ć‚Œć¾ć—ćŸ" msgid "Likes" msgstr "恄恄恭" -#: src/view/com/post-thread/PostThreadItem.tsx:181 +#: src/view/com/post-thread/PostThreadItem.tsx:183 msgid "Likes on this post" msgstr "ć“ć®ęŠ•ēØæć‚’ć„ć„ć­ć™ć‚‹" @@ -2222,7 +2252,7 @@ msgstr "ęŠ•ēØæć‚’ć•ć‚‰ć«ćƒ­ćƒ¼ćƒ‰" msgid "Load new notifications" msgstr "ęœ€ę–°ć®é€šēŸ„ć‚’ćƒ­ćƒ¼ćƒ‰" -#: src/view/com/feeds/FeedPage.tsx:181 +#: src/view/com/feeds/FeedPage.tsx:115 #: src/view/screens/Profile.tsx:440 #: src/view/screens/ProfileFeed.tsx:495 #: src/view/screens/ProfileList.tsx:681 @@ -2252,7 +2282,7 @@ msgstr "ćƒ­ć‚°ć‚¢ć‚¦ćƒˆ" #~ msgid "Logged-out users" #~ msgstr "ćƒ­ć‚°ć‚¢ć‚¦ćƒˆć—ćŸćƒ¦ćƒ¼ć‚¶ćƒ¼" -#: src/view/screens/Moderation.tsx:136 +#: src/view/screens/Moderation.tsx:155 msgid "Logged-out visibility" msgstr "ćƒ­ć‚°ć‚¢ć‚¦ćƒˆć—ćŸćƒ¦ćƒ¼ć‚¶ćƒ¼ć‹ć‚‰ć®åÆč¦–ę€§" @@ -2268,6 +2298,10 @@ msgstr "ćƒŖć‚¹ćƒˆć«ćŖć„ć‚¢ć‚«ć‚¦ćƒ³ćƒˆć«ćƒ­ć‚°ć‚¤ćƒ³" msgid "Make sure this is where you intend to go!" msgstr "ę„å›³ć—ćŸå “ę‰€ć§ć‚ć‚‹ć“ćØć‚’ē¢ŗčŖć—ć¦ćć ć•ć„ļ¼" +#: src/components/dialogs/MutedWords.tsx:71 +msgid "Manage your muted words and tags" +msgstr "" + #: src/view/com/auth/create/Step2.tsx:118 msgid "May not be longer than 253 characters" msgstr "" @@ -2289,7 +2323,7 @@ msgid "Mentioned users" msgstr "ćƒ”ćƒ³ć‚·ćƒ§ćƒ³ć•ć‚ŒćŸćƒ¦ćƒ¼ć‚¶ćƒ¼" #: src/view/com/util/ViewHeader.tsx:81 -#: src/view/screens/Search/Search.tsx:623 +#: src/view/screens/Search/Search.tsx:646 msgid "Menu" msgstr "ćƒ”ćƒ‹ćƒ„ćƒ¼" @@ -2302,7 +2336,7 @@ msgid "Message from server: {0}" msgstr "ć‚µćƒ¼ćƒćƒ¼ć‹ć‚‰ć®ćƒ”ćƒƒć‚»ćƒ¼ć‚øļ¼š{0}" #: src/Navigation.tsx:115 -#: src/view/screens/Moderation.tsx:64 +#: src/view/screens/Moderation.tsx:66 #: src/view/screens/Settings/index.tsx:625 #: src/view/shell/desktop/LeftNav.tsx:397 #: src/view/shell/Drawer.tsx:511 @@ -2333,7 +2367,7 @@ msgstr "ćƒ¢ćƒ‡ćƒ¬ćƒ¼ć‚·ćƒ§ćƒ³ćƒŖć‚¹ćƒˆć‚’ä½œęˆć—ć¾ć—ćŸ" msgid "Moderation list updated" msgstr "ćƒ¢ćƒ‡ćƒ¬ćƒ¼ć‚·ćƒ§ćƒ³ćƒŖć‚¹ćƒˆć‚’ę›“ę–°ć—ć¾ć—ćŸ" -#: src/view/screens/Moderation.tsx:95 +#: src/view/screens/Moderation.tsx:114 msgid "Moderation lists" msgstr "ćƒ¢ćƒ‡ćƒ¬ćƒ¼ć‚·ćƒ§ćƒ³ćƒŖć‚¹ćƒˆ" @@ -2360,7 +2394,7 @@ msgstr "ćć®ä»–ć®ćƒ•ć‚£ćƒ¼ćƒ‰" msgid "More options" msgstr "ćć®ä»–ć®ć‚Ŗćƒ—ć‚·ćƒ§ćƒ³" -#: src/view/com/util/forms/PostDropdownBtn.tsx:299 +#: src/view/com/util/forms/PostDropdownBtn.tsx:315 msgid "More post options" msgstr "ćć®ć»ć‹ć®ęŠ•ēØæć®ć‚Ŗćƒ—ć‚·ćƒ§ćƒ³" @@ -2372,6 +2406,14 @@ msgstr "ć„ć„ć­ć®ę•°ćŒå¤šć„é †ć«čæ”äæ”ć‚’č”Øē¤ŗ" msgid "Must be at least 3 characters" msgstr "" +#: src/components/TagMenu/index.tsx:253 +msgid "Mute" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:91 +msgid "Mute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:327 msgid "Mute Account" msgstr "ć‚¢ć‚«ć‚¦ćƒ³ćƒˆć‚’ćƒŸćƒ„ćƒ¼ćƒˆ" @@ -2380,6 +2422,18 @@ msgstr "ć‚¢ć‚«ć‚¦ćƒ³ćƒˆć‚’ćƒŸćƒ„ćƒ¼ćƒˆ" msgid "Mute accounts" msgstr "ć‚¢ć‚«ć‚¦ćƒ³ćƒˆć‚’ćƒŸćƒ„ćƒ¼ćƒˆ" +#: src/components/TagMenu/index.tsx:211 +msgid "Mute all {tag} posts" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:131 +msgid "Mute in tags only" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:116 +msgid "Mute in text & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:491 msgid "Mute list" msgstr "ćƒŖć‚¹ćƒˆć‚’ćƒŸćƒ„ćƒ¼ćƒˆ" @@ -2392,15 +2446,27 @@ msgstr "ć“ć‚Œć‚‰ć®ć‚¢ć‚«ć‚¦ćƒ³ćƒˆć‚’ćƒŸćƒ„ćƒ¼ćƒˆć—ć¾ć™ć‹ļ¼Ÿ" msgid "Mute this List" msgstr "ć“ć®ćƒŖć‚¹ćƒˆć‚’ćƒŸćƒ„ćƒ¼ćƒˆ" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/dialogs/MutedWords.tsx:109 +msgid "Mute this word in post text and tags" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:124 +msgid "Mute this word in tags only" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Mute thread" msgstr "ć‚¹ćƒ¬ćƒƒćƒ‰ć‚’ćƒŸćƒ„ćƒ¼ćƒˆ" +#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +msgid "Mute words & tags" +msgstr "" + #: src/view/com/lists/ListCard.tsx:102 msgid "Muted" msgstr "ćƒŸćƒ„ćƒ¼ćƒˆć•ć‚Œć¦ć„ć¾ć™" -#: src/view/screens/Moderation.tsx:109 +#: src/view/screens/Moderation.tsx:128 msgid "Muted accounts" msgstr "ćƒŸćƒ„ćƒ¼ćƒˆäø­ć®ć‚¢ć‚«ć‚¦ćƒ³ćƒˆ" @@ -2413,6 +2479,10 @@ msgstr "ćƒŸćƒ„ćƒ¼ćƒˆäø­ć®ć‚¢ć‚«ć‚¦ćƒ³ćƒˆ" msgid "Muted accounts have their posts removed from your feed and from your notifications. Mutes are completely private." msgstr "ćƒŸćƒ„ćƒ¼ćƒˆäø­ć®ć‚¢ć‚«ć‚¦ćƒ³ćƒˆć®ęŠ•ēØæćÆć€ćƒ•ć‚£ćƒ¼ćƒ‰ć‚„é€šēŸ„ć‹ć‚‰å–ć‚Šé™¤ć‹ć‚Œć¾ć™ć€‚ćƒŸćƒ„ćƒ¼ćƒˆć®čØ­å®šćÆå®Œå…Øć«éžå…¬é–‹ć§ć™ć€‚" +#: src/view/screens/Moderation.tsx:100 +msgid "Muted words & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:277 msgid "Muting is private. Muted accounts can interact with you, but you will not see their posts or receive notifications from them." msgstr "ćƒŸćƒ„ćƒ¼ćƒˆć®čØ­å®šćÆéžå…¬é–‹ć§ć™ć€‚ćƒŸćƒ„ćƒ¼ćƒˆäø­ć®ć‚¢ć‚«ć‚¦ćƒ³ćƒˆćÆć‚ćŖćŸćØå¼•ćē¶šćé–¢ć‚ć‚‹ć“ćØćŒć§ćć¾ć™ćŒć€ćć®ć‚¢ć‚«ć‚¦ćƒ³ćƒˆć®ęŠ•ēØæć‚„é€šēŸ„ć‚’å—äæ”ć™ć‚‹ć“ćØćÆć§ćć¾ć›ć‚“ć€‚" @@ -2476,6 +2546,10 @@ msgstr "ćƒ•ć‚©ćƒ­ćƒÆćƒ¼ć‚„ćƒ‡ćƒ¼ć‚æćøć®ć‚¢ć‚Æć‚»ć‚¹ć‚’å¤±ć†ć“ćØćÆć‚ć‚Šć¾ msgid "Never lose access to your followers or data." msgstr "ćƒ•ć‚©ćƒ­ćƒÆćƒ¼ć‚„ćƒ‡ćƒ¼ć‚æćøć®ć‚¢ć‚Æć‚»ć‚¹ć‚’å¤±ć†ć“ćØćÆć‚ć‚Šć¾ć›ć‚“ć€‚" +#: src/components/dialogs/MutedWords.tsx:244 +msgid "Nevermind" +msgstr "" + #: src/view/screens/Lists.tsx:76 msgctxt "action" msgid "New" @@ -2497,7 +2571,7 @@ msgstr "ę–°ć—ć„ćƒ‘ć‚¹ćƒÆćƒ¼ćƒ‰" msgid "New Password" msgstr "ę–°ć—ć„ćƒ‘ć‚¹ćƒÆćƒ¼ćƒ‰" -#: src/view/com/feeds/FeedPage.tsx:192 +#: src/view/com/feeds/FeedPage.tsx:126 msgctxt "action" msgid "New post" msgstr "ę–°ć—ć„ęŠ•ēØæ" @@ -2586,8 +2660,8 @@ msgid "No results found for \"{query}\"" msgstr "怌{query}ć€ć®ę¤œē“¢ēµęžœćÆć‚ć‚Šć¾ć›ć‚“" #: src/view/com/modals/ListAddRemoveUsers.tsx:127 -#: src/view/screens/Search/Search.tsx:280 -#: src/view/screens/Search/Search.tsx:308 +#: src/view/screens/Search/Search.tsx:281 +#: src/view/screens/Search/Search.tsx:309 msgid "No results found for {query}" msgstr "怌{query}ć€ć®ę¤œē“¢ēµęžœćÆć‚ć‚Šć¾ć›ć‚“" @@ -2617,7 +2691,7 @@ msgstr "ä»ŠćÆć—ćŖć„" #~ msgid "Note: Bluesky is an open and public network, and enabling this will not make your profile private or limit the ability of logged in users to see your posts. This setting only limits the visibility of posts on the Bluesky app and website; third-party apps that display Bluesky content may not respect this setting, and could show your content to logged-out users." #~ msgstr "注記:BlueskyćÆć‚Ŗćƒ¼ćƒ—ćƒ³ć§ćƒ‘ćƒ–ćƒŖćƒƒć‚ÆćŖćƒćƒƒćƒˆćƒÆćƒ¼ć‚Æć§ć‚ć‚Šć€ć“ć®čØ­å®šć‚’ęœ‰åŠ¹ć«ć—ć¦ć‚‚ćƒ­ć‚°ć‚¤ćƒ³ć—ć¦ć„ć‚‹ćƒ¦ćƒ¼ć‚¶ćƒ¼ćÆć‚ćŖćŸć®ćƒ—ćƒ­ćƒ•ć‚£ćƒ¼ćƒ«ć‚„ęŠ•ēØæć‚’åˆ¶é™ćŖćé–²č¦§ć§ćć¾ć™ć€‚ć“ć®čØ­å®šćÆBlueskyć®ć‚¢ćƒ—ćƒŖćŠć‚ˆć³ć‚¦ć‚§ćƒ–ć‚µć‚¤ćƒˆäøŠć®ćæć§ć®ć‚ćŖćŸć®ć‚³ćƒ³ćƒ†ćƒ³ćƒ„ć®åÆč¦–ę€§ć‚’åˆ¶é™ć™ć‚‹ć‚‚ć®ć§ć™ć€‚Blueskyć®ć‚³ćƒ³ćƒ†ćƒ³ćƒ„ć‚’č”Øē¤ŗć™ć‚‹ć‚µćƒ¼ćƒ‰ćƒ‘ćƒ¼ćƒ†ć‚£ćƒ¼ć®ć‚¢ćƒ—ćƒŖć‚„ć‚¦ć‚§ćƒ–ć‚µć‚¤ćƒˆćŖć©ćÆć“ć®čØ­å®šć‚’å°Šé‡ć—ćŖć„å “åˆćŒć‚ć‚Šć€ćƒ­ć‚°ć‚¢ć‚¦ćƒˆć—ćŸćƒ¦ćƒ¼ć‚¶ćƒ¼ć«åÆ¾ć—ć‚ćŖćŸć®ć‚³ćƒ³ćƒ†ćƒ³ćƒ„ćŒč”Øē¤ŗć•ć‚Œć‚‹åÆčƒ½ę€§ćŒć‚ć‚Šć¾ć™ć€‚" -#: src/view/screens/Moderation.tsx:233 +#: src/view/screens/Moderation.tsx:252 msgid "Note: Bluesky is an open and public network. This setting only limits the visibility of your content on the Bluesky app and website, and other apps may not respect this setting. Your content may still be shown to logged-out users by other apps and websites." msgstr "注記:BlueskyćÆć‚Ŗćƒ¼ćƒ—ćƒ³ć§ćƒ‘ćƒ–ćƒŖćƒƒć‚ÆćŖćƒćƒƒćƒˆćƒÆćƒ¼ć‚Æć§ć™ć€‚ć“ć®čØ­å®šćÆBlueskyć®ć‚¢ćƒ—ćƒŖćŠć‚ˆć³ć‚¦ć‚§ćƒ–ć‚µć‚¤ćƒˆäøŠć®ćæć§ć®ć‚ćŖćŸć®ć‚³ćƒ³ćƒ†ćƒ³ćƒ„ć®åÆč¦–ę€§ć‚’åˆ¶é™ć™ć‚‹ć‚‚ć®ć§ć‚ć‚Šć€ä»–ć®ć‚¢ćƒ—ćƒŖć§ćÆć“ć®čØ­å®šć‚’å°Šé‡ć—ćŖć„å “åˆćŒć‚ć‚Šć¾ć™ć€‚ä»–ć®ć‚¢ćƒ—ćƒŖć‚„ć‚¦ć‚§ćƒ–ć‚µć‚¤ćƒˆć§ćÆć€ćƒ­ć‚°ć‚¢ć‚¦ćƒˆć—ćŸćƒ¦ćƒ¼ć‚¶ćƒ¼ć«ć‚ćŖćŸć®ć‚³ćƒ³ćƒ†ćƒ³ćƒ„ćŒč”Øē¤ŗć•ć‚Œć‚‹å “åˆćŒć‚ć‚Šć¾ć™ć€‚" @@ -2655,7 +2729,7 @@ msgstr "å¤ć„é †ć«čæ”äæ”ć‚’č”Øē¤ŗ" msgid "Onboarding reset" msgstr "ć‚Ŗćƒ³ćƒœćƒ¼ćƒ‡ć‚£ćƒ³ć‚°ć®ćƒŖć‚»ćƒƒćƒˆ" -#: src/view/com/composer/Composer.tsx:375 +#: src/view/com/composer/Composer.tsx:382 msgid "One or more images is missing alt text." msgstr "1ć¤ć‚‚ć—ććÆč¤‡ę•°ć®ē”»åƒć«ALTćƒ†ć‚­ć‚¹ćƒˆćŒć‚ć‚Šć¾ć›ć‚“ć€‚" @@ -2672,8 +2746,12 @@ msgstr "おっと!" msgid "Open" msgstr "é–‹ć‹ć‚Œć¦ć„ć¾ć™" -#: src/view/com/composer/Composer.tsx:470 -#: src/view/com/composer/Composer.tsx:471 +#: src/view/screens/Moderation.tsx:75 +msgid "Open content filtering settings" +msgstr "" + +#: src/view/com/composer/Composer.tsx:477 +#: src/view/com/composer/Composer.tsx:478 msgid "Open emoji picker" msgstr "ēµµę–‡å­—ć‚’å…„åŠ›" @@ -2681,6 +2759,10 @@ msgstr "ēµµę–‡å­—ć‚’å…„åŠ›" msgid "Open links with in-app browser" msgstr "ć‚¢ćƒ—ćƒŖå†…ćƒ–ćƒ©ć‚¦ć‚¶ćƒ¼ć§ćƒŖćƒ³ć‚Æć‚’é–‹ć" +#: src/view/screens/Moderation.tsx:92 +msgid "Open muted words settings" +msgstr "" + #: src/view/com/home/HomeHeaderLayoutMobile.tsx:49 msgid "Open navigation" msgstr "ćƒŠćƒ“ć‚²ćƒ¼ć‚·ćƒ§ćƒ³ć‚’é–‹ć" @@ -2757,6 +2839,7 @@ msgstr "ćƒ¢ćƒ‡ćƒ¬ćƒ¼ć‚·ćƒ§ćƒ³ć®čØ­å®šć‚’é–‹ć" msgid "Opens password reset form" msgstr "ćƒ‘ć‚¹ćƒÆćƒ¼ćƒ‰ćƒŖć‚»ćƒƒćƒˆć®ćƒ•ć‚©ćƒ¼ćƒ ć‚’é–‹ć" +#: src/view/com/home/HomeHeaderLayout.web.tsx:60 #: src/view/screens/Feeds.tsx:356 msgid "Opens screen to edit Saved Feeds" msgstr "äæå­˜ć•ć‚ŒćŸćƒ•ć‚£ćƒ¼ćƒ‰ć®ē·Øé›†ē”»é¢ć‚’é–‹ć" @@ -2941,7 +3024,7 @@ msgstr "ć“ć®ć‚³ćƒ³ćƒ†ćƒ³ćƒ„ć«åÆ¾ć™ć‚‹č­¦å‘ŠćŒčŖ¤ć£ć¦é©ē”Øć•ć‚ŒćŸćØę€ msgid "Please Verify Your Email" msgstr "ćƒ”ćƒ¼ćƒ«ć‚¢ćƒ‰ćƒ¬ć‚¹ć‚’ē¢ŗčŖć—ć¦ćć ć•ć„" -#: src/view/com/composer/Composer.tsx:215 +#: src/view/com/composer/Composer.tsx:222 msgid "Please wait for your link card to finish loading" msgstr "ćƒŖćƒ³ć‚Æć‚«ćƒ¼ćƒ‰ćŒćƒ­ćƒ¼ćƒ‰ć•ć‚Œć‚‹ć¾ć§ćŠå¾…ć”ćć ć•ć„" @@ -2953,8 +3036,8 @@ msgstr "政治" msgid "Porn" msgstr "ćƒćƒ«ćƒŽ" -#: src/view/com/composer/Composer.tsx:350 -#: src/view/com/composer/Composer.tsx:358 +#: src/view/com/composer/Composer.tsx:357 +#: src/view/com/composer/Composer.tsx:365 msgctxt "action" msgid "Post" msgstr "ęŠ•ēØæ" @@ -2970,7 +3053,7 @@ msgstr "ęŠ•ēØæ" #~ msgid "Post" #~ msgstr "ęŠ•ēØæ" -#: src/view/com/post-thread/PostThreadItem.tsx:173 +#: src/view/com/post-thread/PostThreadItem.tsx:175 msgid "Post by {0}" msgstr "{0}ć«ć‚ˆć‚‹ęŠ•ēØæ" @@ -2980,11 +3063,11 @@ msgstr "{0}ć«ć‚ˆć‚‹ęŠ•ēØæ" msgid "Post by @{0}" msgstr "@{0}ć«ć‚ˆć‚‹ęŠ•ēØæ" -#: src/view/com/util/forms/PostDropdownBtn.tsx:88 +#: src/view/com/util/forms/PostDropdownBtn.tsx:90 msgid "Post deleted" msgstr "ęŠ•ēØæć‚’å‰Šé™¤" -#: src/view/com/post-thread/PostThread.tsx:461 +#: src/view/com/post-thread/PostThread.tsx:462 msgid "Post hidden" msgstr "ęŠ•ēØæć‚’éžč”Øē¤ŗ" @@ -2996,14 +3079,22 @@ msgstr "ęŠ•ēØæć®čØ€čŖž" msgid "Post Languages" msgstr "ęŠ•ēØæć®čØ€čŖž" -#: src/view/com/post-thread/PostThread.tsx:513 +#: src/view/com/post-thread/PostThread.tsx:514 msgid "Post not found" msgstr "ęŠ•ēØæćŒč¦‹ć¤ć‹ć‚Šć¾ć›ć‚“" +#: src/components/TagMenu/index.tsx:257 +msgid "posts" +msgstr "" + #: src/view/screens/Profile.tsx:180 msgid "Posts" msgstr "ęŠ•ēØæ" +#: src/components/dialogs/MutedWords.tsx:77 +msgid "Posts can be muted based on their text, their tags, or both." +msgstr "" + #: src/view/com/posts/FeedErrorMessage.tsx:64 msgid "Posts hidden" msgstr "éžč”Øē¤ŗć®ęŠ•ēØæ" @@ -3068,11 +3159,11 @@ msgstr "ćƒ¦ćƒ¼ć‚¶ćƒ¼ć‚’äø€ę‹¬ć§ćƒŸćƒ„ćƒ¼ćƒˆć¾ćŸćÆćƒ–ćƒ­ćƒƒć‚Æć™ć‚‹ć€å…¬é–‹ msgid "Public, shareable lists which can drive feeds." msgstr "ćƒ•ć‚£ćƒ¼ćƒ‰ćØć—ć¦åˆ©ē”Øć§ćć‚‹ć€å…¬é–‹ć•ć‚ŒćŸå…±ęœ‰åÆčƒ½ćŖćƒŖć‚¹ćƒˆć€‚" -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish post" msgstr "ęŠ•ēØæć‚’å…¬é–‹" -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish reply" msgstr "返俔を公開" @@ -3110,6 +3201,7 @@ msgstr "ćŠć™ć™ć‚ć®ćƒ•ć‚£ćƒ¼ćƒ‰" msgid "Recommended Users" msgstr "ćŠć™ć™ć‚ć®ćƒ¦ćƒ¼ć‚¶ćƒ¼" +#: src/components/dialogs/MutedWords.tsx:249 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/SelfLabel.tsx:83 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -3147,6 +3239,10 @@ msgstr "ć‚¤ćƒ”ćƒ¼ć‚øć‚’å‰Šé™¤" msgid "Remove image preview" msgstr "ć‚¤ćƒ”ćƒ¼ć‚øćƒ—ćƒ¬ćƒ“ćƒ„ćƒ¼ć‚’å‰Šé™¤" +#: src/components/dialogs/MutedWords.tsx:294 +msgid "Remove mute word from your list" +msgstr "" + #: src/view/com/modals/Repost.tsx:47 msgid "Remove repost" msgstr "ćƒŖćƒć‚¹ćƒˆć‚’å‰Šé™¤" @@ -3181,7 +3277,7 @@ msgstr "返俔" msgid "Replies to this thread are disabled" msgstr "ć“ć®ć‚¹ćƒ¬ćƒƒćƒ‰ćøć®čæ”äæ”ćÆć§ćć¾ć›ć‚“" -#: src/view/com/composer/Composer.tsx:348 +#: src/view/com/composer/Composer.tsx:355 msgctxt "action" msgid "Reply" msgstr "返俔" @@ -3191,7 +3287,7 @@ msgid "Reply Filters" msgstr "čæ”äæ”ć®ćƒ•ć‚£ćƒ«ć‚æćƒ¼" #: src/view/com/post/Post.tsx:167 -#: src/view/com/posts/FeedItem.tsx:285 +#: src/view/com/posts/FeedItem.tsx:287 msgctxt "description" msgid "Reply to <0/>" msgstr "<0/>に返俔" @@ -3213,7 +3309,7 @@ msgid "Report List" msgstr "ćƒŖć‚¹ćƒˆć‚’å ±å‘Š" #: src/view/com/modals/report/SendReportButton.tsx:37 -#: src/view/com/util/forms/PostDropdownBtn.tsx:239 +#: src/view/com/util/forms/PostDropdownBtn.tsx:255 msgid "Report post" msgstr "ęŠ•ēØæć‚’å ±å‘Š" @@ -3242,7 +3338,7 @@ msgstr "ćƒŖćƒć‚¹ćƒˆć¾ćŸćÆå¼•ē”Ø" msgid "Reposted By" msgstr "ćƒŖćƒć‚¹ćƒˆć—ćŸćƒ¦ćƒ¼ć‚¶ćƒ¼" -#: src/view/com/posts/FeedItem.tsx:205 +#: src/view/com/posts/FeedItem.tsx:207 msgid "Reposted by {0}" msgstr "{0}ć«ćƒŖćƒć‚¹ćƒˆć•ć‚ŒćŸ" @@ -3250,7 +3346,7 @@ msgstr "{0}ć«ćƒŖćƒć‚¹ćƒˆć•ć‚ŒćŸ" #~ msgid "Reposted by {0})" #~ msgstr "{0}ć«ć‚ˆć‚‹ćƒŖćƒć‚¹ćƒˆ" -#: src/view/com/posts/FeedItem.tsx:222 +#: src/view/com/posts/FeedItem.tsx:224 msgid "Reposted by <0/>" msgstr "<0/>ć«ć‚ˆć‚‹ćƒŖćƒć‚¹ćƒˆ" @@ -3258,7 +3354,7 @@ msgstr "<0/>ć«ć‚ˆć‚‹ćƒŖćƒć‚¹ćƒˆ" msgid "reposted your post" msgstr "ć‚ćŖćŸć®ęŠ•ēØæćÆćƒŖćƒć‚¹ćƒˆć•ć‚Œć¾ć—ćŸ" -#: src/view/com/post-thread/PostThreadItem.tsx:186 +#: src/view/com/post-thread/PostThreadItem.tsx:188 msgid "Reposts of this post" msgstr "ć“ć®ęŠ•ēØæć‚’ćƒŖćƒć‚¹ćƒˆ" @@ -3409,9 +3505,9 @@ msgstr "äø€ē•ŖäøŠć¾ć§ć‚¹ć‚Æćƒ­ćƒ¼ćƒ«" #: src/view/com/modals/ListAddRemoveUsers.tsx:75 #: src/view/com/util/forms/SearchInput.tsx:67 #: src/view/com/util/forms/SearchInput.tsx:79 -#: src/view/screens/Search/Search.tsx:418 -#: src/view/screens/Search/Search.tsx:645 -#: src/view/screens/Search/Search.tsx:663 +#: src/view/screens/Search/Search.tsx:419 +#: src/view/screens/Search/Search.tsx:668 +#: src/view/screens/Search/Search.tsx:686 #: src/view/shell/bottom-bar/BottomBar.tsx:159 #: src/view/shell/desktop/LeftNav.tsx:324 #: src/view/shell/desktop/Search.tsx:214 @@ -3421,11 +3517,19 @@ msgstr "äø€ē•ŖäøŠć¾ć§ć‚¹ć‚Æćƒ­ćƒ¼ćƒ«" msgid "Search" msgstr "検瓢" -#: src/view/screens/Search/Search.tsx:712 +#: src/view/screens/Search/Search.tsx:735 #: src/view/shell/desktop/Search.tsx:255 msgid "Search for \"{query}\"" msgstr "怌{query}ć€ć‚’ę¤œē“¢" +#: src/components/TagMenu/index.tsx:145 +msgid "Search for all posts by @{authorHandle} with tag {tag}" +msgstr "" + +#: src/components/TagMenu/index.tsx:90 +msgid "Search for all posts with tag {tag}" +msgstr "" + #: src/view/screens/Search/Search.tsx:390 #~ msgid "Search for posts and users." #~ msgstr "ęŠ•ēØæćØćƒ¦ćƒ¼ć‚¶ćƒ¼ć‚’ę¤œē“¢ć—ć¾ć™ć€‚" @@ -3440,6 +3544,22 @@ msgstr "ćƒ¦ćƒ¼ć‚¶ćƒ¼ć‚’ę¤œē“¢" msgid "Security Step Required" msgstr "åæ…č¦ćŖć‚»ć‚­ćƒ„ćƒŖćƒ†ć‚£ć®ę‰‹é †" +#: src/components/TagMenu/index.web.tsx:50 +msgid "See {truncatedTag} posts" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:67 +msgid "See {truncatedTag} posts by user" +msgstr "" + +#: src/components/TagMenu/index.tsx:128 +msgid "See <0>{tag} posts" +msgstr "" + +#: src/components/TagMenu/index.tsx:189 +msgid "See <0>{tag} posts by this user" +msgstr "" + #: src/view/screens/SavedFeeds.tsx:163 msgid "See this guide" msgstr "ć‚¬ć‚¤ćƒ‰ć‚’č¦‹ć‚‹" @@ -3657,7 +3777,7 @@ msgid "Share" msgstr "å…±ęœ‰" #: src/view/com/profile/ProfileHeader.tsx:295 -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 #: src/view/screens/ProfileList.tsx:418 msgid "Share" msgstr "å…±ęœ‰" @@ -3690,9 +3810,9 @@ msgstr "{0}ć«ć‚ˆć‚‹åŸ‹ć‚č¾¼ćæć‚’č”Øē¤ŗ" msgid "Show follows similar to {0}" msgstr "{0}ć«ä¼¼ćŸćŠć™ć™ć‚ć®ćƒ•ć‚©ćƒ­ćƒ¼å€™č£œć‚’č”Øē¤ŗ" -#: src/view/com/post-thread/PostThreadItem.tsx:532 -#: src/view/com/post/Post.tsx:196 -#: src/view/com/posts/FeedItem.tsx:359 +#: src/view/com/post-thread/PostThreadItem.tsx:538 +#: src/view/com/post/Post.tsx:198 +#: src/view/com/posts/FeedItem.tsx:363 msgid "Show More" msgstr "さらに蔨示" @@ -3860,7 +3980,7 @@ msgstr "ć‚½ćƒ•ćƒˆć‚¦ć‚§ć‚¢é–‹ē™ŗ" msgid "Something went wrong. Check your email and try again." msgstr "ćŖć‚“ć‚‰ć‹ć®å•é”ŒćŒē™ŗē”Ÿć—ć¾ć—ćŸć€‚ćƒ”ćƒ¼ćƒ«ć‚¢ćƒ‰ćƒ¬ć‚¹ć‚’ē¢ŗčŖć—ć€ć‚‚ć†äø€åŗ¦ćŠč©¦ć—ćć ć•ć„ć€‚" -#: src/App.native.tsx:61 +#: src/App.native.tsx:63 msgid "Sorry! Your session expired. Please log in again." msgstr "ē”³ć—čØ³ć‚ć‚Šć¾ć›ć‚“ļ¼ć‚»ćƒƒć‚·ćƒ§ćƒ³ć®ęœ‰åŠ¹ęœŸé™ćŒåˆ‡ć‚Œć¾ć—ćŸć€‚ć‚‚ć†äø€åŗ¦ćƒ­ć‚°ć‚¤ćƒ³ć—ć¦ćć ć•ć„ć€‚" @@ -3926,7 +4046,7 @@ msgstr "ć“ć®ćƒŖć‚¹ćƒˆć«ē™»éŒ²" #~ msgid "Subscribed" #~ msgstr "ē™»éŒ²ęøˆćæ" -#: src/view/screens/Search/Search.tsx:373 +#: src/view/screens/Search/Search.tsx:374 msgid "Suggested Follows" msgstr "ćŠć™ć™ć‚ć®ćƒ•ć‚©ćƒ­ćƒ¼" @@ -3970,6 +4090,14 @@ msgstr "ć‚·ć‚¹ćƒ†ćƒ " msgid "System log" msgstr "ć‚·ć‚¹ćƒ†ćƒ ćƒ­ć‚°" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "tag" +msgstr "" + +#: src/components/TagMenu/index.tsx:74 +msgid "Tag menu: {tag}" +msgstr "" + #: src/view/com/modals/crop-image/CropImage.web.tsx:112 msgid "Tall" msgstr "トール" @@ -3993,6 +4121,10 @@ msgstr "ę”ä»¶" msgid "Terms of Service" msgstr "åˆ©ē”Øč¦ē“„" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "text" +msgstr "" + #: src/view/com/modals/AppealLabel.tsx:70 #: src/view/com/modals/report/InputIssueDetails.tsx:51 msgid "Text input field" @@ -4018,7 +4150,7 @@ msgstr "č‘—ä½œęØ©ćƒćƒŖć‚·ćƒ¼ćÆ<0/>ć«ē§»å‹•ć—ć¾ć—ćŸ" msgid "The following steps will help customize your Bluesky experience." msgstr "ę¬”ć®ę‰‹é †ć§ć‚ćŖćŸć®Blueskyć§ć®ä½“éØ“ć‚’ć‚«ć‚¹ć‚æćƒžć‚¤ć‚ŗć§ćć¾ć™ć€‚" -#: src/view/com/post-thread/PostThread.tsx:516 +#: src/view/com/post-thread/PostThread.tsx:517 msgid "The post may have been deleted." msgstr "ęŠ•ēØæćŒå‰Šé™¤ć•ć‚ŒćŸåÆčƒ½ę€§ćŒć‚ć‚Šć¾ć™ć€‚" @@ -4200,7 +4332,7 @@ msgstr "ć“ć®ćƒŖć‚¹ćƒˆćÆē©ŗć§ć™ļ¼" msgid "This name is already in use" msgstr "ć“ć®åå‰ćÆć™ć§ć«ä½æē”Øäø­ć§ć™" -#: src/view/com/post-thread/PostThreadItem.tsx:123 +#: src/view/com/post-thread/PostThreadItem.tsx:125 msgid "This post has been deleted." msgstr "ć“ć®ęŠ•ēØæćÆå‰Šé™¤ć•ć‚Œć¾ć—ćŸć€‚" @@ -4224,7 +4356,11 @@ msgstr "ć“ć®ćƒ¦ćƒ¼ć‚¶ćƒ¼ćÆć€ć‚ćŖćŸćŒćƒŸćƒ„ćƒ¼ćƒˆć—ćŸ<0/>ćƒŖć‚¹ćƒˆć« msgid "This warning is only available for posts with media attached." msgstr "ć“ć®č­¦å‘ŠćÆć€ćƒ”ćƒ‡ć‚£ć‚¢ćŒę·»ä»˜ć•ć‚Œć¦ć„ć‚‹ęŠ•ēØæć«ć®ćæä½æē”Øć§ćć¾ć™ć€‚" -#: src/view/com/util/forms/PostDropdownBtn.tsx:221 +#: src/components/dialogs/MutedWords.tsx:236 +msgid "This will delete {0} from your muted words. You can always add it back later." +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:237 msgid "This will hide this post from your feeds." msgstr "ć“ć®ęŠ•ēØæć‚’ć‚ćŖćŸć®ćƒ•ć‚£ćƒ¼ćƒ‰ć«ćŠć„ć¦éžč”Øē¤ŗć«ć—ć¾ć™ć€‚" @@ -4241,6 +4377,10 @@ msgstr "ć‚¹ćƒ¬ćƒƒćƒ‰ćƒ¢ćƒ¼ćƒ‰" msgid "Threads Preferences" msgstr "ć‚¹ćƒ¬ćƒƒćƒ‰ć®čØ­å®š" +#: src/components/dialogs/MutedWords.tsx:95 +msgid "Toggle between muted word options." +msgstr "" + #: src/view/com/util/forms/DropdownButton.tsx:246 msgid "Toggle dropdown" msgstr "ćƒ‰ćƒ­ćƒƒćƒ—ćƒ€ć‚¦ćƒ³ć‚’ćƒˆć‚°ćƒ«" @@ -4249,9 +4389,9 @@ msgstr "ćƒ‰ćƒ­ćƒƒćƒ—ćƒ€ć‚¦ćƒ³ć‚’ćƒˆć‚°ćƒ«" msgid "Transformations" msgstr "å¤‰ę›" -#: src/view/com/post-thread/PostThreadItem.tsx:679 -#: src/view/com/post-thread/PostThreadItem.tsx:681 -#: src/view/com/util/forms/PostDropdownBtn.tsx:154 +#: src/view/com/post-thread/PostThreadItem.tsx:685 +#: src/view/com/post-thread/PostThreadItem.tsx:687 +#: src/view/com/util/forms/PostDropdownBtn.tsx:156 msgid "Translate" msgstr "翻訳" @@ -4320,15 +4460,24 @@ msgstr "ę®‹åæµćŖćŒć‚‰ć€ć‚¢ć‚«ć‚¦ćƒ³ćƒˆć‚’ä½œęˆć™ć‚‹ćŸć‚ć®č¦ä»¶ć‚’ęŗ€ćŸ msgid "Unlike" msgstr "いいねを外す" +#: src/components/TagMenu/index.tsx:253 #: src/view/screens/ProfileList.tsx:597 msgid "Unmute" msgstr "ćƒŸćƒ„ćƒ¼ćƒˆć‚’č§£é™¤" +#: src/components/TagMenu/index.web.tsx:90 +msgid "Unmute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:326 msgid "Unmute Account" msgstr "ć‚¢ć‚«ć‚¦ćƒ³ćƒˆć®ćƒŸćƒ„ćƒ¼ćƒˆć‚’č§£é™¤" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/TagMenu/index.tsx:210 +msgid "Unmute all {tag} posts" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Unmute thread" msgstr "ć‚¹ćƒ¬ćƒƒćƒ‰ć®ćƒŸćƒ„ćƒ¼ćƒˆć‚’č§£é™¤" @@ -4533,6 +4682,10 @@ msgstr "ć‚ćŖćŸć®ćƒ•ć‚©ćƒ­ćƒ¼äø­ć®ćƒ¦ćƒ¼ć‚¶ćƒ¼ć®ęŠ•ēØæć‚’čŖ­ćæēµ‚ć‚ć‚Šć¾ #~ msgid "We recommend \"For You\" by Skygaze:" #~ msgstr "Skygazeć«ć‚ˆć‚‹ć€ŒFor Youć€ćƒ•ć‚£ćƒ¼ćƒ‰ćŒćŠć™ć™ć‚ļ¼š" +#: src/components/dialogs/MutedWords.tsx:161 +msgid "We recommend avoiding common words that appear in many posts, since it can result in no posts being shown." +msgstr "" + #: src/screens/Onboarding/StepAlgoFeeds/index.tsx:124 msgid "We recommend our \"Discover\" feed:" msgstr "ęˆ‘ć€…ć®ć€ŒDiscoverć€ćƒ•ć‚£ćƒ¼ćƒ‰ćŒćŠć™ć™ć‚ļ¼š" @@ -4561,7 +4714,11 @@ msgstr "ē§ćŸć”ćÆć‚ćŖćŸćŒå‚åŠ ć—ć¦ćć‚Œć‚‹ć“ćØć‚’ćØć¦ć‚‚ę„½ć—ćæ msgid "We're sorry, but we were unable to resolve this list. If this persists, please contact the list creator, @{handleOrDid}." msgstr "å¤§å¤‰ē”³ć—čØ³ć‚ć‚Šć¾ć›ć‚“ćŒć€ć“ć®ćƒŖć‚¹ćƒˆć‚’č§£ę±ŗć§ćć¾ć›ć‚“ć§ć—ćŸć€‚ćć‚Œć§ć‚‚ć“ć®å•é”ŒćŒč§£ę±ŗć—ćŖć„å “åˆćÆć€ä½œęˆč€…ć®@{handleOrDid}ć¾ć§ćŠå•ć„åˆć‚ć›ćć ć•ć„ć€‚" -#: src/view/screens/Search/Search.tsx:253 +#: src/components/dialogs/MutedWords.tsx:182 +msgid "We're sorry, but we weren't able to load your muted words at this time. Please try again." +msgstr "" + +#: src/view/screens/Search/Search.tsx:254 msgid "We're sorry, but your search could not be completed. Please try again in a few minutes." msgstr "å¤§å¤‰ē”³ć—čØ³ć‚ć‚Šć¾ć›ć‚“ćŒć€ę¤œē“¢ć‚’å®Œäŗ†ć§ćć¾ć›ć‚“ć§ć—ćŸć€‚ę•°åˆ†å¾Œć«å†č©¦č”Œć—ć¦ćć ć•ć„ć€‚" @@ -4582,7 +4739,7 @@ msgid "What is the issue with this {collectionName}?" msgstr "恓恮{collectionName}ć®å•é”ŒćÆä½•ć§ć™ć‹ļ¼Ÿ" #: src/view/com/auth/SplashScreen.tsx:59 -#: src/view/com/composer/Composer.tsx:279 +#: src/view/com/composer/Composer.tsx:286 msgid "What's up?" msgstr "ęœ€čæ‘ć©ć†ļ¼Ÿ" @@ -4603,11 +4760,11 @@ msgstr "čæ”äæ”ć§ćć‚‹ćƒ¦ćƒ¼ć‚¶ćƒ¼" msgid "Wide" msgstr "ćƒÆć‚¤ćƒ‰" -#: src/view/com/composer/Composer.tsx:415 +#: src/view/com/composer/Composer.tsx:422 msgid "Write post" msgstr "ęŠ•ēØæć‚’ę›øć" -#: src/view/com/composer/Composer.tsx:278 +#: src/view/com/composer/Composer.tsx:285 #: src/view/com/composer/Prompt.tsx:33 msgid "Write your reply" msgstr "čæ”äæ”ć‚’ę›øć" @@ -4676,7 +4833,7 @@ msgstr "äæå­˜ć•ć‚ŒćŸćƒ•ć‚£ćƒ¼ćƒ‰ćŒć‚ć‚Šć¾ć›ć‚“ļ¼" msgid "You don't have any saved feeds." msgstr "äæå­˜ć•ć‚ŒćŸćƒ•ć‚£ćƒ¼ćƒ‰ćŒć‚ć‚Šć¾ć›ć‚“ć€‚" -#: src/view/com/post-thread/PostThread.tsx:464 +#: src/view/com/post-thread/PostThread.tsx:465 msgid "You have blocked the author or you have been blocked by the author." msgstr "ć‚ćŖćŸćŒęŠ•ēØæč€…ć‚’ćƒ–ćƒ­ćƒƒć‚Æć—ć¦ć„ć‚‹ć‹ć€ć¾ćŸćÆęŠ•ēØæč€…ć«ć‚ˆć£ć¦ć‚ćŖćŸćÆćƒ–ćƒ­ćƒƒć‚Æć•ć‚Œć¦ć„ć¾ć™ć€‚" @@ -4716,6 +4873,10 @@ msgstr "ć‚¢ćƒ—ćƒŖćƒ‘ć‚¹ćƒÆćƒ¼ćƒ‰ćÆć¾ć ä½œęˆć•ć‚Œć¦ć„ć¾ć›ć‚“ć€‚äø‹ć®ćƒœ msgid "You have not muted any accounts yet. To mute an account, go to their profile and selected \"Mute account\" from the menu on their account." msgstr "ćƒŸćƒ„ćƒ¼ćƒˆć—ć¦ć„ć‚‹ć‚¢ć‚«ć‚¦ćƒ³ćƒˆćÆć¾ć ć‚ć‚Šć¾ć›ć‚“ć€‚ć‚¢ć‚«ć‚¦ćƒ³ćƒˆć‚’ćƒŸćƒ„ćƒ¼ćƒˆć™ć‚‹ć«ćÆć€ćƒ—ćƒ­ćƒ•ć‚£ćƒ¼ćƒ«ć«ē§»å‹•ć—ć€ć‚¢ć‚«ć‚¦ćƒ³ćƒˆćƒ”ćƒ‹ćƒ„ćƒ¼ć‹ć‚‰ć€Œć‚¢ć‚«ć‚¦ćƒ³ćƒˆć‚’ćƒŸćƒ„ćƒ¼ćƒˆć€ć‚’éøęŠžć—ć¾ć™ć€‚" +#: src/components/dialogs/MutedWords.tsx:202 +msgid "You haven't muted any words or tags yet" +msgstr "" + #: src/view/com/modals/ContentFilteringSettings.tsx:175 msgid "You must be 18 or older to enable adult content." msgstr "ęˆäŗŗå‘ć‘ć‚³ćƒ³ćƒ†ćƒ³ćƒ„ć‚’ęœ‰åŠ¹ć«ć™ć‚‹ć«ćÆć€18ę­³ä»„äøŠć§ć‚ć‚‹åæ…č¦ćŒć‚ć‚Šć¾ć™ć€‚" @@ -4724,11 +4885,11 @@ msgstr "ęˆäŗŗå‘ć‘ć‚³ćƒ³ćƒ†ćƒ³ćƒ„ć‚’ęœ‰åŠ¹ć«ć™ć‚‹ć«ćÆć€18ę­³ä»„äøŠć§ć‚ msgid "You must be 18 years or older to enable adult content" msgstr "ęˆäŗŗå‘ć‘ć‚³ćƒ³ćƒ†ćƒ³ćƒ„ć‚’ęœ‰åŠ¹ć«ć™ć‚‹ć«ćÆć€18ę­³ä»„äøŠć§ć‚ć‚‹åæ…č¦ćŒć‚ć‚Šć¾ć™ć€‚" -#: src/view/com/util/forms/PostDropdownBtn.tsx:127 +#: src/view/com/util/forms/PostDropdownBtn.tsx:129 msgid "You will no longer receive notifications for this thread" msgstr "ć“ć‚Œä»„é™ć€ć“ć®ć‚¹ćƒ¬ćƒƒćƒ‰ć«é–¢ć™ć‚‹é€šēŸ„ć‚’å—ć‘å–ć‚‹ć“ćØćÆć§ććŖććŖć‚Šć¾ć™" -#: src/view/com/util/forms/PostDropdownBtn.tsx:130 +#: src/view/com/util/forms/PostDropdownBtn.tsx:132 msgid "You will now receive notifications for this thread" msgstr "ć“ć‚Œä»„é™ć€ć“ć®ć‚¹ćƒ¬ćƒƒćƒ‰ć«é–¢ć™ć‚‹é€šēŸ„ć‚’å—ć‘å–ć‚‹ć“ćØćŒć§ćć¾ć™" @@ -4818,11 +4979,15 @@ msgstr "ćƒ•ćƒ«ćƒćƒ³ćƒ‰ćƒ«ćÆ<0>@{0}ć«ćŖć‚Šć¾ć™" #~ msgid "Your invite codes are hidden when logged in using an App Password" #~ msgstr "ć‚¢ćƒ—ćƒŖćƒ‘ć‚¹ćƒÆćƒ¼ćƒ‰ć‚’ä½æē”Øć—ć¦ćƒ­ć‚°ć‚¤ćƒ³ć™ć‚‹ćØć€ę‹›å¾…ć‚³ćƒ¼ćƒ‰ćÆéžč”Øē¤ŗć«ćŖć‚Šć¾ć™ć€‚" +#: src/components/dialogs/MutedWords.tsx:173 +msgid "Your muted words" +msgstr "" + #: src/view/com/modals/ChangePassword.tsx:155 msgid "Your password has been changed successfully!" msgstr "ćƒ‘ć‚¹ćƒÆćƒ¼ćƒ‰ć®å¤‰ę›“ćŒå®Œäŗ†ć—ć¾ć—ćŸļ¼" -#: src/view/com/composer/Composer.tsx:267 +#: src/view/com/composer/Composer.tsx:274 msgid "Your post has been published" msgstr "ęŠ•ēØæć‚’å…¬é–‹ć—ć¾ć—ćŸ" @@ -4841,7 +5006,7 @@ msgstr "ć‚ćŖćŸć®ćƒ—ćƒ­ćƒ•ć‚£ćƒ¼ćƒ«" #~ msgid "Your profile and posts will not be visible to people visiting the Bluesky app or website without having an account and being logged in." #~ msgstr "ć‚ćŖćŸć®ćƒ—ćƒ­ćƒ•ć‚£ćƒ¼ćƒ«ćØęŠ•ēØæćÆć€ć‚¢ć‚«ć‚¦ćƒ³ćƒˆć‚’ęŒć£ć¦ćŠć‚‰ćšćƒ­ć‚°ć‚¤ćƒ³ć—ć¦ć„ćŖć„ēŠ¶ę…‹ć§Blueskyć®ć‚¢ćƒ—ćƒŖć¾ćŸćÆć‚¦ć‚§ćƒ–ć‚µć‚¤ćƒˆć‚’čØŖå•ć™ć‚‹äŗŗć€…ć«ćÆč”Øē¤ŗć•ć‚Œć¾ć›ć‚“ć€‚" -#: src/view/com/composer/Composer.tsx:266 +#: src/view/com/composer/Composer.tsx:273 msgid "Your reply has been published" msgstr "čæ”äæ”ć‚’å…¬é–‹ć—ć¾ć—ćŸ" diff --git a/src/locale/locales/ko/messages.po b/src/locale/locales/ko/messages.po index 7ef971ac77..b70ba1694c 100644 --- a/src/locale/locales/ko/messages.po +++ b/src/locale/locales/ko/messages.po @@ -76,7 +76,7 @@ msgid "A new version of the app is available. Please update to continue using th msgstr "새 ė²„ģ „ģ˜ ģ•±ģ„ ģ‚¬ģš©ķ•  수 ģžˆģŠµė‹ˆė‹¤. ģ•±ģ„ ź³„ģ† ģ‚¬ģš©ķ•˜ė ¤ė©“ ģ—…ė°ģ“ķŠøķ•˜ģ„øģš”." #: src/view/com/util/ViewHeader.tsx:83 -#: src/view/screens/Search/Search.tsx:624 +#: src/view/screens/Search/Search.tsx:647 msgid "Access navigation links and settings" msgstr "ķƒģƒ‰ 링크 ė° ģ„¤ģ •ģœ¼ė”œ ģ“ė™ķ•©ė‹ˆė‹¤" @@ -127,6 +127,7 @@ msgstr "계정 차단 ķ•“ģ œėØ" msgid "Account unmuted" msgstr "계정 ģ–øė®¤ķŠøėØ" +#: src/components/dialogs/MutedWords.tsx:147 #: src/view/com/auth/onboarding/RecommendedFeedsItem.tsx:150 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -168,14 +169,22 @@ msgstr "세부 정볓 추가" msgid "Add details to report" msgstr "ģ‹ ź³  세부 정볓 추가" -#: src/view/com/composer/Composer.tsx:446 +#: src/view/com/composer/Composer.tsx:453 msgid "Add link card" msgstr "링크 ģ¹“ė“œ 추가" -#: src/view/com/composer/Composer.tsx:451 +#: src/view/com/composer/Composer.tsx:458 msgid "Add link card:" msgstr "링크 ģ¹“ė“œ 추가:" +#: src/components/dialogs/MutedWords.tsx:140 +msgid "Add mute word for configured settings" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:74 +msgid "Add muted words and tags" +msgstr "" + #: src/view/com/modals/ChangeHandle.tsx:417 msgid "Add the following DNS record to your domain:" msgstr "ė„ė©”ģøģ— ė‹¤ģŒ DNS ė ˆģ½”ė“œė„¼ ģ¶”ź°€ķ•˜ģ„øģš”:" @@ -295,7 +304,7 @@ msgstr "앱 ė¹„ė°€ė²ˆķ˜ø 설정" msgid "App Passwords" msgstr "앱 ė¹„ė°€ė²ˆķ˜ø" -#: src/view/com/util/forms/PostDropdownBtn.tsx:279 +#: src/view/com/util/forms/PostDropdownBtn.tsx:295 msgid "Appeal content warning" msgstr "ģ½˜ķ…ģø  경고 ģ“ģ˜ģ‹ ģ²­" @@ -319,15 +328,16 @@ msgstr "ėŖØģ–‘" msgid "Are you sure you want to delete the app password \"{name}\"?" msgstr "앱 ė¹„ė°€ė²ˆķ˜ø \"{name}\"ģ„(넼) ģ‚­ģ œķ•˜ģ‹œź² ģŠµė‹ˆź¹Œ?" -#: src/view/com/composer/Composer.tsx:143 +#: src/view/com/composer/Composer.tsx:150 msgid "Are you sure you'd like to discard this draft?" msgstr "ģ“ ģ“ˆģ•ˆģ„ ģ‚­ģ œķ•˜ģ‹œź² ģŠµė‹ˆź¹Œ?" +#: src/components/dialogs/MutedWords.tsx:233 #: src/view/screens/ProfileList.tsx:365 msgid "Are you sure?" msgstr "ģ •ė§ģøź°€ģš”?" -#: src/view/com/util/forms/PostDropdownBtn.tsx:262 +#: src/view/com/util/forms/PostDropdownBtn.tsx:278 msgid "Are you sure? This cannot be undone." msgstr "ģ •ė§ģøź°€ģš”? ė˜ėŒė¦“ 수 ģ—†ģŠµė‹ˆė‹¤." @@ -349,15 +359,15 @@ msgstr "ģ„ ģ •ģ ģ“ģ§€ ģ•Šź±°ė‚˜ ģ˜ˆģˆ ģ ģø ė…øģ¶œ." #: src/view/com/auth/login/LoginForm.tsx:259 #: src/view/com/auth/login/SetNewPasswordForm.tsx:179 #: src/view/com/modals/report/InputIssueDetails.tsx:46 -#: src/view/com/post-thread/PostThread.tsx:471 -#: src/view/com/post-thread/PostThread.tsx:521 -#: src/view/com/post-thread/PostThread.tsx:529 +#: src/view/com/post-thread/PostThread.tsx:472 +#: src/view/com/post-thread/PostThread.tsx:522 +#: src/view/com/post-thread/PostThread.tsx:530 #: src/view/com/profile/ProfileHeader.tsx:649 #: src/view/com/util/ViewHeader.tsx:81 msgid "Back" msgstr "ė’¤ė”œ" -#: src/view/com/post-thread/PostThread.tsx:479 +#: src/view/com/post-thread/PostThread.tsx:480 msgctxt "action" msgid "Back" msgstr "ė’¤ė”œ" @@ -405,7 +415,7 @@ msgstr "ģ“ 리스트 차단" msgid "Blocked" msgstr "차단됨" -#: src/view/screens/Moderation.tsx:123 +#: src/view/screens/Moderation.tsx:142 msgid "Blocked accounts" msgstr "ģ°Øė‹Øķ•œ 계정" @@ -464,7 +474,7 @@ msgstr "BlueskyėŠ” ź³µź°œģ ģž…ė‹ˆė‹¤." msgid "Bluesky uses invites to build a healthier community. If you don't know anybody with an invite, you can sign up for the waitlist and we'll send one soon." msgstr "BlueskyėŠ” ė” ź±“ź°•ķ•œ ģ»¤ė®¤ė‹ˆķ‹°ė„¼ źµ¬ģ¶•ķ•˜źø° ģœ„ķ•“ ģ“ˆėŒ€ ė°©ģ‹ģ„ ģ‚¬ģš©ķ•©ė‹ˆė‹¤. ģ“ˆėŒ€ķ•“ 준 ģ‚¬ėžŒģ“ ģ—†ėŠ” 경우 ėŒ€źø°ģž 명단에 ė“±ė”ķ•˜ė©“ ź³§ ģ“ˆėŒ€ė„¼ ė³“ė‚“ź² ģŠµė‹ˆė‹¤." -#: src/view/screens/Moderation.tsx:226 +#: src/view/screens/Moderation.tsx:245 msgid "Bluesky will not show your profile and posts to logged-out users. Other apps may not honor this request. This does not make your account private." msgstr "ė”œź·øģ•„ģ›ƒķ•œ ģ‚¬ģš©ģžģ—ź²Œ ė‚“ ķ”„ė”œķ•„ź³¼ ź²Œģ‹œė¬¼ģ„ ķ‘œģ‹œķ•˜ģ§€ ģ•ŠģŠµė‹ˆė‹¤. 다넸 ģ•±ģ—ģ„œėŠ” ģ“ ģ„¤ģ •ģ„ ė”°ė„“ģ§€ ģ•Šģ„ 수 ģžˆģŠµė‹ˆė‹¤. ė‚“ ź³„ģ •ģ„ ė¹„ź³µź°œė”œ ģ „ķ™˜ķ•˜ģ§€ėŠ” ģ•ŠģŠµė‹ˆė‹¤." @@ -516,8 +526,8 @@ msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must msgstr "źø€ģž, ģˆ«ģž, 공백, ėŒ€ģ‹œ, ė°‘ģ¤„ė§Œ ķ¬ķ•Øķ•  수 ģžˆģŠµė‹ˆė‹¤. źøøģ“ėŠ” 4ģž ģ“ģƒģ“ģ–“ģ•¼ ķ•˜ź³  32ģžė„¼ ė„˜ģ§€ ģ•Šģ•„ģ•¼ ķ•©ė‹ˆė‹¤." #: src/components/Prompt.tsx:91 -#: src/view/com/composer/Composer.tsx:300 -#: src/view/com/composer/Composer.tsx:305 +#: src/view/com/composer/Composer.tsx:307 +#: src/view/com/composer/Composer.tsx:312 #: src/view/com/modals/ChangeEmail.tsx:218 #: src/view/com/modals/ChangeEmail.tsx:220 #: src/view/com/modals/ChangePassword.tsx:265 @@ -531,7 +541,7 @@ msgstr "źø€ģž, ģˆ«ģž, 공백, ėŒ€ģ‹œ, ė°‘ģ¤„ė§Œ ķ¬ķ•Øķ•  수 ģžˆģŠµė‹ˆė‹¤. #: src/view/com/modals/VerifyEmail.tsx:247 #: src/view/com/modals/VerifyEmail.tsx:253 #: src/view/com/modals/Waitlist.tsx:142 -#: src/view/screens/Search/Search.tsx:693 +#: src/view/screens/Search/Search.tsx:716 #: src/view/shell/desktop/Search.tsx:238 msgid "Cancel" msgstr "ģ·Øģ†Œ" @@ -678,7 +688,7 @@ msgid "Clear all storage data (restart after this)" msgstr "ėŖØė“  ģŠ¤ķ† ė¦¬ģ§€ ė°ģ“ķ„° ģ§€ģš°źø° (ģ“ķ›„ ė‹¤ģ‹œ ģ‹œģž‘)" #: src/view/com/util/forms/SearchInput.tsx:88 -#: src/view/screens/Search/Search.tsx:674 +#: src/view/screens/Search/Search.tsx:697 msgid "Clear search query" msgstr "ź²€ģƒ‰ģ–“ ģ§€ģš°źø°" @@ -686,6 +696,11 @@ msgstr "ź²€ģƒ‰ģ–“ ģ§€ģš°źø°" msgid "click here" msgstr "ģ“ź³³ģ„ 큓릭" +#: src/components/RichText.tsx:189 +#: src/components/TagMenu/index.web.tsx:125 +msgid "Click here to open tag menu for {tag}" +msgstr "" + #: src/screens/Onboarding/index.tsx:35 msgid "Climate" msgstr "기후" @@ -716,11 +731,15 @@ msgstr "ģ“ėÆøģ§€ ė‹«źø°" msgid "Close image viewer" msgstr "ģ“ėÆøģ§€ ė·°ģ–“ ė‹«źø°" -#: src/view/shell/index.web.tsx:49 +#: src/view/shell/index.web.tsx:51 msgid "Close navigation footer" msgstr "ķƒģƒ‰ 푸터 ė‹«źø°" -#: src/view/shell/index.web.tsx:50 +#: src/components/TagMenu/index.tsx:266 +msgid "Close this dialog" +msgstr "" + +#: src/view/shell/index.web.tsx:52 msgid "Closes bottom navigation bar" msgstr "ķ•˜ė‹Ø ķƒģƒ‰ ė§‰ėŒ€ė„¼ ė‹«ģŠµė‹ˆė‹¤" @@ -728,7 +747,7 @@ msgstr "ķ•˜ė‹Ø ķƒģƒ‰ ė§‰ėŒ€ė„¼ ė‹«ģŠµė‹ˆė‹¤" msgid "Closes password update alert" msgstr "ė¹„ė°€ė²ˆķ˜ø 변경 ģ•Œė¦¼ģ„ ė‹«ģŠµė‹ˆė‹¤" -#: src/view/com/composer/Composer.tsx:302 +#: src/view/com/composer/Composer.tsx:309 msgid "Closes post composer and discards post draft" msgstr "ź²Œģ‹œė¬¼ ģž‘ģ„± ģƒģžė„¼ ė‹«ź³  ź²Œģ‹œė¬¼ ģ“ˆģ•ˆģ„ ģ‚­ģ œķ•©ė‹ˆė‹¤" @@ -761,7 +780,7 @@ msgstr "ģ˜Øė³“ė”© ģ™„ė£Œ 후 계정 ģ‚¬ģš© ģ‹œģž‘" msgid "Complete the challenge" msgstr "" -#: src/view/com/composer/Composer.tsx:417 +#: src/view/com/composer/Composer.tsx:424 msgid "Compose posts up to {MAX_GRAPHEME_LENGTH} characters in length" msgstr "ģµœėŒ€ {MAX_GRAPHEME_LENGTH}ģž źøøģ“ź¹Œģ§€ źø€ģ„ ģž‘ģ„±ķ•  수 ģžˆģŠµė‹ˆė‹¤" @@ -825,7 +844,7 @@ msgstr "ģ—°ź²° 중…" msgid "Contact support" msgstr "지원에 ģ—°ė½ķ•˜źø°" -#: src/view/screens/Moderation.tsx:81 +#: src/view/screens/Moderation.tsx:83 msgid "Content filtering" msgstr "ģ½˜ķ…ģø  필터링" @@ -891,7 +910,7 @@ msgstr "ė¹Œė“œ 버전 ķ“ė¦½ė³“ė“œģ— 복사됨" #: src/view/com/modals/AddAppPasswords.tsx:76 #: src/view/com/modals/InviteCodes.tsx:152 -#: src/view/com/util/forms/PostDropdownBtn.tsx:141 +#: src/view/com/util/forms/PostDropdownBtn.tsx:143 msgid "Copied to clipboard" msgstr "ķ“ė¦½ė³“ė“œģ— 복사됨" @@ -907,7 +926,7 @@ msgstr "복사" msgid "Copy link to list" msgstr "리스트 링크 복사" -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 msgid "Copy link to post" msgstr "ź²Œģ‹œė¬¼ 링크 복사" @@ -915,7 +934,7 @@ msgstr "ź²Œģ‹œė¬¼ 링크 복사" msgid "Copy link to profile" msgstr "ķ”„ė”œķ•„ 링크 복사" -#: src/view/com/util/forms/PostDropdownBtn.tsx:168 +#: src/view/com/util/forms/PostDropdownBtn.tsx:170 msgid "Copy post text" msgstr "ź²Œģ‹œė¬¼ ķ…ģŠ¤ķŠø 복사" @@ -971,7 +990,7 @@ msgstr "<0/> ė‹˜ģ“ ė§Œė“¦" msgid "Created by you" msgstr "ė‚“ź°€ ė§Œė“¦" -#: src/view/com/composer/Composer.tsx:448 +#: src/view/com/composer/Composer.tsx:455 msgid "Creates a card with a thumbnail. The card links to {url}" msgstr "미리볓기 ģ“ėÆøģ§€ź°€ ģžˆėŠ” ģ¹“ė“œė„¼ ė§Œė“­ė‹ˆė‹¤. ģ¹“ė“œź°€ {url}(으)딜 ģ—°ź²°ė©ė‹ˆė‹¤" @@ -1048,11 +1067,11 @@ msgstr "ė‚“ 계정 ģ‚­ģ œ" msgid "Delete My Account…" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:257 +#: src/view/com/util/forms/PostDropdownBtn.tsx:273 msgid "Delete post" msgstr "ź²Œģ‹œė¬¼ ģ‚­ģ œ" -#: src/view/com/util/forms/PostDropdownBtn.tsx:261 +#: src/view/com/util/forms/PostDropdownBtn.tsx:277 msgid "Delete this post?" msgstr "ģ“ ź²Œģ‹œė¬¼ģ„ ģ‚­ģ œķ•˜ģ‹œź² ģŠµė‹ˆź¹Œ?" @@ -1075,7 +1094,7 @@ msgstr "설명" #~ msgid "Developer Tools" #~ msgstr "ź°œė°œģž ė„źµ¬" -#: src/view/com/composer/Composer.tsx:211 +#: src/view/com/composer/Composer.tsx:218 msgid "Did you want to say anything?" msgstr "ķ•˜ź³  ģ‹¶ģ€ ė§ģ“ ģžˆė‚˜ģš”?" @@ -1083,15 +1102,15 @@ msgstr "ķ•˜ź³  ģ‹¶ģ€ ė§ģ“ ģžˆė‚˜ģš”?" msgid "Dim" msgstr "" -#: src/view/com/composer/Composer.tsx:144 +#: src/view/com/composer/Composer.tsx:151 msgid "Discard" msgstr "ģ‚­ģ œ" -#: src/view/com/composer/Composer.tsx:138 +#: src/view/com/composer/Composer.tsx:145 msgid "Discard draft" msgstr "ģ“ˆģ•ˆ ģ‚­ģ œ" -#: src/view/screens/Moderation.tsx:207 +#: src/view/screens/Moderation.tsx:226 msgid "Discourage apps from showing my account to logged-out users" msgstr "ģ•±ģ“ ė”œź·øģ•„ģ›ƒķ•œ ģ‚¬ģš©ģžģ—ź²Œ ė‚“ ź³„ģ •ģ„ ķ‘œģ‹œķ•˜ģ§€ ģ•Šė„ė” ģ„¤ģ •ķ•˜źø°" @@ -1170,7 +1189,7 @@ msgstr "" msgid "Download CAR file" msgstr "" -#: src/view/com/composer/text-input/TextInput.web.tsx:247 +#: src/view/com/composer/text-input/TextInput.web.tsx:249 msgid "Drop to add images" msgstr "ė“œė”­ķ•˜ģ—¬ ģ“ėÆøģ§€ 추가" @@ -1242,6 +1261,7 @@ msgstr "ķ”„ė”œķ•„ ķŽøģ§‘" msgid "Edit Profile" msgstr "ķ”„ė”œķ•„ ķŽøģ§‘" +#: src/view/com/home/HomeHeaderLayout.web.tsx:59 #: src/view/screens/Feeds.tsx:355 msgid "Edit Saved Feeds" msgstr "ģ €ģž„ėœ ķ”¼ė“œ ķŽøģ§‘" @@ -1324,6 +1344,11 @@ msgstr "ķ”¼ė“œ ė" msgid "Enter a name for this App Password" msgstr "ģ“ 앱 ė¹„ė°€ė²ˆķ˜øģ˜ ģ“ė¦„ģ„ ģž…ė „ķ•˜ģ„øģš”" +#: src/components/dialogs/MutedWords.tsx:87 +#: src/components/dialogs/MutedWords.tsx:88 +msgid "Enter a word or tag" +msgstr "" + #: src/view/com/modals/VerifyEmail.tsx:105 msgid "Enter Confirmation Code" msgstr "ķ™•ģø ģ½”ė“œ ģž…ė „" @@ -1373,7 +1398,7 @@ msgstr "ģ‚¬ģš©ģž ģ“ė¦„ ė° ė¹„ė°€ė²ˆķ˜ø ģž…ė „" msgid "Error receiving captcha response." msgstr "" -#: src/view/screens/Search/Search.tsx:109 +#: src/view/screens/Search/Search.tsx:110 msgid "Error:" msgstr "오넘:" @@ -1444,7 +1469,7 @@ msgstr "앱 ė¹„ė°€ė²ˆķ˜øė„¼ ė§Œė“¤ģ§€ ėŖ»ķ–ˆģŠµė‹ˆė‹¤." msgid "Failed to create the list. Check your internet connection and try again." msgstr "리스트넼 ė§Œė“¤ģ§€ ėŖ»ķ–ˆģŠµė‹ˆė‹¤. ģøķ„°ė„· ģ—°ź²°ģ„ ķ™•ģøķ•œ 후 ė‹¤ģ‹œ ģ‹œė„ķ•˜ģ„øģš”." -#: src/view/com/util/forms/PostDropdownBtn.tsx:108 +#: src/view/com/util/forms/PostDropdownBtn.tsx:110 msgid "Failed to delete post, please try again" msgstr "ź²Œģ‹œė¬¼ģ„ ģ‚­ģ œķ•˜ģ§€ ėŖ»ķ–ˆģŠµė‹ˆė‹¤. ė‹¤ģ‹œ ģ‹œė„ķ•“ ģ£¼ģ„øģš”" @@ -1466,8 +1491,8 @@ msgid "Feed offline" msgstr "ķ”¼ė“œ ģ˜¤ķ”„ė¼ģø" #: src/view/com/feeds/FeedPage.tsx:143 -msgid "Feed Preferences" -msgstr "ķ”¼ė“œ 설정" +#~ msgid "Feed Preferences" +#~ msgstr "ķ”¼ė“œ 설정" #: src/view/shell/desktop/RightNav.tsx:61 #: src/view/shell/Drawer.tsx:311 @@ -1507,11 +1532,11 @@ msgstr "마묓리 중" msgid "Find accounts to follow" msgstr "ķŒ”ė”œģš°ķ•  계정 찾아볓기" -#: src/view/screens/Search/Search.tsx:439 +#: src/view/screens/Search/Search.tsx:440 msgid "Find users on Bluesky" msgstr "Blueskyģ—ģ„œ ģ‚¬ģš©ģž 찾기" -#: src/view/screens/Search/Search.tsx:437 +#: src/view/screens/Search/Search.tsx:438 msgid "Find users with the search tool on the right" msgstr "ģ˜¤ė„øģŖ½ģ˜ ź²€ģƒ‰ ė„źµ¬ė”œ ģ‚¬ģš©ģž 찾기" @@ -1608,6 +1633,7 @@ msgid "Following {0}" msgstr "{0} ķŒ”ė”œģš° 중" #: src/Navigation.tsx:248 +#: src/view/com/home/HomeHeaderLayout.web.tsx:45 #: src/view/com/home/HomeHeaderLayoutMobile.tsx:83 #: src/view/screens/PreferencesFollowingFeed.tsx:104 #: src/view/screens/Settings/index.tsx:543 @@ -1647,7 +1673,7 @@ msgstr "ė¹„ė°€ė²ˆķ˜ø 분실" msgid "Forgot Password" msgstr "ė¹„ė°€ė²ˆķ˜ø 분실" -#: src/view/com/posts/FeedItem.tsx:187 +#: src/view/com/posts/FeedItem.tsx:189 msgctxt "from-feed" msgid "From <0/>" msgstr "<0/>ģ—ģ„œ" @@ -1680,7 +1706,7 @@ msgstr "ė’¤ė”œ" msgid "Go back to previous step" msgstr "ģ“ģ „ ė‹Øź³„ė”œ ėŒģ•„ź°€źø°" -#: src/view/screens/Search/Search.tsx:724 +#: src/view/screens/Search/Search.tsx:747 #: src/view/shell/desktop/Search.tsx:262 msgid "Go to @{queryMaybeHandle}" msgstr "@{queryMaybeHandle}(으)딜 ģ“ė™" @@ -1697,6 +1723,10 @@ msgstr "ė‹¤ģŒ" msgid "Handle" msgstr "핸들" +#: src/components/RichText.tsx:188 +msgid "Hashtag: {tag}" +msgstr "" + #: src/view/com/auth/create/CreateAccount.tsx:208 msgid "Having trouble?" msgstr "ė¬øģ œź°€ ģžˆė‚˜ģš”?" @@ -1735,7 +1765,7 @@ msgctxt "action" msgid "Hide" msgstr "숨기기" -#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +#: src/view/com/util/forms/PostDropdownBtn.tsx:232 msgid "Hide post" msgstr "ź²Œģ‹œė¬¼ 숨기기" @@ -1744,7 +1774,7 @@ msgstr "ź²Œģ‹œė¬¼ 숨기기" msgid "Hide the content" msgstr "ģ½˜ķ…ģø  숨기기" -#: src/view/com/util/forms/PostDropdownBtn.tsx:220 +#: src/view/com/util/forms/PostDropdownBtn.tsx:236 msgid "Hide this post?" msgstr "ģ“ ź²Œģ‹œė¬¼ģ„ ģˆØźø°ģ‹œź² ģŠµė‹ˆź¹Œ?" @@ -1893,7 +1923,7 @@ msgstr "ė¹„ė°€ė²ˆķ˜øė„¼ ģž…ė „ķ•©ė‹ˆė‹¤" msgid "Input your user handle" msgstr "ģ‚¬ģš©ģž ķ•øė“¤ģ„ ģž…ė „ķ•©ė‹ˆė‹¤" -#: src/view/com/post-thread/PostThreadItem.tsx:224 +#: src/view/com/post-thread/PostThreadItem.tsx:226 msgid "Invalid or unsupported post record" msgstr "ģœ ķšØķ•˜ģ§€ ģ•Šź±°ė‚˜ ģ§€ģ›ė˜ģ§€ ģ•ŠėŠ” ź²Œģ‹œė¬¼ źø°ė”" @@ -1995,7 +2025,7 @@ msgstr "ė” ģ•Œģ•„ė³“źø°" msgid "Learn more about this warning" msgstr "ģ“ 경고에 ėŒ€ķ•“ ė” ģ•Œģ•„ė³“źø°" -#: src/view/screens/Moderation.tsx:243 +#: src/view/screens/Moderation.tsx:262 msgid "Learn more about what is public on Bluesky." msgstr "Blueskyģ—ģ„œ ź³µź°œė˜ėŠ” 항목에 ėŒ€ķ•“ ģžģ„øķžˆ ģ•Œģ•„ė³“ģ„øģš”." @@ -2071,7 +2101,7 @@ msgstr "ė‹˜ģ“ ė‚“ ź²Œģ‹œė¬¼ģ„ ģ¢‹ģ•„ķ•©ė‹ˆė‹¤" msgid "Likes" msgstr "ģ¢‹ģ•„ģš”" -#: src/view/com/post-thread/PostThreadItem.tsx:181 +#: src/view/com/post-thread/PostThreadItem.tsx:183 msgid "Likes on this post" msgstr "ģ“ ź²Œģ‹œė¬¼ģ„ ģ¢‹ģ•„ģš” ķ‘œģ‹œķ•©ė‹ˆė‹¤" @@ -2128,7 +2158,7 @@ msgstr "ė” ė§Žģ€ ź²Œģ‹œė¬¼ 불러오기" msgid "Load new notifications" msgstr "새 ģ•Œė¦¼ 불러오기" -#: src/view/com/feeds/FeedPage.tsx:181 +#: src/view/com/feeds/FeedPage.tsx:115 #: src/view/screens/Profile.tsx:440 #: src/view/screens/ProfileFeed.tsx:495 #: src/view/screens/ProfileList.tsx:681 @@ -2154,7 +2184,7 @@ msgstr "딜그" msgid "Log out" msgstr "ė”œź·øģ•„ģ›ƒ" -#: src/view/screens/Moderation.tsx:136 +#: src/view/screens/Moderation.tsx:155 msgid "Logged-out visibility" msgstr "ė”œź·øģ•„ģ›ƒ ķ‘œģ‹œ" @@ -2166,6 +2196,10 @@ msgstr "ėŖ©ė”ģ— ģ—†ėŠ” ź³„ģ •ģœ¼ė”œ ė”œź·øģø" msgid "Make sure this is where you intend to go!" msgstr "ģ“ź³³ģ“ ė‹¹ģ‹ ģ“ ź°€ź³ ģž ķ•˜ėŠ” ź³³ģøģ§€ ķ™•ģøķ•˜ģ„øģš”!" +#: src/components/dialogs/MutedWords.tsx:71 +msgid "Manage your muted words and tags" +msgstr "" + #: src/view/com/auth/create/Step2.tsx:118 msgid "May not be longer than 253 characters" msgstr "" @@ -2187,7 +2221,7 @@ msgid "Mentioned users" msgstr "ė©˜ģ…˜ķ•œ ģ‚¬ģš©ģž" #: src/view/com/util/ViewHeader.tsx:81 -#: src/view/screens/Search/Search.tsx:623 +#: src/view/screens/Search/Search.tsx:646 msgid "Menu" msgstr "메뉓" @@ -2196,7 +2230,7 @@ msgid "Message from server: {0}" msgstr "ģ„œė²„ģ—ģ„œ 볓낸 ė©”ģ‹œģ§€: {0}" #: src/Navigation.tsx:115 -#: src/view/screens/Moderation.tsx:64 +#: src/view/screens/Moderation.tsx:66 #: src/view/screens/Settings/index.tsx:625 #: src/view/shell/desktop/LeftNav.tsx:397 #: src/view/shell/Drawer.tsx:511 @@ -2227,7 +2261,7 @@ msgstr "검토 리스트 ģƒģ„±ėØ" msgid "Moderation list updated" msgstr "검토 리스트 ģ—…ė°ģ“ķŠøėØ" -#: src/view/screens/Moderation.tsx:95 +#: src/view/screens/Moderation.tsx:114 msgid "Moderation lists" msgstr "검토 리스트" @@ -2254,7 +2288,7 @@ msgstr "ķ”¼ė“œ ė” 볓기" msgid "More options" msgstr "ģ˜µģ…˜ ė” 볓기" -#: src/view/com/util/forms/PostDropdownBtn.tsx:299 +#: src/view/com/util/forms/PostDropdownBtn.tsx:315 msgid "More post options" msgstr "ź²Œģ‹œė¬¼ ģ˜µģ…˜ ė” 볓기" @@ -2266,6 +2300,14 @@ msgstr "ģ¢‹ģ•„ģš” ė§Žģ€ 순" msgid "Must be at least 3 characters" msgstr "" +#: src/components/TagMenu/index.tsx:253 +msgid "Mute" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:91 +msgid "Mute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:327 msgid "Mute Account" msgstr "계정 뮤트" @@ -2274,6 +2316,18 @@ msgstr "계정 뮤트" msgid "Mute accounts" msgstr "계정 뮤트" +#: src/components/TagMenu/index.tsx:211 +msgid "Mute all {tag} posts" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:131 +msgid "Mute in tags only" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:116 +msgid "Mute in text & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:491 msgid "Mute list" msgstr "리스트 뮤트" @@ -2286,15 +2340,27 @@ msgstr "ģ“ ź³„ģ •ė“¤ģ„ ė®¤ķŠøķ•˜ģ‹œź² ģŠµė‹ˆź¹Œ?" msgid "Mute this List" msgstr "ģ“ 리스트 뮤트" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/dialogs/MutedWords.tsx:109 +msgid "Mute this word in post text and tags" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:124 +msgid "Mute this word in tags only" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Mute thread" msgstr "ģŠ¤ė ˆė“œ 뮤트" +#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +msgid "Mute words & tags" +msgstr "" + #: src/view/com/lists/ListCard.tsx:102 msgid "Muted" msgstr "뮤트됨" -#: src/view/screens/Moderation.tsx:109 +#: src/view/screens/Moderation.tsx:128 msgid "Muted accounts" msgstr "ė®¤ķŠøķ•œ 계정" @@ -2307,6 +2373,10 @@ msgstr "ė®¤ķŠøķ•œ 계정" msgid "Muted accounts have their posts removed from your feed and from your notifications. Mutes are completely private." msgstr "ź³„ģ •ģ„ ė®¤ķŠøķ•˜ė©“ ķ”¼ė“œģ™€ ģ•Œė¦¼ģ—ģ„œ 핓당 ź³„ģ •ģ˜ ź²Œģ‹œė¬¼ģ“ ģ‚¬ė¼ģ§‘ė‹ˆė‹¤. 뮤트 ėŖ©ė”ģ€ ģ™„ģ „ķžˆ ė¹„ź³µź°œė”œ ģœ ģ§€ė©ė‹ˆė‹¤." +#: src/view/screens/Moderation.tsx:100 +msgid "Muted words & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:277 msgid "Muting is private. Muted accounts can interact with you, but you will not see their posts or receive notifications from them." msgstr "뮤트 ėŖ©ė”ģ€ ė¹„ź³µź°œģž…ė‹ˆė‹¤. ė®¤ķŠøķ•œ ź³„ģ •ģ€ ė‚˜ģ™€ ģƒķ˜øģž‘ģš©ķ•  수 ģžˆģ§€ė§Œ 핓당 ź³„ģ •ģ˜ ź²Œģ‹œė¬¼ģ„ ė³“ź±°ė‚˜ 핓당 ź³„ģ •ģœ¼ė”œė¶€ķ„° ģ•Œė¦¼ģ„ ė°›ģ„ 수 ģ—†ģŠµė‹ˆė‹¤." @@ -2370,6 +2440,10 @@ msgstr "ķŒ”ė”œģ›Œģ™€ ė°ģ“ķ„°ģ— ėŒ€ķ•œ ģ ‘ź·¼ ź¶Œķ•œģ„ ģžƒģ§€ ģ•ŠģŠµė‹ˆė‹¤." msgid "Never lose access to your followers or data." msgstr "ķŒ”ė”œģ›Œ ė˜ėŠ” ė°ģ“ķ„°ģ— ėŒ€ķ•œ ģ ‘ź·¼ ź¶Œķ•œģ„ ģžƒģ§€ ģ•ŠģŠµė‹ˆė‹¤." +#: src/components/dialogs/MutedWords.tsx:244 +msgid "Nevermind" +msgstr "" + #: src/view/screens/Lists.tsx:76 msgctxt "action" msgid "New" @@ -2391,7 +2465,7 @@ msgstr "새 ė¹„ė°€ė²ˆķ˜ø" msgid "New Password" msgstr "" -#: src/view/com/feeds/FeedPage.tsx:192 +#: src/view/com/feeds/FeedPage.tsx:126 msgctxt "action" msgid "New post" msgstr "새 ź²Œģ‹œė¬¼" @@ -2476,8 +2550,8 @@ msgid "No results found for \"{query}\"" msgstr "\"{query}\"에 ėŒ€ķ•œ 결과넼 ģ°¾ģ„ 수 ģ—†ģŠµė‹ˆė‹¤" #: src/view/com/modals/ListAddRemoveUsers.tsx:127 -#: src/view/screens/Search/Search.tsx:280 -#: src/view/screens/Search/Search.tsx:308 +#: src/view/screens/Search/Search.tsx:281 +#: src/view/screens/Search/Search.tsx:309 msgid "No results found for {query}" msgstr "{query}에 ėŒ€ķ•œ 결과넼 ģ°¾ģ„ 수 ģ—†ģŠµė‹ˆė‹¤" @@ -2503,7 +2577,7 @@ msgstr "ģ°¾ģ„ 수 ģ—†ģŒ" msgid "Not right now" msgstr "ė‚˜ģ¤‘ģ— ķ•˜źø°" -#: src/view/screens/Moderation.tsx:233 +#: src/view/screens/Moderation.tsx:252 msgid "Note: Bluesky is an open and public network. This setting only limits the visibility of your content on the Bluesky app and website, and other apps may not respect this setting. Your content may still be shown to logged-out users by other apps and websites." msgstr "ģ°øź³ : BlueskyėŠ” ź°œė°©ķ˜• 공개 ė„¤ķŠøģ›Œķ¬ģž…ė‹ˆė‹¤. ģ“ ģ„¤ģ •ģ€ Bluesky 앱과 ģ›¹ģ‚¬ģ“ķŠøģ—ģ„œė§Œ ė‚“ ģ½˜ķ…ģø ź°€ ķ‘œģ‹œė˜ėŠ” ź²ƒģ„ ģ œķ•œķ•˜ė©°, 다넸 ģ•±ģ—ģ„œėŠ” ģ“ ģ„¤ģ •ģ„ ģ¤€ģˆ˜ķ•˜ģ§€ ģ•Šģ„ 수 ģžˆģŠµė‹ˆė‹¤. 다넸 앱과 ģ›¹ģ‚¬ģ“ķŠøģ—ģ„œėŠ” ė”œź·øģ•„ģ›ƒķ•œ ģ‚¬ģš©ģžģ—ź²Œ ė‚“ ģ½˜ķ…ģø ź°€ ź³„ģ† ķ‘œģ‹œė  수 ģžˆģŠµė‹ˆė‹¤." @@ -2541,7 +2615,7 @@ msgstr "ģ˜¤ėž˜ėœ 순" msgid "Onboarding reset" msgstr "ģ˜Øė³“ė”© ģž¬ģ„¤ģ •" -#: src/view/com/composer/Composer.tsx:375 +#: src/view/com/composer/Composer.tsx:382 msgid "One or more images is missing alt text." msgstr "ķ•˜ė‚˜ ģ“ģƒģ˜ ģ“ėÆøģ§€ģ— ėŒ€ģ²“ ķ…ģŠ¤ķŠøź°€ ėˆ„ė½ė˜ģ—ˆģŠµė‹ˆė‹¤." @@ -2558,8 +2632,12 @@ msgstr "ģ“ėŸ°!" msgid "Open" msgstr "ź³µź°œģ„±" -#: src/view/com/composer/Composer.tsx:470 -#: src/view/com/composer/Composer.tsx:471 +#: src/view/screens/Moderation.tsx:75 +msgid "Open content filtering settings" +msgstr "" + +#: src/view/com/composer/Composer.tsx:477 +#: src/view/com/composer/Composer.tsx:478 msgid "Open emoji picker" msgstr "ģ“ėŖØķ‹°ģ½˜ ģ„ ķƒźø° ģ—“źø°" @@ -2567,6 +2645,10 @@ msgstr "ģ“ėŖØķ‹°ģ½˜ ģ„ ķƒźø° ģ—“źø°" msgid "Open links with in-app browser" msgstr "링크넼 ģøģ•± ėøŒė¼ģš°ģ €ė”œ ģ—½ė‹ˆė‹¤" +#: src/view/screens/Moderation.tsx:92 +msgid "Open muted words settings" +msgstr "" + #: src/view/com/home/HomeHeaderLayoutMobile.tsx:49 msgid "Open navigation" msgstr "ė‚“ė¹„ź²Œģ“ģ…˜ ģ—“źø°" @@ -2643,6 +2725,7 @@ msgstr "검토 ģ„¤ģ •ģ„ ģ—½ė‹ˆė‹¤" msgid "Opens password reset form" msgstr "ė¹„ė°€ė²ˆķ˜ø ģž¬ģ„¤ģ • ģ–‘ģ‹ģ„ ģ—½ė‹ˆė‹¤" +#: src/view/com/home/HomeHeaderLayout.web.tsx:60 #: src/view/screens/Feeds.tsx:356 msgid "Opens screen to edit Saved Feeds" msgstr "ģ €ģž„ėœ ķ”¼ė“œė„¼ ķŽøģ§‘ķ•  수 ģžˆėŠ” ķ™”ė©“ģ„ ģ—½ė‹ˆė‹¤" @@ -2818,7 +2901,7 @@ msgstr "ģ“ ģ½˜ķ…ģø  경고가 ģž˜ėŖ» ģ ģš©ė˜ģ—ˆė‹¤ź³  ģƒź°ķ•˜ėŠ” ģ“ģœ ė„¼ msgid "Please Verify Your Email" msgstr "ģ“ė©”ģ¼ ģøģ¦ķ•˜źø°" -#: src/view/com/composer/Composer.tsx:215 +#: src/view/com/composer/Composer.tsx:222 msgid "Please wait for your link card to finish loading" msgstr "링크 ģ¹“ė“œė„¼ ģ™„ģ „ķžˆ 불러올 ė•Œź¹Œģ§€ źø°ė‹¤ė ¤ģ£¼ģ„øģš”" @@ -2830,8 +2913,8 @@ msgstr "ģ •ģ¹˜" msgid "Porn" msgstr "ķ¬ė„“ė…ø" -#: src/view/com/composer/Composer.tsx:350 -#: src/view/com/composer/Composer.tsx:358 +#: src/view/com/composer/Composer.tsx:357 +#: src/view/com/composer/Composer.tsx:365 msgctxt "action" msgid "Post" msgstr "ź²Œģ‹œķ•˜źø°" @@ -2841,7 +2924,7 @@ msgctxt "description" msgid "Post" msgstr "ź²Œģ‹œė¬¼" -#: src/view/com/post-thread/PostThreadItem.tsx:173 +#: src/view/com/post-thread/PostThreadItem.tsx:175 msgid "Post by {0}" msgstr "{0} ė‹˜ģ˜ ź²Œģ‹œė¬¼" @@ -2851,11 +2934,11 @@ msgstr "{0} ė‹˜ģ˜ ź²Œģ‹œė¬¼" msgid "Post by @{0}" msgstr "@{0} ė‹˜ģ˜ ź²Œģ‹œė¬¼" -#: src/view/com/util/forms/PostDropdownBtn.tsx:88 +#: src/view/com/util/forms/PostDropdownBtn.tsx:90 msgid "Post deleted" msgstr "ź²Œģ‹œė¬¼ ģ‚­ģ œėØ" -#: src/view/com/post-thread/PostThread.tsx:461 +#: src/view/com/post-thread/PostThread.tsx:462 msgid "Post hidden" msgstr "ź²Œģ‹œė¬¼ ģˆØź¹€" @@ -2867,14 +2950,22 @@ msgstr "ź²Œģ‹œė¬¼ ģ–øģ–“" msgid "Post Languages" msgstr "ź²Œģ‹œė¬¼ ģ–øģ–“" -#: src/view/com/post-thread/PostThread.tsx:513 +#: src/view/com/post-thread/PostThread.tsx:514 msgid "Post not found" msgstr "ź²Œģ‹œė¬¼ģ„ ģ°¾ģ„ 수 ģ—†ģŒ" +#: src/components/TagMenu/index.tsx:257 +msgid "posts" +msgstr "" + #: src/view/screens/Profile.tsx:180 msgid "Posts" msgstr "ź²Œģ‹œė¬¼" +#: src/components/dialogs/MutedWords.tsx:77 +msgid "Posts can be muted based on their text, their tags, or both." +msgstr "" + #: src/view/com/posts/FeedErrorMessage.tsx:64 msgid "Posts hidden" msgstr "ź²Œģ‹œė¬¼ 숨겨짐" @@ -2939,11 +3030,11 @@ msgstr "ģ¼ź“„ ė®¤ķŠøķ•˜ź±°ė‚˜ 차단할 수 ģžˆėŠ” ź³µź°œģ ģ“ź³  공유 ź°€ msgid "Public, shareable lists which can drive feeds." msgstr "ķ”¼ė“œė„¼ ķƒģƒ‰ķ•  수 ģžˆėŠ” ź³µź°œģ ģ“ź³  공유 ź°€ėŠ„ķ•œ ėŖ©ė”ģž…ė‹ˆė‹¤." -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish post" msgstr "ź²Œģ‹œė¬¼ ź²Œģ‹œķ•˜źø°" -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish reply" msgstr "답글 ź²Œģ‹œķ•˜źø°" @@ -2977,6 +3068,7 @@ msgstr "ģ¶”ģ²œ ķ”¼ė“œ" msgid "Recommended Users" msgstr "ģ¶”ģ²œ ģ‚¬ģš©ģž" +#: src/components/dialogs/MutedWords.tsx:249 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/SelfLabel.tsx:83 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -3014,6 +3106,10 @@ msgstr "ģ“ėÆøģ§€ 제거" msgid "Remove image preview" msgstr "ģ“ėÆøģ§€ 미리볓기 제거" +#: src/components/dialogs/MutedWords.tsx:294 +msgid "Remove mute word from your list" +msgstr "" + #: src/view/com/modals/Repost.tsx:47 msgid "Remove repost" msgstr "ģž¬ź²Œģ‹œė„¼ ģ·Øģ†Œķ•©ė‹ˆė‹¤" @@ -3048,7 +3144,7 @@ msgstr "답글" msgid "Replies to this thread are disabled" msgstr "ģ“ ģŠ¤ė ˆė“œģ— ėŒ€ķ•œ ė‹µźø€ģ“ ė¹„ķ™œģ„±ķ™”ė©ė‹ˆė‹¤." -#: src/view/com/composer/Composer.tsx:348 +#: src/view/com/composer/Composer.tsx:355 msgctxt "action" msgid "Reply" msgstr "답글" @@ -3058,7 +3154,7 @@ msgid "Reply Filters" msgstr "답글 ķ•„ķ„°" #: src/view/com/post/Post.tsx:167 -#: src/view/com/posts/FeedItem.tsx:285 +#: src/view/com/posts/FeedItem.tsx:287 msgctxt "description" msgid "Reply to <0/>" msgstr "<0/> ė‹˜ģ—ź²Œ ė³“ė‚“ėŠ” 답글" @@ -3080,7 +3176,7 @@ msgid "Report List" msgstr "리스트 ģ‹ ź³ " #: src/view/com/modals/report/SendReportButton.tsx:37 -#: src/view/com/util/forms/PostDropdownBtn.tsx:239 +#: src/view/com/util/forms/PostDropdownBtn.tsx:255 msgid "Report post" msgstr "ź²Œģ‹œė¬¼ ģ‹ ź³ " @@ -3105,11 +3201,11 @@ msgstr "ģž¬ź²Œģ‹œ ė˜ėŠ” ź²Œģ‹œė¬¼ ģøģš©" msgid "Reposted By" msgstr "ģž¬ź²Œģ‹œķ•œ ģ‚¬ģš©ģž" -#: src/view/com/posts/FeedItem.tsx:205 +#: src/view/com/posts/FeedItem.tsx:207 msgid "Reposted by {0}" msgstr "{0} ė‹˜ģ“ ģž¬ź²Œģ‹œķ•Ø" -#: src/view/com/posts/FeedItem.tsx:222 +#: src/view/com/posts/FeedItem.tsx:224 msgid "Reposted by <0/>" msgstr "<0/> ė‹˜ģ“ ģž¬ź²Œģ‹œķ•Ø" @@ -3117,7 +3213,7 @@ msgstr "<0/> ė‹˜ģ“ ģž¬ź²Œģ‹œķ•Ø" msgid "reposted your post" msgstr "ė‹˜ģ“ ė‚“ ź²Œģ‹œė¬¼ģ„ ģž¬ź²Œģ‹œķ–ˆģŠµė‹ˆė‹¤" -#: src/view/com/post-thread/PostThreadItem.tsx:186 +#: src/view/com/post-thread/PostThreadItem.tsx:188 msgid "Reposts of this post" msgstr "ģ“ ź²Œģ‹œė¬¼ģ˜ ģž¬ź²Œģ‹œ" @@ -3268,9 +3364,9 @@ msgstr "ė§Ø ģœ„ė”œ 스크딤" #: src/view/com/modals/ListAddRemoveUsers.tsx:75 #: src/view/com/util/forms/SearchInput.tsx:67 #: src/view/com/util/forms/SearchInput.tsx:79 -#: src/view/screens/Search/Search.tsx:418 -#: src/view/screens/Search/Search.tsx:645 -#: src/view/screens/Search/Search.tsx:663 +#: src/view/screens/Search/Search.tsx:419 +#: src/view/screens/Search/Search.tsx:668 +#: src/view/screens/Search/Search.tsx:686 #: src/view/shell/bottom-bar/BottomBar.tsx:159 #: src/view/shell/desktop/LeftNav.tsx:324 #: src/view/shell/desktop/Search.tsx:214 @@ -3280,11 +3376,19 @@ msgstr "ė§Ø ģœ„ė”œ 스크딤" msgid "Search" msgstr "ź²€ģƒ‰" -#: src/view/screens/Search/Search.tsx:712 +#: src/view/screens/Search/Search.tsx:735 #: src/view/shell/desktop/Search.tsx:255 msgid "Search for \"{query}\"" msgstr "\"{query}\"에 ėŒ€ķ•œ ź²€ģƒ‰ ź²°ź³¼" +#: src/components/TagMenu/index.tsx:145 +msgid "Search for all posts by @{authorHandle} with tag {tag}" +msgstr "" + +#: src/components/TagMenu/index.tsx:90 +msgid "Search for all posts with tag {tag}" +msgstr "" + #: src/view/com/auth/LoggedOut.tsx:104 #: src/view/com/auth/LoggedOut.tsx:105 #: src/view/com/modals/ListAddRemoveUsers.tsx:70 @@ -3295,6 +3399,22 @@ msgstr "ģ‚¬ģš©ģž ź²€ģƒ‰ķ•˜źø°" msgid "Security Step Required" msgstr "ė³“ģ•ˆ 단계 ķ•„ģš”" +#: src/components/TagMenu/index.web.tsx:50 +msgid "See {truncatedTag} posts" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:67 +msgid "See {truncatedTag} posts by user" +msgstr "" + +#: src/components/TagMenu/index.tsx:128 +msgid "See <0>{tag} posts" +msgstr "" + +#: src/components/TagMenu/index.tsx:189 +msgid "See <0>{tag} posts by this user" +msgstr "" + #: src/view/screens/SavedFeeds.tsx:163 msgid "See this guide" msgstr "ģ“ ź°€ģ“ė“œ" @@ -3500,7 +3620,7 @@ msgid "Share" msgstr "공유" #: src/view/com/profile/ProfileHeader.tsx:295 -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 #: src/view/screens/ProfileList.tsx:418 msgid "Share" msgstr "공유" @@ -3533,9 +3653,9 @@ msgstr "{0} ģž„ė² ė“œ ķ‘œģ‹œ" msgid "Show follows similar to {0}" msgstr "{0} ė‹˜ź³¼ ė¹„ģŠ·ķ•œ ķŒ”ė”œģš° ķ‘œģ‹œ" -#: src/view/com/post-thread/PostThreadItem.tsx:532 -#: src/view/com/post/Post.tsx:196 -#: src/view/com/posts/FeedItem.tsx:359 +#: src/view/com/post-thread/PostThreadItem.tsx:538 +#: src/view/com/post/Post.tsx:198 +#: src/view/com/posts/FeedItem.tsx:363 msgid "Show More" msgstr "ė” 볓기" @@ -3703,7 +3823,7 @@ msgstr "ģ†Œķ”„ķŠøģ›Øģ–“ 개발" msgid "Something went wrong. Check your email and try again." msgstr "ė¬øģ œź°€ ė°œģƒķ–ˆģŠµė‹ˆė‹¤. ģ“ė©”ģ¼ģ„ ķ™•ģøķ•œ 후 ė‹¤ģ‹œ ģ‹œė„ķ•˜ģ„øģš”." -#: src/App.native.tsx:61 +#: src/App.native.tsx:63 msgid "Sorry! Your session expired. Please log in again." msgstr "ģ£„ģ†”ķ•©ė‹ˆė‹¤. ģ„øģ…˜ģ“ ė§Œė£Œė˜ģ—ˆģŠµė‹ˆė‹¤. ė‹¤ģ‹œ ė”œź·øģøķ•“ ģ£¼ģ„øģš”." @@ -3761,7 +3881,7 @@ msgstr "{0} ķ”¼ė“œ źµ¬ė…ķ•˜źø°" msgid "Subscribe to this list" msgstr "ģ“ 리스트 źµ¬ė…ķ•˜źø°" -#: src/view/screens/Search/Search.tsx:373 +#: src/view/screens/Search/Search.tsx:374 msgid "Suggested Follows" msgstr "ķŒ”ė”œģš° ģ¶”ģ²œ" @@ -3805,6 +3925,14 @@ msgstr "ģ‹œģŠ¤ķ…œ" msgid "System log" msgstr "ģ‹œģŠ¤ķ…œ 딜그" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "tag" +msgstr "" + +#: src/components/TagMenu/index.tsx:74 +msgid "Tag menu: {tag}" +msgstr "" + #: src/view/com/modals/crop-image/CropImage.web.tsx:112 msgid "Tall" msgstr "ģ„øė”œ" @@ -3828,6 +3956,10 @@ msgstr "ģ“ģš©ģ•½ź“€" msgid "Terms of Service" msgstr "ģ„œė¹„ģŠ¤ ģ“ģš©ģ•½ź“€" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "text" +msgstr "" + #: src/view/com/modals/AppealLabel.tsx:70 #: src/view/com/modals/report/InputIssueDetails.tsx:51 msgid "Text input field" @@ -3853,7 +3985,7 @@ msgstr "ģ €ģž‘ź¶Œ ģ •ģ±…ģ„ <0/>(으)딜 ģ“ė™ķ–ˆģŠµė‹ˆė‹¤" msgid "The following steps will help customize your Bluesky experience." msgstr "ė‹¤ģŒ ė‹Øź³„ėŠ” Bluesky ķ™˜ź²½ģ„ ė§žģ¶¤ ģ„¤ģ •ķ•˜ėŠ” ė° ė„ģ›€ģ“ ė©ė‹ˆė‹¤." -#: src/view/com/post-thread/PostThread.tsx:516 +#: src/view/com/post-thread/PostThread.tsx:517 msgid "The post may have been deleted." msgstr "ź²Œģ‹œė¬¼ģ“ ģ‚­ģ œė˜ģ—ˆģ„ 수 ģžˆģŠµė‹ˆė‹¤." @@ -4019,7 +4151,7 @@ msgstr "ģ“ ė¦¬ģŠ¤ķŠøėŠ” 비얓 ģžˆģŠµė‹ˆė‹¤." msgid "This name is already in use" msgstr "ģ“ ģ“ė¦„ģ€ ģ“ėÆø ģ‚¬ģš© ģ¤‘ģž…ė‹ˆė‹¤" -#: src/view/com/post-thread/PostThreadItem.tsx:123 +#: src/view/com/post-thread/PostThreadItem.tsx:125 msgid "This post has been deleted." msgstr "ģ“ ź²Œģ‹œė¬¼ģ€ ģ‚­ģ œė˜ģ—ˆģŠµė‹ˆė‹¤." @@ -4043,7 +4175,11 @@ msgstr "" msgid "This warning is only available for posts with media attached." msgstr "ģ“ ź²½ź³ ėŠ” 미디얓가 ģ²Øė¶€ėœ ź²Œģ‹œė¬¼ģ—ė§Œ ģ‚¬ģš©ķ•  수 ģžˆģŠµė‹ˆė‹¤." -#: src/view/com/util/forms/PostDropdownBtn.tsx:221 +#: src/components/dialogs/MutedWords.tsx:236 +msgid "This will delete {0} from your muted words. You can always add it back later." +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:237 msgid "This will hide this post from your feeds." msgstr "ķ”¼ė“œģ—ģ„œ ģ“ ź²Œģ‹œė¬¼ģ„ ģˆØź¹ė‹ˆė‹¤." @@ -4060,6 +4196,10 @@ msgstr "ģŠ¤ė ˆė“œ ėŖØė“œ" msgid "Threads Preferences" msgstr "ģŠ¤ė ˆė“œ 설정" +#: src/components/dialogs/MutedWords.tsx:95 +msgid "Toggle between muted word options." +msgstr "" + #: src/view/com/util/forms/DropdownButton.tsx:246 msgid "Toggle dropdown" msgstr "ė“œė”­ė‹¤ģš“ ģ—“źø° ė° ė‹«źø°" @@ -4068,9 +4208,9 @@ msgstr "ė“œė”­ė‹¤ģš“ ģ—“źø° ė° ė‹«źø°" msgid "Transformations" msgstr "ė³€ķ˜•" -#: src/view/com/post-thread/PostThreadItem.tsx:679 -#: src/view/com/post-thread/PostThreadItem.tsx:681 -#: src/view/com/util/forms/PostDropdownBtn.tsx:154 +#: src/view/com/post-thread/PostThreadItem.tsx:685 +#: src/view/com/post-thread/PostThreadItem.tsx:687 +#: src/view/com/util/forms/PostDropdownBtn.tsx:156 msgid "Translate" msgstr "ė²ˆģ—­" @@ -4135,15 +4275,24 @@ msgstr "ģ•„ģ‰½ģ§€ė§Œ ź³„ģ •ģ„ ė§Œė“¤ 수 ģžˆėŠ” ģš”ź±“ģ„ ģ¶©ģ”±ķ•˜ģ§€ ėŖ»ķ–ˆ msgid "Unlike" msgstr "ģ¢‹ģ•„ģš” ģ·Øģ†Œ" +#: src/components/TagMenu/index.tsx:253 #: src/view/screens/ProfileList.tsx:597 msgid "Unmute" msgstr "ģ–øė®¤ķŠø" +#: src/components/TagMenu/index.web.tsx:90 +msgid "Unmute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:326 msgid "Unmute Account" msgstr "계정 ģ–øė®¤ķŠø" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/TagMenu/index.tsx:210 +msgid "Unmute all {tag} posts" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Unmute thread" msgstr "ģŠ¤ė ˆė“œ ģ–øė®¤ķŠø" @@ -4340,6 +4489,10 @@ msgstr "즐거욓 ģ‹œź°„ ė˜ģ‹œźø° ė°”ėžė‹ˆė‹¤. Blueskyģ˜ ė‹¤ģŒ ķŠ¹ģ§•ģ„ źø° msgid "We ran out of posts from your follows. Here's the latest from <0/>." msgstr "ķŒ”ė”œģš°ķ•œ ģ‚¬ģš©ģžģ˜ ź²Œģ‹œė¬¼ģ“ ė¶€ģ”±ķ•©ė‹ˆė‹¤. ėŒ€ģ‹  <0/>ģ˜ ģµœģ‹  ź²Œģ‹œė¬¼ģ„ ķ‘œģ‹œķ•©ė‹ˆė‹¤." +#: src/components/dialogs/MutedWords.tsx:161 +msgid "We recommend avoiding common words that appear in many posts, since it can result in no posts being shown." +msgstr "" + #: src/screens/Onboarding/StepAlgoFeeds/index.tsx:124 msgid "We recommend our \"Discover\" feed:" msgstr "\"Discover\" ķ”¼ė“œė„¼ ź¶Œģž„ķ•©ė‹ˆė‹¤:" @@ -4368,7 +4521,11 @@ msgstr "당신과 ķ•Øź»˜ķ•˜ź²Œ ė˜ģ–“ 정말 źø°ģ˜ė„¤ģš”!" msgid "We're sorry, but we were unable to resolve this list. If this persists, please contact the list creator, @{handleOrDid}." msgstr "ģ£„ģ†”ķ•˜ģ§€ė§Œ ģ“ 리스트넼 불러올 수 ģ—†ģŠµė‹ˆė‹¤. ģ“ ė¬øģ œź°€ ź³„ģ†ė˜ė©“ 리스트 ģž‘ģ„±ģžģø @{handleOrDid}ģ—ź²Œ ė¬øģ˜ķ•˜ģ„øģš”." -#: src/view/screens/Search/Search.tsx:253 +#: src/components/dialogs/MutedWords.tsx:182 +msgid "We're sorry, but we weren't able to load your muted words at this time. Please try again." +msgstr "" + +#: src/view/screens/Search/Search.tsx:254 msgid "We're sorry, but your search could not be completed. Please try again in a few minutes." msgstr "ģ£„ģ†”ķ•˜ģ§€ė§Œ ź²€ģƒ‰ģ„ ģ™„ė£Œķ•  수 ģ—†ģŠµė‹ˆė‹¤. ėŖ‡ ė¶„ 후에 ė‹¤ģ‹œ ģ‹œė„ķ•“ ģ£¼ģ„øģš”." @@ -4389,7 +4546,7 @@ msgid "What is the issue with this {collectionName}?" msgstr "ģ“ {collectionName}에 ģ–“ė–¤ ė¬øģ œź°€ ģžˆė‚˜ģš”?" #: src/view/com/auth/SplashScreen.tsx:59 -#: src/view/com/composer/Composer.tsx:279 +#: src/view/com/composer/Composer.tsx:286 msgid "What's up?" msgstr "묓슨 ģ¼ģ“ ģ¼ģ–“ė‚˜ź³  ģžˆė‚˜ģš”?" @@ -4410,11 +4567,11 @@ msgstr "ė‹µźø€ģ„ 달 수 ģžˆėŠ” ģ‚¬ėžŒ" msgid "Wide" msgstr "ź°€ė”œ" -#: src/view/com/composer/Composer.tsx:415 +#: src/view/com/composer/Composer.tsx:422 msgid "Write post" msgstr "ź²Œģ‹œė¬¼ ģž‘ģ„±" -#: src/view/com/composer/Composer.tsx:278 +#: src/view/com/composer/Composer.tsx:285 #: src/view/com/composer/Prompt.tsx:33 msgid "Write your reply" msgstr "답글 ģž‘ģ„±ķ•˜źø°" @@ -4471,7 +4628,7 @@ msgstr "ģ €ģž„ėœ ķ”¼ė“œź°€ ģ—†ģŠµė‹ˆė‹¤!" msgid "You don't have any saved feeds." msgstr "ģ €ģž„ėœ ķ”¼ė“œź°€ ģ—†ģŠµė‹ˆė‹¤." -#: src/view/com/post-thread/PostThread.tsx:464 +#: src/view/com/post-thread/PostThread.tsx:465 msgid "You have blocked the author or you have been blocked by the author." msgstr "ģž‘ģ„±ģžė„¼ ģ°Øė‹Øķ–ˆź±°ė‚˜ ģž‘ģ„±ģžź°€ ė‚˜ė„¼ ģ°Øė‹Øķ–ˆģŠµė‹ˆė‹¤." @@ -4511,6 +4668,10 @@ msgstr "아직 앱 ė¹„ė°€ė²ˆķ˜øė„¼ ģƒģ„±ķ•˜ģ§€ ģ•Šģ•˜ģŠµė‹ˆė‹¤. ģ•„ėž˜ ė²„ķŠ¼ msgid "You have not muted any accounts yet. To mute an account, go to their profile and selected \"Mute account\" from the menu on their account." msgstr "아직 ģ–“ė–¤ ź³„ģ •ė„ ė®¤ķŠøķ•˜ģ§€ ģ•Šģ•˜ģŠµė‹ˆė‹¤. ź³„ģ •ģ„ ė®¤ķŠøķ•˜ė ¤ė©“ 핓당 ź³„ģ •ģ˜ ķ”„ė”œķ•„ė”œ ģ“ė™ķ•˜ģ—¬ 계정 ė©”ė‰“ģ—ģ„œ \"계정 뮤트\"넼 ģ„ ķƒķ•˜ģ„øģš”." +#: src/components/dialogs/MutedWords.tsx:202 +msgid "You haven't muted any words or tags yet" +msgstr "" + #: src/view/com/modals/ContentFilteringSettings.tsx:175 msgid "You must be 18 or older to enable adult content." msgstr "ģ„±ģø ģ½˜ķ…ģø ė„¼ ķ™œģ„±ķ™”ķ•˜ė ¤ė©“ 18세 ģ“ģƒģ“ģ–“ģ•¼ ķ•©ė‹ˆė‹¤." @@ -4519,11 +4680,11 @@ msgstr "ģ„±ģø ģ½˜ķ…ģø ė„¼ ķ™œģ„±ķ™”ķ•˜ė ¤ė©“ 18세 ģ“ģƒģ“ģ–“ģ•¼ ķ•©ė‹ˆė‹¤." msgid "You must be 18 years or older to enable adult content" msgstr "ģ„±ģø ģ½˜ķ…ģø ė„¼ ģ‚¬ģš©ķ•˜ė ¤ė©“ 만 18세 ģ“ģƒģ“ģ–“ģ•¼ ķ•©ė‹ˆė‹¤." -#: src/view/com/util/forms/PostDropdownBtn.tsx:127 +#: src/view/com/util/forms/PostDropdownBtn.tsx:129 msgid "You will no longer receive notifications for this thread" msgstr "ģ“ ģŠ¤ė ˆė“œģ— ėŒ€ķ•œ ģ•Œė¦¼ģ„ ė” ģ“ģƒ 받지 ģ•ŠģŠµė‹ˆė‹¤" -#: src/view/com/util/forms/PostDropdownBtn.tsx:130 +#: src/view/com/util/forms/PostDropdownBtn.tsx:132 msgid "You will now receive notifications for this thread" msgstr "ģ“ģ œ ģ“ ģŠ¤ė ˆė“œģ— ėŒ€ķ•œ ģ•Œė¦¼ģ„ ė°›ģŠµė‹ˆė‹¤" @@ -4609,11 +4770,15 @@ msgstr "ė‚“ 전첓 핸들: <0>@{0}" #~ msgid "Your invite codes are hidden when logged in using an App Password" #~ msgstr "앱 ė¹„ė°€ė²ˆķ˜øė„¼ ģ‚¬ģš©ķ•˜ģ—¬ ė”œź·øģøķ•˜ė©“ ģ“ˆėŒ€ ģ½”ė“œź°€ ģˆØź²Øģ§‘ė‹ˆė‹¤" +#: src/components/dialogs/MutedWords.tsx:173 +msgid "Your muted words" +msgstr "" + #: src/view/com/modals/ChangePassword.tsx:155 msgid "Your password has been changed successfully!" msgstr "" -#: src/view/com/composer/Composer.tsx:267 +#: src/view/com/composer/Composer.tsx:274 msgid "Your post has been published" msgstr "ź²Œģ‹œė¬¼ģ„ ź²Œģ‹œķ–ˆģŠµė‹ˆė‹¤" @@ -4628,7 +4793,7 @@ msgstr "ź²Œģ‹œė¬¼, ģ¢‹ģ•„ģš”, 차단 ėŖ©ė”ģ€ ź³µź°œė©ė‹ˆė‹¤. 뮤트 ėŖ©ė”ģ€ msgid "Your profile" msgstr "ė‚“ ķ”„ė”œķ•„" -#: src/view/com/composer/Composer.tsx:266 +#: src/view/com/composer/Composer.tsx:273 msgid "Your reply has been published" msgstr "ė‚“ ė‹µźø€ģ„ ź²Œģ‹œķ–ˆģŠµė‹ˆė‹¤" diff --git a/src/locale/locales/pt-BR/messages.po b/src/locale/locales/pt-BR/messages.po index 9178214dd4..ff5d7e55dc 100644 --- a/src/locale/locales/pt-BR/messages.po +++ b/src/locale/locales/pt-BR/messages.po @@ -76,7 +76,7 @@ msgid "A new version of the app is available. Please update to continue using th msgstr "Uma nova versĆ£o do aplicativo estĆ” disponĆ­vel. Por favor, atualize para continuar usando o aplicativo." #: src/view/com/util/ViewHeader.tsx:83 -#: src/view/screens/Search/Search.tsx:624 +#: src/view/screens/Search/Search.tsx:647 msgid "Access navigation links and settings" msgstr "Acessar links de navegação e configuraƧƵes" @@ -127,6 +127,7 @@ msgstr "Conta desbloqueada" msgid "Account unmuted" msgstr "Conta dessilenciada" +#: src/components/dialogs/MutedWords.tsx:147 #: src/view/com/auth/onboarding/RecommendedFeedsItem.tsx:150 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -168,14 +169,22 @@ msgstr "Adicionar detalhes" msgid "Add details to report" msgstr "Adicionar detalhes Ć  denĆŗncia" -#: src/view/com/composer/Composer.tsx:446 +#: src/view/com/composer/Composer.tsx:453 msgid "Add link card" msgstr "Adicionar prĆ©via de link" -#: src/view/com/composer/Composer.tsx:451 +#: src/view/com/composer/Composer.tsx:458 msgid "Add link card:" msgstr "Adicionar prĆ©via de link:" +#: src/components/dialogs/MutedWords.tsx:140 +msgid "Add mute word for configured settings" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:74 +msgid "Add muted words and tags" +msgstr "" + #: src/view/com/modals/ChangeHandle.tsx:417 msgid "Add the following DNS record to your domain:" msgstr "Adicione o seguinte registro DNS ao seu domĆ­nio:" @@ -299,7 +308,7 @@ msgstr "ConfiguraƧƵes de Senha de Aplicativo" msgid "App Passwords" msgstr "Senhas de Aplicativos" -#: src/view/com/util/forms/PostDropdownBtn.tsx:279 +#: src/view/com/util/forms/PostDropdownBtn.tsx:295 msgid "Appeal content warning" msgstr "Contestar aviso de conteĆŗdo" @@ -323,15 +332,16 @@ msgstr "AparĆŖncia" msgid "Are you sure you want to delete the app password \"{name}\"?" msgstr "Tem certeza de que deseja excluir a senha do aplicativo \"{name}\"?" -#: src/view/com/composer/Composer.tsx:143 +#: src/view/com/composer/Composer.tsx:150 msgid "Are you sure you'd like to discard this draft?" msgstr "Tem certeza que deseja descartar este rascunho?" +#: src/components/dialogs/MutedWords.tsx:233 #: src/view/screens/ProfileList.tsx:365 msgid "Are you sure?" msgstr "Tem certeza?" -#: src/view/com/util/forms/PostDropdownBtn.tsx:262 +#: src/view/com/util/forms/PostDropdownBtn.tsx:278 msgid "Are you sure? This cannot be undone." msgstr "Tem certeza? Esta ação nĆ£o poderĆ” ser desfeita." @@ -353,15 +363,15 @@ msgstr "Nudez artĆ­stica ou nĆ£o erótica." #: src/view/com/auth/login/LoginForm.tsx:259 #: src/view/com/auth/login/SetNewPasswordForm.tsx:179 #: src/view/com/modals/report/InputIssueDetails.tsx:46 -#: src/view/com/post-thread/PostThread.tsx:471 -#: src/view/com/post-thread/PostThread.tsx:521 -#: src/view/com/post-thread/PostThread.tsx:529 +#: src/view/com/post-thread/PostThread.tsx:472 +#: src/view/com/post-thread/PostThread.tsx:522 +#: src/view/com/post-thread/PostThread.tsx:530 #: src/view/com/profile/ProfileHeader.tsx:649 #: src/view/com/util/ViewHeader.tsx:81 msgid "Back" msgstr "Voltar" -#: src/view/com/post-thread/PostThread.tsx:479 +#: src/view/com/post-thread/PostThread.tsx:480 msgctxt "action" msgid "Back" msgstr "Voltar" @@ -409,7 +419,7 @@ msgstr "Bloquear esta Lista" msgid "Blocked" msgstr "Bloqueado" -#: src/view/screens/Moderation.tsx:123 +#: src/view/screens/Moderation.tsx:142 msgid "Blocked accounts" msgstr "Contas bloqueadas" @@ -468,7 +478,7 @@ msgstr "Bluesky Ć© pĆŗblico." msgid "Bluesky uses invites to build a healthier community. If you don't know anybody with an invite, you can sign up for the waitlist and we'll send one soon." msgstr "O Bluesky usa convites para criar uma comunidade mais saudĆ”vel. Se vocĆŖ nĆ£o conhece ninguĆ©m que tenha um convite, inscreva-se na lista de espera e em breve enviaremos um para vocĆŖ." -#: src/view/screens/Moderation.tsx:226 +#: src/view/screens/Moderation.tsx:245 msgid "Bluesky will not show your profile and posts to logged-out users. Other apps may not honor this request. This does not make your account private." msgstr "O Bluesky nĆ£o mostrarĆ” seu perfil e publicaƧƵes para usuĆ”rios desconectados. Outros aplicativos podem nĆ£o honrar esta solicitação. Isso nĆ£o torna a sua conta privada." @@ -520,8 +530,8 @@ msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must msgstr "Só pode conter letras, nĆŗmeros, espaƧos, traƧos e sublinhados. Deve ter pelo menos 4 caracteres, mas nĆ£o mais de 32 caracteres." #: src/components/Prompt.tsx:91 -#: src/view/com/composer/Composer.tsx:300 -#: src/view/com/composer/Composer.tsx:305 +#: src/view/com/composer/Composer.tsx:307 +#: src/view/com/composer/Composer.tsx:312 #: src/view/com/modals/ChangeEmail.tsx:218 #: src/view/com/modals/ChangeEmail.tsx:220 #: src/view/com/modals/ChangePassword.tsx:265 @@ -535,7 +545,7 @@ msgstr "Só pode conter letras, nĆŗmeros, espaƧos, traƧos e sublinhados. Deve #: src/view/com/modals/VerifyEmail.tsx:247 #: src/view/com/modals/VerifyEmail.tsx:253 #: src/view/com/modals/Waitlist.tsx:142 -#: src/view/screens/Search/Search.tsx:693 +#: src/view/screens/Search/Search.tsx:716 #: src/view/shell/desktop/Search.tsx:238 msgid "Cancel" msgstr "Cancelar" @@ -686,7 +696,7 @@ msgid "Clear all storage data (restart after this)" msgstr "Limpar todos os dados de armazenamento (reinicie em seguida)" #: src/view/com/util/forms/SearchInput.tsx:88 -#: src/view/screens/Search/Search.tsx:674 +#: src/view/screens/Search/Search.tsx:697 msgid "Clear search query" msgstr "Limpar busca" @@ -694,6 +704,11 @@ msgstr "Limpar busca" msgid "click here" msgstr "clique aqui" +#: src/components/RichText.tsx:189 +#: src/components/TagMenu/index.web.tsx:125 +msgid "Click here to open tag menu for {tag}" +msgstr "" + #: src/screens/Onboarding/index.tsx:35 msgid "Climate" msgstr "Clima e tempo" @@ -724,11 +739,15 @@ msgstr "Fechar imagem" msgid "Close image viewer" msgstr "Fechar visualizador de imagens" -#: src/view/shell/index.web.tsx:49 +#: src/view/shell/index.web.tsx:51 msgid "Close navigation footer" msgstr "Fechar o painel de navegação" -#: src/view/shell/index.web.tsx:50 +#: src/components/TagMenu/index.tsx:266 +msgid "Close this dialog" +msgstr "" + +#: src/view/shell/index.web.tsx:52 msgid "Closes bottom navigation bar" msgstr "Fecha barra de navegação inferior" @@ -736,7 +755,7 @@ msgstr "Fecha barra de navegação inferior" msgid "Closes password update alert" msgstr "Fecha alerta de troca de senha" -#: src/view/com/composer/Composer.tsx:302 +#: src/view/com/composer/Composer.tsx:309 msgid "Closes post composer and discards post draft" msgstr "Fecha o editor de post e descarta o rascunho" @@ -769,7 +788,7 @@ msgstr "Completar e comeƧar a usar sua conta" msgid "Complete the challenge" msgstr "" -#: src/view/com/composer/Composer.tsx:417 +#: src/view/com/composer/Composer.tsx:424 msgid "Compose posts up to {MAX_GRAPHEME_LENGTH} characters in length" msgstr "Escreva posts de atĆ© {MAX_GRAPHEME_LENGTH} caracteres" @@ -833,7 +852,7 @@ msgstr "Conectando..." msgid "Contact support" msgstr "Contatar suporte" -#: src/view/screens/Moderation.tsx:81 +#: src/view/screens/Moderation.tsx:83 msgid "Content filtering" msgstr "Filtragem do conteĆŗdo" @@ -899,7 +918,7 @@ msgstr "VersĆ£o do aplicativo copiada" #: src/view/com/modals/AddAppPasswords.tsx:76 #: src/view/com/modals/InviteCodes.tsx:152 -#: src/view/com/util/forms/PostDropdownBtn.tsx:141 +#: src/view/com/util/forms/PostDropdownBtn.tsx:143 msgid "Copied to clipboard" msgstr "Copiado" @@ -915,7 +934,7 @@ msgstr "Copiar" msgid "Copy link to list" msgstr "Copiar link da lista" -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 msgid "Copy link to post" msgstr "Copiar link do post" @@ -923,7 +942,7 @@ msgstr "Copiar link do post" msgid "Copy link to profile" msgstr "Copiar link do perfil" -#: src/view/com/util/forms/PostDropdownBtn.tsx:168 +#: src/view/com/util/forms/PostDropdownBtn.tsx:170 msgid "Copy post text" msgstr "Copiar texto do post" @@ -979,7 +998,7 @@ msgstr "Criado por <0/>" msgid "Created by you" msgstr "Criado por vocĆŖ" -#: src/view/com/composer/Composer.tsx:448 +#: src/view/com/composer/Composer.tsx:455 msgid "Creates a card with a thumbnail. The card links to {url}" msgstr "Cria uma prĆ©via com miniatura. A prĆ©via faz um link para {url}" @@ -1056,11 +1075,11 @@ msgstr "Excluir minha conta" msgid "Delete My Account…" msgstr "Excluir minha conta…" -#: src/view/com/util/forms/PostDropdownBtn.tsx:257 +#: src/view/com/util/forms/PostDropdownBtn.tsx:273 msgid "Delete post" msgstr "Excluir post" -#: src/view/com/util/forms/PostDropdownBtn.tsx:261 +#: src/view/com/util/forms/PostDropdownBtn.tsx:277 msgid "Delete this post?" msgstr "Excluir este post?" @@ -1083,7 +1102,7 @@ msgstr "Descrição" #~ msgid "Developer Tools" #~ msgstr "Ferramentas de Desenvolvedor" -#: src/view/com/composer/Composer.tsx:211 +#: src/view/com/composer/Composer.tsx:218 msgid "Did you want to say anything?" msgstr "VocĆŖ gostaria de dizer alguma coisa?" @@ -1091,15 +1110,15 @@ msgstr "VocĆŖ gostaria de dizer alguma coisa?" msgid "Dim" msgstr "Menos escuro" -#: src/view/com/composer/Composer.tsx:144 +#: src/view/com/composer/Composer.tsx:151 msgid "Discard" msgstr "Descartar" -#: src/view/com/composer/Composer.tsx:138 +#: src/view/com/composer/Composer.tsx:145 msgid "Discard draft" msgstr "Descartar rascunho" -#: src/view/screens/Moderation.tsx:207 +#: src/view/screens/Moderation.tsx:226 msgid "Discourage apps from showing my account to logged-out users" msgstr "Desencorajar aplicativos a mostrar minha conta para usuĆ”rios deslogados" @@ -1178,7 +1197,7 @@ msgstr "" msgid "Download CAR file" msgstr "" -#: src/view/com/composer/text-input/TextInput.web.tsx:247 +#: src/view/com/composer/text-input/TextInput.web.tsx:249 msgid "Drop to add images" msgstr "Solte para adicionar imagens" @@ -1250,6 +1269,7 @@ msgstr "Editar perfil" msgid "Edit Profile" msgstr "Editar Perfil" +#: src/view/com/home/HomeHeaderLayout.web.tsx:59 #: src/view/screens/Feeds.tsx:355 msgid "Edit Saved Feeds" msgstr "Editar Feeds Salvos" @@ -1332,6 +1352,11 @@ msgstr "Fim do feed" msgid "Enter a name for this App Password" msgstr "Insira um nome para esta Senha de Aplicativo" +#: src/components/dialogs/MutedWords.tsx:87 +#: src/components/dialogs/MutedWords.tsx:88 +msgid "Enter a word or tag" +msgstr "" + #: src/view/com/modals/VerifyEmail.tsx:105 msgid "Enter Confirmation Code" msgstr "Insira o código de confirmação" @@ -1381,7 +1406,7 @@ msgstr "Digite seu nome de usuĆ”rio e senha" msgid "Error receiving captcha response." msgstr "" -#: src/view/screens/Search/Search.tsx:109 +#: src/view/screens/Search/Search.tsx:110 msgid "Error:" msgstr "Erro:" @@ -1452,7 +1477,7 @@ msgstr "NĆ£o foi possĆ­vel criar senha de aplicativo." msgid "Failed to create the list. Check your internet connection and try again." msgstr "NĆ£o foi possĆ­vel criar a lista. Por favor tente novamente." -#: src/view/com/util/forms/PostDropdownBtn.tsx:108 +#: src/view/com/util/forms/PostDropdownBtn.tsx:110 msgid "Failed to delete post, please try again" msgstr "NĆ£o foi possĆ­vel excluir o post, por favor tente novamente." @@ -1474,8 +1499,8 @@ msgid "Feed offline" msgstr "Feed offline" #: src/view/com/feeds/FeedPage.tsx:143 -msgid "Feed Preferences" -msgstr "PreferĆŖncias de Feeds" +#~ msgid "Feed Preferences" +#~ msgstr "PreferĆŖncias de Feeds" #: src/view/shell/desktop/RightNav.tsx:61 #: src/view/shell/Drawer.tsx:311 @@ -1523,11 +1548,11 @@ msgstr "Finalizando" msgid "Find accounts to follow" msgstr "Encontre contas para seguir" -#: src/view/screens/Search/Search.tsx:439 +#: src/view/screens/Search/Search.tsx:440 msgid "Find users on Bluesky" msgstr "Encontrar usuĆ”rios no Bluesky" -#: src/view/screens/Search/Search.tsx:437 +#: src/view/screens/Search/Search.tsx:438 msgid "Find users with the search tool on the right" msgstr "Encontre usuĆ”rios com a ferramenta de busca Ć  direita" @@ -1624,6 +1649,7 @@ msgid "Following {0}" msgstr "Seguindo {0}" #: src/Navigation.tsx:248 +#: src/view/com/home/HomeHeaderLayout.web.tsx:45 #: src/view/com/home/HomeHeaderLayoutMobile.tsx:83 #: src/view/screens/PreferencesFollowingFeed.tsx:104 #: src/view/screens/Settings/index.tsx:543 @@ -1663,7 +1689,7 @@ msgstr "Esqueci a senha" msgid "Forgot Password" msgstr "Esqueci a Senha" -#: src/view/com/posts/FeedItem.tsx:187 +#: src/view/com/posts/FeedItem.tsx:189 msgctxt "from-feed" msgid "From <0/>" msgstr "Por <0/>" @@ -1696,7 +1722,7 @@ msgstr "Voltar" msgid "Go back to previous step" msgstr "Voltar para o passo anterior" -#: src/view/screens/Search/Search.tsx:724 +#: src/view/screens/Search/Search.tsx:747 #: src/view/shell/desktop/Search.tsx:262 msgid "Go to @{queryMaybeHandle}" msgstr "Ir para @{queryMaybleHandle}" @@ -1713,6 +1739,10 @@ msgstr "Próximo" msgid "Handle" msgstr "UsuĆ”rio" +#: src/components/RichText.tsx:188 +msgid "Hashtag: {tag}" +msgstr "" + #: src/view/com/auth/create/CreateAccount.tsx:208 msgid "Having trouble?" msgstr "Precisa de ajuda?" @@ -1751,7 +1781,7 @@ msgctxt "action" msgid "Hide" msgstr "Esconder" -#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +#: src/view/com/util/forms/PostDropdownBtn.tsx:232 msgid "Hide post" msgstr "Ocultar post" @@ -1760,7 +1790,7 @@ msgstr "Ocultar post" msgid "Hide the content" msgstr "Esconder o conteĆŗdo" -#: src/view/com/util/forms/PostDropdownBtn.tsx:220 +#: src/view/com/util/forms/PostDropdownBtn.tsx:236 msgid "Hide this post?" msgstr "Ocultar este post?" @@ -1909,7 +1939,7 @@ msgstr "Insira sua senha" msgid "Input your user handle" msgstr "Insira o usuĆ”rio" -#: src/view/com/post-thread/PostThreadItem.tsx:224 +#: src/view/com/post-thread/PostThreadItem.tsx:226 msgid "Invalid or unsupported post record" msgstr "Post invĆ”lido" @@ -2011,7 +2041,7 @@ msgstr "Saiba Mais" msgid "Learn more about this warning" msgstr "Saiba mais sobre este aviso" -#: src/view/screens/Moderation.tsx:243 +#: src/view/screens/Moderation.tsx:262 msgid "Learn more about what is public on Bluesky." msgstr "Saiba mais sobre o que Ć© pĆŗblico no Bluesky." @@ -2087,7 +2117,7 @@ msgstr "curtiu seu post" msgid "Likes" msgstr "Curtidas" -#: src/view/com/post-thread/PostThreadItem.tsx:181 +#: src/view/com/post-thread/PostThreadItem.tsx:183 msgid "Likes on this post" msgstr "Curtidas neste post" @@ -2144,7 +2174,7 @@ msgstr "Carregar mais posts" msgid "Load new notifications" msgstr "Carregar novas notificaƧƵes" -#: src/view/com/feeds/FeedPage.tsx:181 +#: src/view/com/feeds/FeedPage.tsx:115 #: src/view/screens/Profile.tsx:440 #: src/view/screens/ProfileFeed.tsx:495 #: src/view/screens/ProfileList.tsx:681 @@ -2170,7 +2200,7 @@ msgstr "Registros" msgid "Log out" msgstr "Sair" -#: src/view/screens/Moderation.tsx:136 +#: src/view/screens/Moderation.tsx:155 msgid "Logged-out visibility" msgstr "Visibilidade do seu perfil" @@ -2182,6 +2212,10 @@ msgstr "Fazer login em uma conta que nĆ£o estĆ” listada" msgid "Make sure this is where you intend to go!" msgstr "Certifique-se de onde estĆ” indo!" +#: src/components/dialogs/MutedWords.tsx:71 +msgid "Manage your muted words and tags" +msgstr "" + #: src/view/com/auth/create/Step2.tsx:118 msgid "May not be longer than 253 characters" msgstr "" @@ -2203,7 +2237,7 @@ msgid "Mentioned users" msgstr "UsuĆ”rios mencionados" #: src/view/com/util/ViewHeader.tsx:81 -#: src/view/screens/Search/Search.tsx:623 +#: src/view/screens/Search/Search.tsx:646 msgid "Menu" msgstr "Menu" @@ -2212,7 +2246,7 @@ msgid "Message from server: {0}" msgstr "Mensagem do servidor: {0}" #: src/Navigation.tsx:115 -#: src/view/screens/Moderation.tsx:64 +#: src/view/screens/Moderation.tsx:66 #: src/view/screens/Settings/index.tsx:625 #: src/view/shell/desktop/LeftNav.tsx:397 #: src/view/shell/Drawer.tsx:511 @@ -2243,7 +2277,7 @@ msgstr "Lista de moderação criada" msgid "Moderation list updated" msgstr "Lista de moderação criada" -#: src/view/screens/Moderation.tsx:95 +#: src/view/screens/Moderation.tsx:114 msgid "Moderation lists" msgstr "Listas de moderação" @@ -2270,7 +2304,7 @@ msgstr "Mais feeds" msgid "More options" msgstr "Mais opƧƵes" -#: src/view/com/util/forms/PostDropdownBtn.tsx:299 +#: src/view/com/util/forms/PostDropdownBtn.tsx:315 msgid "More post options" msgstr "Mais opƧƵes do post" @@ -2282,6 +2316,14 @@ msgstr "Respostas mais curtidas primeiro" msgid "Must be at least 3 characters" msgstr "" +#: src/components/TagMenu/index.tsx:253 +msgid "Mute" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:91 +msgid "Mute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:327 msgid "Mute Account" msgstr "Silenciar Conta" @@ -2290,6 +2332,18 @@ msgstr "Silenciar Conta" msgid "Mute accounts" msgstr "Silenciar contas" +#: src/components/TagMenu/index.tsx:211 +msgid "Mute all {tag} posts" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:131 +msgid "Mute in tags only" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:116 +msgid "Mute in text & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:491 msgid "Mute list" msgstr "Lista de moderação" @@ -2302,15 +2356,27 @@ msgstr "Silenciar estas contas?" msgid "Mute this List" msgstr "Silenciar esta lista" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/dialogs/MutedWords.tsx:109 +msgid "Mute this word in post text and tags" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:124 +msgid "Mute this word in tags only" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Mute thread" msgstr "Silenciar thread" +#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +msgid "Mute words & tags" +msgstr "" + #: src/view/com/lists/ListCard.tsx:102 msgid "Muted" msgstr "Silenciada" -#: src/view/screens/Moderation.tsx:109 +#: src/view/screens/Moderation.tsx:128 msgid "Muted accounts" msgstr "Contas silenciadas" @@ -2323,6 +2389,10 @@ msgstr "Contas Silenciadas" msgid "Muted accounts have their posts removed from your feed and from your notifications. Mutes are completely private." msgstr "Contas silenciadas nĆ£o aparecem no seu feed ou nas suas notificaƧƵes. Suas contas silenciadas sĆ£o completamente privadas." +#: src/view/screens/Moderation.tsx:100 +msgid "Muted words & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:277 msgid "Muting is private. Muted accounts can interact with you, but you will not see their posts or receive notifications from them." msgstr "Silenciar Ć© privado. Contas silenciadas podem interagir com vocĆŖ, mas vocĆŖ nĆ£o verĆ” postagens ou receber notificaƧƵes delas." @@ -2386,6 +2456,10 @@ msgstr "Nunca perca o acesso aos seus seguidores e dados." msgid "Never lose access to your followers or data." msgstr "Nunca perca o acesso aos seus seguidores ou dados." +#: src/components/dialogs/MutedWords.tsx:244 +msgid "Nevermind" +msgstr "" + #: src/view/screens/Lists.tsx:76 msgctxt "action" msgid "New" @@ -2407,7 +2481,7 @@ msgstr "Nova senha" msgid "New Password" msgstr "Nova Senha" -#: src/view/com/feeds/FeedPage.tsx:192 +#: src/view/com/feeds/FeedPage.tsx:126 msgctxt "action" msgid "New post" msgstr "Novo post" @@ -2492,8 +2566,8 @@ msgid "No results found for \"{query}\"" msgstr "Nenhum resultado encontrado para \"{query}\"" #: src/view/com/modals/ListAddRemoveUsers.tsx:127 -#: src/view/screens/Search/Search.tsx:280 -#: src/view/screens/Search/Search.tsx:308 +#: src/view/screens/Search/Search.tsx:281 +#: src/view/screens/Search/Search.tsx:309 msgid "No results found for {query}" msgstr "Nenhum resultado encontrado para {query}" @@ -2519,7 +2593,7 @@ msgstr "NĆ£o encontrado" msgid "Not right now" msgstr "Agora nĆ£o" -#: src/view/screens/Moderation.tsx:233 +#: src/view/screens/Moderation.tsx:252 msgid "Note: Bluesky is an open and public network. This setting only limits the visibility of your content on the Bluesky app and website, and other apps may not respect this setting. Your content may still be shown to logged-out users by other apps and websites." msgstr "Nota: o Bluesky Ć© uma rede aberta e pĆŗblica. Esta configuração limita somente a visibilidade do seu conteĆŗdo no site e aplicativo do Bluesky, e outros aplicativos podem nĆ£o respeitar esta configuração. Seu conteĆŗdo ainda poderĆ” ser exibido para usuĆ”rios deslogados por outros aplicativos e sites." @@ -2557,7 +2631,7 @@ msgstr "Respostas mais antigas primeiro" msgid "Onboarding reset" msgstr "Resetar tutoriais" -#: src/view/com/composer/Composer.tsx:375 +#: src/view/com/composer/Composer.tsx:382 msgid "One or more images is missing alt text." msgstr "Uma ou mais imagens estĆ£o sem texto alternativo." @@ -2574,8 +2648,12 @@ msgstr "Opa!" msgid "Open" msgstr "Abrir" -#: src/view/com/composer/Composer.tsx:470 -#: src/view/com/composer/Composer.tsx:471 +#: src/view/screens/Moderation.tsx:75 +msgid "Open content filtering settings" +msgstr "" + +#: src/view/com/composer/Composer.tsx:477 +#: src/view/com/composer/Composer.tsx:478 msgid "Open emoji picker" msgstr "Abrir seletor de emojis" @@ -2583,6 +2661,10 @@ msgstr "Abrir seletor de emojis" msgid "Open links with in-app browser" msgstr "Abrir links no navegador interno" +#: src/view/screens/Moderation.tsx:92 +msgid "Open muted words settings" +msgstr "" + #: src/view/com/home/HomeHeaderLayoutMobile.tsx:49 msgid "Open navigation" msgstr "Abrir navegação" @@ -2659,6 +2741,7 @@ msgstr "Abre configuraƧƵes de moderação" msgid "Opens password reset form" msgstr "Abre o formulĆ”rio de redefinição de senha" +#: src/view/com/home/HomeHeaderLayout.web.tsx:60 #: src/view/screens/Feeds.tsx:356 msgid "Opens screen to edit Saved Feeds" msgstr "Abre a tela para editar feeds salvos" @@ -2839,7 +2922,7 @@ msgstr "Por favor, diga-nos por que vocĆŖ acha que este aviso de conteĆŗdo foi a msgid "Please Verify Your Email" msgstr "Por favor, verifique seu e-mail" -#: src/view/com/composer/Composer.tsx:215 +#: src/view/com/composer/Composer.tsx:222 msgid "Please wait for your link card to finish loading" msgstr "Aguarde atĆ© que a prĆ©via de link termine de carregar" @@ -2851,8 +2934,8 @@ msgstr "PolĆ­tica" msgid "Porn" msgstr "Pornografia" -#: src/view/com/composer/Composer.tsx:350 -#: src/view/com/composer/Composer.tsx:358 +#: src/view/com/composer/Composer.tsx:357 +#: src/view/com/composer/Composer.tsx:365 msgctxt "action" msgid "Post" msgstr "Postar" @@ -2862,7 +2945,7 @@ msgctxt "description" msgid "Post" msgstr "Post" -#: src/view/com/post-thread/PostThreadItem.tsx:173 +#: src/view/com/post-thread/PostThreadItem.tsx:175 msgid "Post by {0}" msgstr "Post por {0}" @@ -2872,11 +2955,11 @@ msgstr "Post por {0}" msgid "Post by @{0}" msgstr "Post por @{0}" -#: src/view/com/util/forms/PostDropdownBtn.tsx:88 +#: src/view/com/util/forms/PostDropdownBtn.tsx:90 msgid "Post deleted" msgstr "Post excluĆ­do" -#: src/view/com/post-thread/PostThread.tsx:461 +#: src/view/com/post-thread/PostThread.tsx:462 msgid "Post hidden" msgstr "Post oculto" @@ -2888,14 +2971,22 @@ msgstr "Idioma do post" msgid "Post Languages" msgstr "Idiomas do Post" -#: src/view/com/post-thread/PostThread.tsx:513 +#: src/view/com/post-thread/PostThread.tsx:514 msgid "Post not found" msgstr "Post nĆ£o encontrado" +#: src/components/TagMenu/index.tsx:257 +msgid "posts" +msgstr "" + #: src/view/screens/Profile.tsx:180 msgid "Posts" msgstr "Posts" +#: src/components/dialogs/MutedWords.tsx:77 +msgid "Posts can be muted based on their text, their tags, or both." +msgstr "" + #: src/view/com/posts/FeedErrorMessage.tsx:64 msgid "Posts hidden" msgstr "Posts ocultados" @@ -2960,11 +3051,11 @@ msgstr "Listas pĆŗblicas e compartilhĆ”veis para silenciar ou bloquear usuĆ”rios msgid "Public, shareable lists which can drive feeds." msgstr "Listas pĆŗblicas e compartilhĆ”veis que geram feeds." -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish post" msgstr "Publicar post" -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish reply" msgstr "Publicar resposta" @@ -2998,6 +3089,7 @@ msgstr "Feeds Recomendados" msgid "Recommended Users" msgstr "UsuĆ”rios Recomendados" +#: src/components/dialogs/MutedWords.tsx:249 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/SelfLabel.tsx:83 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -3035,6 +3127,10 @@ msgstr "Remover imagem" msgid "Remove image preview" msgstr "Remover visualização da imagem" +#: src/components/dialogs/MutedWords.tsx:294 +msgid "Remove mute word from your list" +msgstr "" + #: src/view/com/modals/Repost.tsx:47 msgid "Remove repost" msgstr "Desfazer repost" @@ -3069,7 +3165,7 @@ msgstr "Respostas" msgid "Replies to this thread are disabled" msgstr "Respostas para esta thread estĆ£o desativadas" -#: src/view/com/composer/Composer.tsx:348 +#: src/view/com/composer/Composer.tsx:355 msgctxt "action" msgid "Reply" msgstr "Responder" @@ -3079,7 +3175,7 @@ msgid "Reply Filters" msgstr "Filtros de Resposta" #: src/view/com/post/Post.tsx:167 -#: src/view/com/posts/FeedItem.tsx:285 +#: src/view/com/posts/FeedItem.tsx:287 msgctxt "description" msgid "Reply to <0/>" msgstr "Responder <0/>" @@ -3101,7 +3197,7 @@ msgid "Report List" msgstr "Denunciar Lista" #: src/view/com/modals/report/SendReportButton.tsx:37 -#: src/view/com/util/forms/PostDropdownBtn.tsx:239 +#: src/view/com/util/forms/PostDropdownBtn.tsx:255 msgid "Report post" msgstr "Denunciar post" @@ -3126,11 +3222,11 @@ msgstr "Repostar ou citar um post" msgid "Reposted By" msgstr "Repostado Por" -#: src/view/com/posts/FeedItem.tsx:205 +#: src/view/com/posts/FeedItem.tsx:207 msgid "Reposted by {0}" msgstr "Repostado por {0}" -#: src/view/com/posts/FeedItem.tsx:222 +#: src/view/com/posts/FeedItem.tsx:224 msgid "Reposted by <0/>" msgstr "Repostado por <0/>" @@ -3138,7 +3234,7 @@ msgstr "Repostado por <0/>" msgid "reposted your post" msgstr "repostou seu post" -#: src/view/com/post-thread/PostThreadItem.tsx:186 +#: src/view/com/post-thread/PostThreadItem.tsx:188 msgid "Reposts of this post" msgstr "Reposts" @@ -3289,9 +3385,9 @@ msgstr "Ir para o topo" #: src/view/com/modals/ListAddRemoveUsers.tsx:75 #: src/view/com/util/forms/SearchInput.tsx:67 #: src/view/com/util/forms/SearchInput.tsx:79 -#: src/view/screens/Search/Search.tsx:418 -#: src/view/screens/Search/Search.tsx:645 -#: src/view/screens/Search/Search.tsx:663 +#: src/view/screens/Search/Search.tsx:419 +#: src/view/screens/Search/Search.tsx:668 +#: src/view/screens/Search/Search.tsx:686 #: src/view/shell/bottom-bar/BottomBar.tsx:159 #: src/view/shell/desktop/LeftNav.tsx:324 #: src/view/shell/desktop/Search.tsx:214 @@ -3301,11 +3397,19 @@ msgstr "Ir para o topo" msgid "Search" msgstr "Buscar" -#: src/view/screens/Search/Search.tsx:712 +#: src/view/screens/Search/Search.tsx:735 #: src/view/shell/desktop/Search.tsx:255 msgid "Search for \"{query}\"" msgstr "Pesquisar por \"{query}\"" +#: src/components/TagMenu/index.tsx:145 +msgid "Search for all posts by @{authorHandle} with tag {tag}" +msgstr "" + +#: src/components/TagMenu/index.tsx:90 +msgid "Search for all posts with tag {tag}" +msgstr "" + #: src/view/com/auth/LoggedOut.tsx:104 #: src/view/com/auth/LoggedOut.tsx:105 #: src/view/com/modals/ListAddRemoveUsers.tsx:70 @@ -3316,6 +3420,22 @@ msgstr "Buscar usuĆ”rios" msgid "Security Step Required" msgstr "Passo de SeguranƧa NecessĆ”rio" +#: src/components/TagMenu/index.web.tsx:50 +msgid "See {truncatedTag} posts" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:67 +msgid "See {truncatedTag} posts by user" +msgstr "" + +#: src/components/TagMenu/index.tsx:128 +msgid "See <0>{tag} posts" +msgstr "" + +#: src/components/TagMenu/index.tsx:189 +msgid "See <0>{tag} posts by this user" +msgstr "" + #: src/view/screens/SavedFeeds.tsx:163 msgid "See this guide" msgstr "Veja o guia" @@ -3525,7 +3645,7 @@ msgid "Share" msgstr "Compartilhar" #: src/view/com/profile/ProfileHeader.tsx:295 -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 #: src/view/screens/ProfileList.tsx:418 msgid "Share" msgstr "Compartilhar" @@ -3558,9 +3678,9 @@ msgstr "Mostrar anexos de {0}" msgid "Show follows similar to {0}" msgstr "Mostrar usuĆ”rios parecidos com {0}" -#: src/view/com/post-thread/PostThreadItem.tsx:532 -#: src/view/com/post/Post.tsx:196 -#: src/view/com/posts/FeedItem.tsx:359 +#: src/view/com/post-thread/PostThreadItem.tsx:538 +#: src/view/com/post/Post.tsx:198 +#: src/view/com/posts/FeedItem.tsx:363 msgid "Show More" msgstr "Mostrar Mais" @@ -3728,7 +3848,7 @@ msgstr "Desenvolvimento de software" msgid "Something went wrong. Check your email and try again." msgstr "Algo deu errado. Verifique seu e-mail e tente novamente." -#: src/App.native.tsx:61 +#: src/App.native.tsx:63 msgid "Sorry! Your session expired. Please log in again." msgstr "Opa! Sua sessĆ£o expirou. Por favor, entre novamente." @@ -3786,7 +3906,7 @@ msgstr "Increver-se no feed {0}" msgid "Subscribe to this list" msgstr "Inscreva-se nesta lista" -#: src/view/screens/Search/Search.tsx:373 +#: src/view/screens/Search/Search.tsx:374 msgid "Suggested Follows" msgstr "SugestƵes de Seguidores" @@ -3830,6 +3950,14 @@ msgstr "Sistema" msgid "System log" msgstr "Log do sistema" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "tag" +msgstr "" + +#: src/components/TagMenu/index.tsx:74 +msgid "Tag menu: {tag}" +msgstr "" + #: src/view/com/modals/crop-image/CropImage.web.tsx:112 msgid "Tall" msgstr "Alto" @@ -3853,6 +3981,10 @@ msgstr "Termos" msgid "Terms of Service" msgstr "Termos de ServiƧo" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "text" +msgstr "" + #: src/view/com/modals/AppealLabel.tsx:70 #: src/view/com/modals/report/InputIssueDetails.tsx:51 msgid "Text input field" @@ -3878,7 +4010,7 @@ msgstr "A PolĆ­tica de Direitos Autorais foi movida para <0/>" msgid "The following steps will help customize your Bluesky experience." msgstr "Os seguintes passos vĆ£o ajudar a customizar sua experiĆŖncia no Bluesky." -#: src/view/com/post-thread/PostThread.tsx:516 +#: src/view/com/post-thread/PostThread.tsx:517 msgid "The post may have been deleted." msgstr "O post pode ter sido excluĆ­do." @@ -4044,7 +4176,7 @@ msgstr "Esta lista estĆ” vazia!" msgid "This name is already in use" msgstr "VocĆŖ jĆ” tem uma senha com esse nome" -#: src/view/com/post-thread/PostThreadItem.tsx:123 +#: src/view/com/post-thread/PostThreadItem.tsx:125 msgid "This post has been deleted." msgstr "Este post foi excluĆ­do." @@ -4068,7 +4200,11 @@ msgstr "Este usuĆ”rio estĆ” incluĆ­do na lista <0/>, que vocĆŖ silenciou." msgid "This warning is only available for posts with media attached." msgstr "Este aviso só estĆ” disponĆ­vel para publicaƧƵes com mĆ­dia anexada." -#: src/view/com/util/forms/PostDropdownBtn.tsx:221 +#: src/components/dialogs/MutedWords.tsx:236 +msgid "This will delete {0} from your muted words. You can always add it back later." +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:237 msgid "This will hide this post from your feeds." msgstr "Isso ocultarĆ” este post de seus feeds." @@ -4085,6 +4221,10 @@ msgstr "Visualização de Threads" msgid "Threads Preferences" msgstr "PreferĆŖncias das Threads" +#: src/components/dialogs/MutedWords.tsx:95 +msgid "Toggle between muted word options." +msgstr "" + #: src/view/com/util/forms/DropdownButton.tsx:246 msgid "Toggle dropdown" msgstr "Alternar menu suspenso" @@ -4093,9 +4233,9 @@ msgstr "Alternar menu suspenso" msgid "Transformations" msgstr "TransformaƧƵes" -#: src/view/com/post-thread/PostThreadItem.tsx:679 -#: src/view/com/post-thread/PostThreadItem.tsx:681 -#: src/view/com/util/forms/PostDropdownBtn.tsx:154 +#: src/view/com/post-thread/PostThreadItem.tsx:685 +#: src/view/com/post-thread/PostThreadItem.tsx:687 +#: src/view/com/util/forms/PostDropdownBtn.tsx:156 msgid "Translate" msgstr "Traduzir" @@ -4160,15 +4300,24 @@ msgstr "Infelizmente, vocĆŖ nĆ£o atende aos requisitos para criar uma conta." msgid "Unlike" msgstr "Descurtir" +#: src/components/TagMenu/index.tsx:253 #: src/view/screens/ProfileList.tsx:597 msgid "Unmute" msgstr "Dessilenciar" +#: src/components/TagMenu/index.web.tsx:90 +msgid "Unmute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:326 msgid "Unmute Account" msgstr "Dessilenciar conta" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/TagMenu/index.tsx:210 +msgid "Unmute all {tag} posts" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Unmute thread" msgstr "Dessilenciar thread" @@ -4369,6 +4518,10 @@ msgstr "NĆ£o temos mais posts de quem vocĆŖ segue. Aqui estĆ£o os mais novos de #~ msgid "We recommend \"For You\" by Skygaze:" #~ msgstr "Recomendamos o \"Para vocĆŖ\", do Skygaze:" +#: src/components/dialogs/MutedWords.tsx:161 +msgid "We recommend avoiding common words that appear in many posts, since it can result in no posts being shown." +msgstr "" + #: src/screens/Onboarding/StepAlgoFeeds/index.tsx:124 msgid "We recommend our \"Discover\" feed:" msgstr "Recomendamos nosso feed \"Discover\":" @@ -4397,7 +4550,11 @@ msgstr "Estamos muito felizes em recebĆŖ-lo!" msgid "We're sorry, but we were unable to resolve this list. If this persists, please contact the list creator, @{handleOrDid}." msgstr "Tivemos um problema ao exibir esta lista. Se continuar acontecendo, contate o criador da lista: @{handleOrDid}." -#: src/view/screens/Search/Search.tsx:253 +#: src/components/dialogs/MutedWords.tsx:182 +msgid "We're sorry, but we weren't able to load your muted words at this time. Please try again." +msgstr "" + +#: src/view/screens/Search/Search.tsx:254 msgid "We're sorry, but your search could not be completed. Please try again in a few minutes." msgstr "Lamentamos, mas sua busca nĆ£o pĆ“de ser concluĆ­da. Por favor, tente novamente em alguns minutos." @@ -4418,7 +4575,7 @@ msgid "What is the issue with this {collectionName}?" msgstr "Qual Ć© o problema com este {collectionName}?" #: src/view/com/auth/SplashScreen.tsx:59 -#: src/view/com/composer/Composer.tsx:279 +#: src/view/com/composer/Composer.tsx:286 msgid "What's up?" msgstr "E aĆ­?" @@ -4439,11 +4596,11 @@ msgstr "Quem pode responder" msgid "Wide" msgstr "Largo" -#: src/view/com/composer/Composer.tsx:415 +#: src/view/com/composer/Composer.tsx:422 msgid "Write post" msgstr "Escrever post" -#: src/view/com/composer/Composer.tsx:278 +#: src/view/com/composer/Composer.tsx:285 #: src/view/com/composer/Prompt.tsx:33 msgid "Write your reply" msgstr "Escreva sua resposta" @@ -4508,7 +4665,7 @@ msgstr "VocĆŖ nĆ£o tem feeds salvos!" msgid "You don't have any saved feeds." msgstr "VocĆŖ nĆ£o tem feeds salvos." -#: src/view/com/post-thread/PostThread.tsx:464 +#: src/view/com/post-thread/PostThread.tsx:465 msgid "You have blocked the author or you have been blocked by the author." msgstr "VocĆŖ bloqueou esta conta ou foi bloqueado por ela." @@ -4548,6 +4705,10 @@ msgstr "VocĆŖ ainda nĆ£o criou nenhuma senha de aplicativo. VocĆŖ pode criar uma msgid "You have not muted any accounts yet. To mute an account, go to their profile and selected \"Mute account\" from the menu on their account." msgstr "VocĆŖ ainda nĆ£o silenciou nenhuma conta. Para silenciar uma conta, acesse um perfil e selecione \"Silenciar conta\" no menu." +#: src/components/dialogs/MutedWords.tsx:202 +msgid "You haven't muted any words or tags yet" +msgstr "" + #: src/view/com/modals/ContentFilteringSettings.tsx:175 msgid "You must be 18 or older to enable adult content." msgstr "VocĆŖ precisa ser maior de idade para habilitar conteĆŗdo adulto." @@ -4556,11 +4717,11 @@ msgstr "VocĆŖ precisa ser maior de idade para habilitar conteĆŗdo adulto." msgid "You must be 18 years or older to enable adult content" msgstr "VocĆŖ precisa ser maior de idade para habilitar conteĆŗdo adulto." -#: src/view/com/util/forms/PostDropdownBtn.tsx:127 +#: src/view/com/util/forms/PostDropdownBtn.tsx:129 msgid "You will no longer receive notifications for this thread" msgstr "VocĆŖ nĆ£o vai mais receber notificaƧƵes desta thread" -#: src/view/com/util/forms/PostDropdownBtn.tsx:130 +#: src/view/com/util/forms/PostDropdownBtn.tsx:132 msgid "You will now receive notifications for this thread" msgstr "VocĆŖ vai receber notificaƧƵes desta thread" @@ -4646,11 +4807,15 @@ msgstr "Seu usuĆ”rio completo serĆ” <0>@{0}" #~ msgid "Your invite codes are hidden when logged in using an App Password" #~ msgstr "Seus códigos de convite estĆ£o ocultos quando conectado com uma Senha do Aplicativo" +#: src/components/dialogs/MutedWords.tsx:173 +msgid "Your muted words" +msgstr "" + #: src/view/com/modals/ChangePassword.tsx:155 msgid "Your password has been changed successfully!" msgstr "Sua senha foi alterada com sucesso!" -#: src/view/com/composer/Composer.tsx:267 +#: src/view/com/composer/Composer.tsx:274 msgid "Your post has been published" msgstr "Seu post foi publicado" @@ -4665,7 +4830,7 @@ msgstr "Suas postagens, curtidas e bloqueios sĆ£o pĆŗblicos. Silenciamentos sĆ£o msgid "Your profile" msgstr "Seu perfil" -#: src/view/com/composer/Composer.tsx:266 +#: src/view/com/composer/Composer.tsx:273 msgid "Your reply has been published" msgstr "Sua resposta foi publicada" diff --git a/src/locale/locales/uk/messages.po b/src/locale/locales/uk/messages.po index 169b1feb78..8f978261ff 100644 --- a/src/locale/locales/uk/messages.po +++ b/src/locale/locales/uk/messages.po @@ -118,7 +118,7 @@ msgid "A new version of the app is available. Please update to continue using th msgstr "Š”Š¾ŃŃ‚ŃƒŠæŠ½Š° нова Š²ŠµŃ€ŃŃ–я. Š‘ŃƒŠ“ŃŒ ласка, Š¾Š½Š¾Š²Ń–Ń‚ŃŒ Š·Š°ŃŃ‚Š¾ŃŃƒŠ½Š¾Šŗ, щоб проГовжити ним ŠŗŠ¾Ń€ŠøŃŃ‚ŃƒŠ²Š°Ń‚ŠøŃŃ." #: src/view/com/util/ViewHeader.tsx:83 -#: src/view/screens/Search/Search.tsx:624 +#: src/view/screens/Search/Search.tsx:647 msgid "Access navigation links and settings" msgstr "" @@ -169,6 +169,7 @@ msgstr "" msgid "Account unmuted" msgstr "" +#: src/components/dialogs/MutedWords.tsx:147 #: src/view/com/auth/onboarding/RecommendedFeedsItem.tsx:150 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -210,14 +211,22 @@ msgstr "ДоГайте поГробиці" msgid "Add details to report" msgstr "ДоГайте поГробиці Го скарги" -#: src/view/com/composer/Composer.tsx:446 +#: src/view/com/composer/Composer.tsx:453 msgid "Add link card" msgstr "ДоГати попереГній ŠæŠµŃ€ŠµŠ³Š»ŃŠ“" -#: src/view/com/composer/Composer.tsx:451 +#: src/view/com/composer/Composer.tsx:458 msgid "Add link card:" msgstr "ДоГати попереГній ŠæŠµŃ€ŠµŠ³Š»ŃŠ“:" +#: src/components/dialogs/MutedWords.tsx:140 +msgid "Add mute word for configured settings" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:74 +msgid "Add muted words and tags" +msgstr "" + #: src/view/com/modals/ChangeHandle.tsx:417 msgid "Add the following DNS record to your domain:" msgstr "ДоГайте Š½Š°ŃŃ‚ŃƒŠæŠ½ŠøŠ¹ DNS-запис Го вашого Гомену:" @@ -341,7 +350,7 @@ msgstr "" msgid "App Passwords" msgstr "ŠŸŠ°Ń€Š¾Š»Ń– Š“Š»Ń Š·Š°ŃŃ‚Š¾ŃŃƒŠ½ŠŗŃ–Š²" -#: src/view/com/util/forms/PostDropdownBtn.tsx:279 +#: src/view/com/util/forms/PostDropdownBtn.tsx:295 msgid "Appeal content warning" msgstr "ŠžŃŠŗŠ°Ń€Š¶ŠøŃ‚Šø ŠæŠ¾ŠæŠµŃ€ŠµŠ“Š¶ŠµŠ½Š½Ń про вміст" @@ -373,15 +382,16 @@ msgstr "ŠžŃ„Š¾Ń€Š¼Š»ŠµŠ½Š½Ń" msgid "Are you sure you want to delete the app password \"{name}\"?" msgstr "Š’Šø Гійсно хочете виГалити ŠæŠ°Ń€Š¾Š»ŃŒ Š“Š»Ń Š·Š°ŃŃ‚Š¾ŃŃƒŠ½ŠŗŃƒ \"{name}\"?" -#: src/view/com/composer/Composer.tsx:143 +#: src/view/com/composer/Composer.tsx:150 msgid "Are you sure you'd like to discard this draft?" msgstr "Š’Šø Гійсно бажаєте виГалити цю Ń‡ŠµŃ€Š½ŠµŃ‚ŠŗŃƒ?" +#: src/components/dialogs/MutedWords.tsx:233 #: src/view/screens/ProfileList.tsx:365 msgid "Are you sure?" msgstr "Š’Šø впевнені?" -#: src/view/com/util/forms/PostDropdownBtn.tsx:262 +#: src/view/com/util/forms/PostDropdownBtn.tsx:278 msgid "Are you sure? This cannot be undone." msgstr "Š’Šø впевнені? Це не можна буГе ŃŠŗŠ°ŃŃƒŠ²Š°Ń‚Šø." @@ -407,15 +417,15 @@ msgstr "Š„ŃƒŠ“Š¾Š¶Š½Ń або нееротична Š¾Š³Š¾Š»ŠµŠ½Ń–ŃŃ‚ŃŒ." #: src/view/com/auth/login/LoginForm.tsx:259 #: src/view/com/auth/login/SetNewPasswordForm.tsx:179 #: src/view/com/modals/report/InputIssueDetails.tsx:46 -#: src/view/com/post-thread/PostThread.tsx:471 -#: src/view/com/post-thread/PostThread.tsx:521 -#: src/view/com/post-thread/PostThread.tsx:529 +#: src/view/com/post-thread/PostThread.tsx:472 +#: src/view/com/post-thread/PostThread.tsx:522 +#: src/view/com/post-thread/PostThread.tsx:530 #: src/view/com/profile/ProfileHeader.tsx:649 #: src/view/com/util/ViewHeader.tsx:81 msgid "Back" msgstr "ŠŠ°Š·Š°Š“" -#: src/view/com/post-thread/PostThread.tsx:479 +#: src/view/com/post-thread/PostThread.tsx:480 msgctxt "action" msgid "Back" msgstr "" @@ -463,7 +473,7 @@ msgstr "" msgid "Blocked" msgstr "" -#: src/view/screens/Moderation.tsx:123 +#: src/view/screens/Moderation.tsx:142 msgid "Blocked accounts" msgstr "Заблоковані облікові записи" @@ -522,7 +532,7 @@ msgstr "Bluesky ŠæŃƒŠ±Š»Ń–Ń‡Š½ŠøŠ¹." msgid "Bluesky uses invites to build a healthier community. If you don't know anybody with an invite, you can sign up for the waitlist and we'll send one soon." msgstr "Bluesky Š²ŠøŠŗŠ¾Ń€ŠøŃŃ‚Š¾Š²ŃƒŃ” ŃŠøŃŃ‚ŠµŠ¼Ńƒ Š·Š°ŠæŃ€Š¾ŃˆŠµŠ½ŃŒ Š“Š»Ń ŃŃ‚Š²Š¾Ń€ŠµŠ½Š½Ń Š·Š“Š¾Ń€Š¾Š²Ń–ŃˆŠ¾Ń— ŃŠæŃ–Š»ŃŒŠ½Š¾Ń‚Šø. Якщо Š’Šø не знаєте когось хто має Š·Š°ŠæŃ€Š¾ŃˆŠµŠ½Š½Ń, ви можете Š·Š°ŠæŠøŃŠ°Ń‚ŠøŃŃ Го черги Š¾Ń‡Ń–ŠŗŃƒŠ²Š°Š½Š½Ń і ми скоро Š½Š°Š“Ń–ŃˆŠ»ŠµŠ¼Š¾ вам коГ Š·Š°ŠæŃ€Š¾ŃˆŠµŠ½Š½Ń." -#: src/view/screens/Moderation.tsx:226 +#: src/view/screens/Moderation.tsx:245 msgid "Bluesky will not show your profile and posts to logged-out users. Other apps may not honor this request. This does not make your account private." msgstr "Bluesky не буГе ŠæŠ¾ŠŗŠ°Š·ŃƒŠ²Š°Ń‚Šø ваш ŠæŃ€Š¾Ń„Ń–Š»ŃŒ і ŠæŠ¾Š²Ń–Š“Š¾Š¼Š»ŠµŠ½Š½Ń Š²Ń–Š“Š²Ń–Š“ŃƒŠ²Š°Ń‡Š°Š¼ без облікового запису. Š†Š½ŃˆŃ– Š·Š°ŃŃ‚Š¾ŃŃƒŠ½ŠŗŠø Š¼Š¾Š¶ŃƒŃ‚ŃŒ не ŃŠ»Ń–Š“ŃƒŠ²Š°Ń‚Šø Ń†ŃŒŠ¾Š¼Ńƒ Š·Š°ŠæŠøŃ‚Ńƒ. Це не Ń€Š¾Š±ŠøŃ‚ŃŒ ваш обліковий запис приватним." @@ -574,8 +584,8 @@ msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must msgstr "Може містити лише літери, цифри, пробіли, Гефіси та знаки ŠæŃ–Š“ŠŗŃ€ŠµŃŠ»ŠµŠ½Š½Ń, і мати Говжину віГ 4 Го 32 символів." #: src/components/Prompt.tsx:91 -#: src/view/com/composer/Composer.tsx:300 -#: src/view/com/composer/Composer.tsx:305 +#: src/view/com/composer/Composer.tsx:307 +#: src/view/com/composer/Composer.tsx:312 #: src/view/com/modals/ChangeEmail.tsx:218 #: src/view/com/modals/ChangeEmail.tsx:220 #: src/view/com/modals/ChangePassword.tsx:265 @@ -589,7 +599,7 @@ msgstr "Може містити лише літери, цифри, пробіл #: src/view/com/modals/VerifyEmail.tsx:247 #: src/view/com/modals/VerifyEmail.tsx:253 #: src/view/com/modals/Waitlist.tsx:142 -#: src/view/screens/Search/Search.tsx:693 +#: src/view/screens/Search/Search.tsx:716 #: src/view/shell/desktop/Search.tsx:238 msgid "Cancel" msgstr "Š”ŠŗŠ°ŃŃƒŠ²Š°Ń‚Šø" @@ -752,7 +762,7 @@ msgid "Clear all storage data (restart after this)" msgstr "" #: src/view/com/util/forms/SearchInput.tsx:88 -#: src/view/screens/Search/Search.tsx:674 +#: src/view/screens/Search/Search.tsx:697 msgid "Clear search query" msgstr "ŠžŃ‡ŠøŃŃ‚ŠøŃ‚Šø пошуковий запит" @@ -760,6 +770,11 @@ msgstr "ŠžŃ‡ŠøŃŃ‚ŠøŃ‚Šø пошуковий запит" msgid "click here" msgstr "" +#: src/components/RichText.tsx:189 +#: src/components/TagMenu/index.web.tsx:125 +msgid "Click here to open tag menu for {tag}" +msgstr "" + #: src/screens/Onboarding/index.tsx:35 msgid "Climate" msgstr "" @@ -790,11 +805,15 @@ msgstr "Закрити Š·Š¾Š±Ń€Š°Š¶ŠµŠ½Š½Ń" msgid "Close image viewer" msgstr "Закрити ŠæŠµŃ€ŠµŠ³Š»ŃŠ“ Š·Š¾Š±Ń€Š°Š¶ŠµŠ½Š½Ń" -#: src/view/shell/index.web.tsx:49 +#: src/view/shell/index.web.tsx:51 msgid "Close navigation footer" msgstr "Закрити панель навігації" -#: src/view/shell/index.web.tsx:50 +#: src/components/TagMenu/index.tsx:266 +msgid "Close this dialog" +msgstr "" + +#: src/view/shell/index.web.tsx:52 msgid "Closes bottom navigation bar" msgstr "" @@ -802,7 +821,7 @@ msgstr "" msgid "Closes password update alert" msgstr "" -#: src/view/com/composer/Composer.tsx:302 +#: src/view/com/composer/Composer.tsx:309 msgid "Closes post composer and discards post draft" msgstr "" @@ -835,7 +854,7 @@ msgstr "" msgid "Complete the challenge" msgstr "" -#: src/view/com/composer/Composer.tsx:417 +#: src/view/com/composer/Composer.tsx:424 msgid "Compose posts up to {MAX_GRAPHEME_LENGTH} characters in length" msgstr "" @@ -899,7 +918,7 @@ msgstr "Š—ā€™Ń”Š“Š½Š°Š½Š½Ń..." msgid "Contact support" msgstr "" -#: src/view/screens/Moderation.tsx:81 +#: src/view/screens/Moderation.tsx:83 msgid "Content filtering" msgstr "Š¤Ń–Š»ŃŒŃ‚Ń€ŃƒŠ²Š°Š½Š½Ń Š²Š¼Ń–ŃŃ‚Ńƒ" @@ -965,7 +984,7 @@ msgstr "" #: src/view/com/modals/AddAppPasswords.tsx:76 #: src/view/com/modals/InviteCodes.tsx:152 -#: src/view/com/util/forms/PostDropdownBtn.tsx:141 +#: src/view/com/util/forms/PostDropdownBtn.tsx:143 msgid "Copied to clipboard" msgstr "" @@ -981,7 +1000,7 @@ msgstr "Š”ŠŗŠ¾ŠæŃ–ŃŽŠ²Š°Ń‚Šø" msgid "Copy link to list" msgstr "Š”ŠŗŠ¾ŠæŃ–ŃŽŠ²Š°Ń‚Šø ŠæŠ¾ŃŠøŠ»Š°Š½Š½Ń" -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 msgid "Copy link to post" msgstr "Š”ŠŗŠ¾ŠæŃ–ŃŽŠ²Š°Ń‚Šø ŠæŠ¾ŃŠøŠ»Š°Š½Š½Ń" @@ -989,7 +1008,7 @@ msgstr "Š”ŠŗŠ¾ŠæŃ–ŃŽŠ²Š°Ń‚Šø ŠæŠ¾ŃŠøŠ»Š°Š½Š½Ń" msgid "Copy link to profile" msgstr "Š”ŠŗŠ¾ŠæŃ–ŃŽŠ²Š°Ń‚Šø ŠæŠ¾ŃŠøŠ»Š°Š½Š½Ń" -#: src/view/com/util/forms/PostDropdownBtn.tsx:168 +#: src/view/com/util/forms/PostDropdownBtn.tsx:170 msgid "Copy post text" msgstr "Š”ŠŗŠ¾ŠæŃ–ŃŽŠ²Š°Ń‚Šø текст" @@ -1045,7 +1064,7 @@ msgstr "" msgid "Created by you" msgstr "" -#: src/view/com/composer/Composer.tsx:448 +#: src/view/com/composer/Composer.tsx:455 msgid "Creates a card with a thumbnail. The card links to {url}" msgstr "" @@ -1126,11 +1145,11 @@ msgstr "ВиГалити мій обліковий запис" msgid "Delete My Account…" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:257 +#: src/view/com/util/forms/PostDropdownBtn.tsx:273 msgid "Delete post" msgstr "ВиГалити пост" -#: src/view/com/util/forms/PostDropdownBtn.tsx:261 +#: src/view/com/util/forms/PostDropdownBtn.tsx:277 msgid "Delete this post?" msgstr "ВиГалити цей пост?" @@ -1157,7 +1176,7 @@ msgstr "ŠžŠæŠøŃ" #~ msgid "Developer Tools" #~ msgstr "Š†Š½ŃŃ‚Ń€ŃƒŠ¼ŠµŠ½Ń‚Šø розробника" -#: src/view/com/composer/Composer.tsx:211 +#: src/view/com/composer/Composer.tsx:218 msgid "Did you want to say anything?" msgstr "ŠŸŠ¾Ń€Š¾Š¶Š½Ń–Š¹ пост. Š’Šø хотіли Ń‰Š¾ŃŃŒ написати?" @@ -1165,15 +1184,15 @@ msgstr "ŠŸŠ¾Ń€Š¾Š¶Š½Ń–Š¹ пост. Š’Šø хотіли Ń‰Š¾ŃŃŒ написати?" msgid "Dim" msgstr "" -#: src/view/com/composer/Composer.tsx:144 +#: src/view/com/composer/Composer.tsx:151 msgid "Discard" msgstr "ВиГалити" -#: src/view/com/composer/Composer.tsx:138 +#: src/view/com/composer/Composer.tsx:145 msgid "Discard draft" msgstr "Š’Ń–Š“ŠŗŠøŠ½ŃƒŃ‚Šø Ń‡ŠµŃ€Š½ŠµŃ‚ŠŗŃƒ" -#: src/view/screens/Moderation.tsx:207 +#: src/view/screens/Moderation.tsx:226 msgid "Discourage apps from showing my account to logged-out users" msgstr "ŠŸŠ¾ŠæŃ€Š¾ŃŠøŃ‚Šø Š·Š°ŃŃ‚Š¾ŃŃƒŠ½ŠŗŠø не ŠæŠ¾ŠŗŠ°Š·ŃƒŠ²Š°Ń‚Šø мій обліковий запис без Š²Ń…Š¾Š“Ńƒ" @@ -1252,7 +1271,7 @@ msgstr "" msgid "Download CAR file" msgstr "" -#: src/view/com/composer/text-input/TextInput.web.tsx:247 +#: src/view/com/composer/text-input/TextInput.web.tsx:249 msgid "Drop to add images" msgstr "" @@ -1324,6 +1343,7 @@ msgstr "Š ŠµŠ“Š°Š³ŃƒŠ²Š°Ń‚Šø ŠæŃ€Š¾Ń„Ń–Š»ŃŒ" msgid "Edit Profile" msgstr "Š ŠµŠ“Š°Š³ŃƒŠ²Š°Ń‚Šø ŠæŃ€Š¾Ń„Ń–Š»ŃŒ" +#: src/view/com/home/HomeHeaderLayout.web.tsx:59 #: src/view/screens/Feeds.tsx:355 msgid "Edit Saved Feeds" msgstr "Š ŠµŠ“Š°Š³ŃƒŠ²Š°Ń‚Šø збережені стрічки" @@ -1406,6 +1426,11 @@ msgstr "ŠšŃ–Š½ŠµŃ†ŃŒ стрічки" msgid "Enter a name for this App Password" msgstr "" +#: src/components/dialogs/MutedWords.tsx:87 +#: src/components/dialogs/MutedWords.tsx:88 +msgid "Enter a word or tag" +msgstr "" + #: src/view/com/modals/VerifyEmail.tsx:105 msgid "Enter Confirmation Code" msgstr "" @@ -1459,7 +1484,7 @@ msgstr "Š’Š²ŠµŠ“Ń–Ń‚ŃŒ псевГонім та ŠæŠ°Ń€Š¾Š»ŃŒ" msgid "Error receiving captcha response." msgstr "" -#: src/view/screens/Search/Search.tsx:109 +#: src/view/screens/Search/Search.tsx:110 msgid "Error:" msgstr "Помилка:" @@ -1530,7 +1555,7 @@ msgstr "" msgid "Failed to create the list. Check your internet connection and try again." msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:108 +#: src/view/com/util/forms/PostDropdownBtn.tsx:110 msgid "Failed to delete post, please try again" msgstr "" @@ -1552,8 +1577,8 @@ msgid "Feed offline" msgstr "Дтрічка не ŠæŃ€Š°Ń†ŃŽŃ”" #: src/view/com/feeds/FeedPage.tsx:143 -msgid "Feed Preferences" -msgstr "ŠŠ°Š»Š°ŃˆŃ‚ŃƒŠ²Š°Š½Š½Ń стрічки" +#~ msgid "Feed Preferences" +#~ msgstr "ŠŠ°Š»Š°ŃˆŃ‚ŃƒŠ²Š°Š½Š½Ń стрічки" #: src/view/shell/desktop/RightNav.tsx:61 #: src/view/shell/Drawer.tsx:311 @@ -1601,11 +1626,11 @@ msgstr "" msgid "Find accounts to follow" msgstr "" -#: src/view/screens/Search/Search.tsx:439 +#: src/view/screens/Search/Search.tsx:440 msgid "Find users on Bluesky" msgstr "Знайти ŠŗŠ¾Ń€ŠøŃŃ‚ŃƒŠ²Š°Ń‡Ń–Š² у Bluesky" -#: src/view/screens/Search/Search.tsx:437 +#: src/view/screens/Search/Search.tsx:438 msgid "Find users with the search tool on the right" msgstr "Знайти ŠŗŠ¾Ń€ŠøŃŃ‚ŃƒŠ²Š°Ń‡Ń–Š² за Š“Š¾ŠæŠ¾Š¼Š¾Š³Š¾ŃŽ ŠæŠ¾Š»Ń пошуку справа вгорі" @@ -1714,6 +1739,7 @@ msgid "Following {0}" msgstr "" #: src/Navigation.tsx:248 +#: src/view/com/home/HomeHeaderLayout.web.tsx:45 #: src/view/com/home/HomeHeaderLayoutMobile.tsx:83 #: src/view/screens/PreferencesFollowingFeed.tsx:104 #: src/view/screens/Settings/index.tsx:543 @@ -1753,7 +1779,7 @@ msgstr "Š—Š°Š±ŃƒŠ»Šø ŠæŠ°Ń€Š¾Š»ŃŒ" msgid "Forgot Password" msgstr "Š—Š°Š±ŃƒŠ»Šø ŠæŠ°Ń€Š¾Š»ŃŒ" -#: src/view/com/posts/FeedItem.tsx:187 +#: src/view/com/posts/FeedItem.tsx:189 msgctxt "from-feed" msgid "From <0/>" msgstr "" @@ -1786,7 +1812,7 @@ msgstr "ŠŠ°Š·Š°Š“" msgid "Go back to previous step" msgstr "" -#: src/view/screens/Search/Search.tsx:724 +#: src/view/screens/Search/Search.tsx:747 #: src/view/shell/desktop/Search.tsx:262 msgid "Go to @{queryMaybeHandle}" msgstr "" @@ -1803,6 +1829,10 @@ msgstr "Далі" msgid "Handle" msgstr "ŠŸŃŠµŠ²Š“Š¾Š½Ń–Š¼" +#: src/components/RichText.tsx:188 +msgid "Hashtag: {tag}" +msgstr "" + #: src/view/com/auth/create/CreateAccount.tsx:208 msgid "Having trouble?" msgstr "" @@ -1845,7 +1875,7 @@ msgctxt "action" msgid "Hide" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +#: src/view/com/util/forms/PostDropdownBtn.tsx:232 msgid "Hide post" msgstr "ŠŸŃ€ŠøŃ…Š¾Š²Š°Ń‚Šø пост" @@ -1854,7 +1884,7 @@ msgstr "ŠŸŃ€ŠøŃ…Š¾Š²Š°Ń‚Šø пост" msgid "Hide the content" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:220 +#: src/view/com/util/forms/PostDropdownBtn.tsx:236 msgid "Hide this post?" msgstr "ŠŸŃ€ŠøŃ…Š¾Š²Š°Ń‚Šø цей пост?" @@ -2029,7 +2059,7 @@ msgstr "" msgid "Input your user handle" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:224 +#: src/view/com/post-thread/PostThreadItem.tsx:226 msgid "Invalid or unsupported post record" msgstr "" @@ -2131,7 +2161,7 @@ msgstr "Š”Ń–Š·Š½Š°Ń‚ŠøŃŃ Š±Ń–Š»ŃŒŃˆŠµ" msgid "Learn more about this warning" msgstr "Š”Ń–Š·Š½Š°Ń‚ŠøŃŃ Š±Ń–Š»ŃŒŃˆŠµ про це ŠæŠ¾ŠæŠµŃ€ŠµŠ“Š¶ŠµŠ½Š½Ń" -#: src/view/screens/Moderation.tsx:243 +#: src/view/screens/Moderation.tsx:262 msgid "Learn more about what is public on Bluesky." msgstr "Š”Ń–Š·Š½Š°Ń‚ŠøŃŃ Š±Ń–Š»ŃŒŃˆŠµ про те, що є ŠæŃƒŠ±Š»Ń–Ń‡Š½ŠøŠ¼ в Bluesky." @@ -2215,7 +2245,7 @@ msgstr "" msgid "Likes" msgstr "Š’ŠæŠ¾Š“Š¾Š±Š°Š½Š½Ń" -#: src/view/com/post-thread/PostThreadItem.tsx:181 +#: src/view/com/post-thread/PostThreadItem.tsx:183 msgid "Likes on this post" msgstr "" @@ -2280,7 +2310,7 @@ msgstr "Завантажити Š±Ń–Š»ŃŒŃˆŠµ постів" msgid "Load new notifications" msgstr "Завантажити нові ŃŠæŠ¾Š²Ń–Ń‰ŠµŠ½Š½Ń" -#: src/view/com/feeds/FeedPage.tsx:181 +#: src/view/com/feeds/FeedPage.tsx:115 #: src/view/screens/Profile.tsx:440 #: src/view/screens/ProfileFeed.tsx:495 #: src/view/screens/ProfileList.tsx:681 @@ -2310,7 +2340,7 @@ msgstr "" #~ msgid "Logged-out users" #~ msgstr "" -#: src/view/screens/Moderation.tsx:136 +#: src/view/screens/Moderation.tsx:155 msgid "Logged-out visibility" msgstr "Š’ŠøŠ“ŠøŠ¼Ń–ŃŃ‚ŃŒ Š“Š»Ń ŠŗŠ¾Ń€ŠøŃŃ‚ŃƒŠ²Š°Ń‡Ń–Š² без облікового запису" @@ -2326,6 +2356,10 @@ msgstr "Увійти Го облікового запису, ŃŠŗŠ¾Š³Š¾ нема msgid "Make sure this is where you intend to go!" msgstr "ŠŸŠµŃ€ŠµŠŗŠ¾Š½Š°Š¹Ń‚ŠµŃŃ, що це Гійсно той сайт, що ви Š·Š±ŠøŃ€Š°Ń”Ń‚ŠµŃŃ віГвіГати!" +#: src/components/dialogs/MutedWords.tsx:71 +msgid "Manage your muted words and tags" +msgstr "" + #: src/view/com/auth/create/Step2.tsx:118 msgid "May not be longer than 253 characters" msgstr "" @@ -2347,7 +2381,7 @@ msgid "Mentioned users" msgstr "ЗгаГані ŠŗŠ¾Ń€ŠøŃŃ‚ŃƒŠ²Š°Ń‡Ń–" #: src/view/com/util/ViewHeader.tsx:81 -#: src/view/screens/Search/Search.tsx:623 +#: src/view/screens/Search/Search.tsx:646 msgid "Menu" msgstr "ŠœŠµŠ½ŃŽ" @@ -2360,7 +2394,7 @@ msgid "Message from server: {0}" msgstr "" #: src/Navigation.tsx:115 -#: src/view/screens/Moderation.tsx:64 +#: src/view/screens/Moderation.tsx:66 #: src/view/screens/Settings/index.tsx:625 #: src/view/shell/desktop/LeftNav.tsx:397 #: src/view/shell/Drawer.tsx:511 @@ -2391,7 +2425,7 @@ msgstr "" msgid "Moderation list updated" msgstr "" -#: src/view/screens/Moderation.tsx:95 +#: src/view/screens/Moderation.tsx:114 msgid "Moderation lists" msgstr "Дписки Š“Š»Ń моГерації" @@ -2418,7 +2452,7 @@ msgstr "Š‘Ń–Š»ŃŒŃˆŠµ стрічок" msgid "More options" msgstr "ДоГаткові опції" -#: src/view/com/util/forms/PostDropdownBtn.tsx:299 +#: src/view/com/util/forms/PostDropdownBtn.tsx:315 msgid "More post options" msgstr "" @@ -2430,6 +2464,14 @@ msgstr "За ŠŗŃ–Š»ŃŒŠŗŃ–ŃŃ‚ŃŽ впоГобань" msgid "Must be at least 3 characters" msgstr "" +#: src/components/TagMenu/index.tsx:253 +msgid "Mute" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:91 +msgid "Mute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:327 msgid "Mute Account" msgstr "Š†Š³Š½Š¾Ń€ŃƒŠ²Š°Ń‚Šø обліковий запис" @@ -2438,6 +2480,18 @@ msgstr "Š†Š³Š½Š¾Ń€ŃƒŠ²Š°Ń‚Šø обліковий запис" msgid "Mute accounts" msgstr "Š†Š³Š½Š¾Ń€ŃƒŠ²Š°Ń‚Šø облікові записи" +#: src/components/TagMenu/index.tsx:211 +msgid "Mute all {tag} posts" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:131 +msgid "Mute in tags only" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:116 +msgid "Mute in text & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:491 msgid "Mute list" msgstr "Š†Š³Š½Š¾Ń€ŃƒŠ²Š°Ń‚Šø список" @@ -2450,15 +2504,27 @@ msgstr "Š†Š³Š½Š¾Ń€ŃƒŠ²Š°Ń‚Šø ці облікові записи?" msgid "Mute this List" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/dialogs/MutedWords.tsx:109 +msgid "Mute this word in post text and tags" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:124 +msgid "Mute this word in tags only" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Mute thread" msgstr "Š†Š³Š½Š¾Ń€ŃƒŠ²Š°Ń‚Šø пост" +#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +msgid "Mute words & tags" +msgstr "" + #: src/view/com/lists/ListCard.tsx:102 msgid "Muted" msgstr "" -#: src/view/screens/Moderation.tsx:109 +#: src/view/screens/Moderation.tsx:128 msgid "Muted accounts" msgstr "Ігноровані облікові записи" @@ -2471,6 +2537,10 @@ msgstr "Ігноровані облікові записи" msgid "Muted accounts have their posts removed from your feed and from your notifications. Mutes are completely private." msgstr "Ігноровані облікові записи автоматично Š²ŠøŠ»ŃƒŃ‡Š°ŃŽŃ‚ŃŒŃŃ Ń–Š· Š²Š°ŃˆŠ¾Ń— стрічки та ŃŠæŠ¾Š²Ń–Ń‰ŠµŠ½ŃŒ. Š†Š³Š½Š¾Ń€ŃƒŠ²Š°Š½Š½Ń є ŠæŠ¾Š²Š½Ń–ŃŃ‚ŃŽ приватним." +#: src/view/screens/Moderation.tsx:100 +msgid "Muted words & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:277 msgid "Muting is private. Muted accounts can interact with you, but you will not see their posts or receive notifications from them." msgstr "Š†Š³Š½Š¾Ń€ŃƒŠ²Š°Š½Š½Ń є приватним. Ігноровані ŠŗŠ¾Ń€ŠøŃŃ‚ŃƒŠ²Š°Ń‡Ń– Š¼Š¾Š¶ŃƒŃ‚ŃŒ Š²Š·Š°Ń”Š¼Š¾Š“Ń–ŃŃ‚Šø Š· вами, але ви не бачитимете їх пости і не Š¾Ń‚Ń€ŠøŠ¼ŃƒŠ²Š°Ń‚ŠøŠ¼ŠµŃ‚Šµ віГ них ŃŠæŠ¾Š²Ń–Ń‰ŠµŠ½ŃŒ." @@ -2538,6 +2608,10 @@ msgstr "ŠŃ–ŠŗŠ¾Š»Šø не втрачайте Š“Š¾ŃŃ‚ŃƒŠæ Го Š²Š°ŃˆŠøŃ… Ган msgid "Never lose access to your followers or data." msgstr "" +#: src/components/dialogs/MutedWords.tsx:244 +msgid "Nevermind" +msgstr "" + #: src/view/screens/Lists.tsx:76 msgctxt "action" msgid "New" @@ -2559,7 +2633,7 @@ msgstr "" msgid "New Password" msgstr "" -#: src/view/com/feeds/FeedPage.tsx:192 +#: src/view/com/feeds/FeedPage.tsx:126 msgctxt "action" msgid "New post" msgstr "" @@ -2653,8 +2727,8 @@ msgstr "ŠŃ–Ń‡Š¾Š³Š¾ не знайГено за запитом Ā«{query}Ā»" #~ msgstr "" #: src/view/com/modals/ListAddRemoveUsers.tsx:127 -#: src/view/screens/Search/Search.tsx:280 -#: src/view/screens/Search/Search.tsx:308 +#: src/view/screens/Search/Search.tsx:281 +#: src/view/screens/Search/Search.tsx:309 msgid "No results found for {query}" msgstr "ŠŃ–Ń‡Š¾Š³Š¾ не знайГено за запитом Ā«{query}Ā»" @@ -2688,7 +2762,7 @@ msgstr "" #~ msgid "Note: Bluesky is an open and public network, and enabling this will not make your profile private or limit the ability of logged in users to see your posts. This setting only limits the visibility of posts on the Bluesky app and website; third-party apps that display Bluesky content may not respect this setting, and could show your content to logged-out users." #~ msgstr "" -#: src/view/screens/Moderation.tsx:233 +#: src/view/screens/Moderation.tsx:252 msgid "Note: Bluesky is an open and public network. This setting only limits the visibility of your content on the Bluesky app and website, and other apps may not respect this setting. Your content may still be shown to logged-out users by other apps and websites." msgstr "ŠŸŃ€ŠøŠ¼Ń–Ń‚ŠŗŠ°: Bluesky є Š²Ń–Š“ŠŗŃ€ŠøŃ‚Š¾ŃŽ і ŠæŃƒŠ±Š»Ń–Ń‡Š½Š¾ŃŽ Š¼ŠµŃ€ŠµŠ¶ŠµŃŽ. Цей параметр Š¾Š±Š¼ŠµŠ¶ŃƒŃ” Š²ŠøŠ“ŠøŠ¼Ń–ŃŃ‚ŃŒ вашого Š²Š¼Ń–ŃŃ‚Ńƒ лише у Š·Š°ŃŃ‚Š¾ŃŃƒŠ½ŠŗŠ°Ń… і на сайті Bluesky, але Ń–Š½ŃˆŃ– Š·Š°ŃŃ‚Š¾ŃŃƒŠ½ŠŗŠø Š¼Š¾Š¶ŃƒŃ‚ŃŒ Ń†ŃŒŠ¾Š³Š¾ не Š“Š¾Ń‚Ń€ŠøŠ¼ŃƒŠ²Š°Ń‚ŠøŃŃ. Š’Š°Ńˆ вміст все ще може Š±ŃƒŃ‚Šø показаний Š²Ń–Š“Š²Ń–Š“ŃƒŠ²Š°Ń‡Š°Š¼ без облікового запису Ń–Š½ŃˆŠøŠ¼Šø Š·Š°ŃŃ‚Š¾ŃŃƒŠ½ŠŗŠ°Š¼Šø і вебсайтами." @@ -2730,7 +2804,7 @@ msgstr "Š”ŠæŠ¾Ń‡Š°Ń‚ŠŗŃƒ Š½Š°Š¹Š“Š°Š²Š½Ń–ŃˆŃ–" msgid "Onboarding reset" msgstr "" -#: src/view/com/composer/Composer.tsx:375 +#: src/view/com/composer/Composer.tsx:382 msgid "One or more images is missing alt text." msgstr "Š”Š»Ń оГного або ŠŗŃ–Š»ŃŒŠŗŠ¾Ń… Š·Š¾Š±Ń€Š°Š¶ŠµŠ½ŃŒ Š²Ń–Š“ŃŃƒŃ‚Š½Ń–Š¹ Š°Š»ŃŒŃ‚ŠµŃ€Š½Š°Ń‚ŠøŠ²Š½ŠøŠ¹ текст." @@ -2747,8 +2821,12 @@ msgstr "" msgid "Open" msgstr "" -#: src/view/com/composer/Composer.tsx:470 -#: src/view/com/composer/Composer.tsx:471 +#: src/view/screens/Moderation.tsx:75 +msgid "Open content filtering settings" +msgstr "" + +#: src/view/com/composer/Composer.tsx:477 +#: src/view/com/composer/Composer.tsx:478 msgid "Open emoji picker" msgstr "ЕмоГжі" @@ -2756,6 +2834,10 @@ msgstr "ЕмоГжі" msgid "Open links with in-app browser" msgstr "" +#: src/view/screens/Moderation.tsx:92 +msgid "Open muted words settings" +msgstr "" + #: src/view/com/home/HomeHeaderLayoutMobile.tsx:49 msgid "Open navigation" msgstr "ВіГкрити Š½Š°Š²Ń–Š³Š°Ń†Ń–ŃŽ" @@ -2832,6 +2914,7 @@ msgstr "ВіГкриває Š½Š°Š»Š°ŃˆŃ‚ŃƒŠ²Š°Š½Š½Ń моГерації" msgid "Opens password reset form" msgstr "" +#: src/view/com/home/HomeHeaderLayout.web.tsx:60 #: src/view/screens/Feeds.tsx:356 msgid "Opens screen to edit Saved Feeds" msgstr "" @@ -3016,7 +3099,7 @@ msgstr "Š‘ŃƒŠ“ŃŒ ласка, Š²ŠŗŠ°Š¶Ń–Ń‚ŃŒ Ń‡Š¾Š¼Ńƒ ви вважаєте що msgid "Please Verify Your Email" msgstr "" -#: src/view/com/composer/Composer.tsx:215 +#: src/view/com/composer/Composer.tsx:222 msgid "Please wait for your link card to finish loading" msgstr "Š‘ŃƒŠ“ŃŒ ласка, зачекайте Гоки Š·Š°Š²ŠµŃ€ŃˆŠøŃ‚ŃŒŃŃ ŃŃ‚Š²Š¾Ń€ŠµŠ½Š½Ń ŠæŠ¾ŠæŠµŃ€ŠµŠ“Š½ŃŒŠ¾Š³Š¾ ŠæŠµŃ€ŠµŠ³Š»ŃŠ“Ńƒ Š“Š»Ń ŠæŠ¾ŃŠøŠ»Š°Š½Š½Ń" @@ -3028,8 +3111,8 @@ msgstr "" msgid "Porn" msgstr "" -#: src/view/com/composer/Composer.tsx:350 -#: src/view/com/composer/Composer.tsx:358 +#: src/view/com/composer/Composer.tsx:357 +#: src/view/com/composer/Composer.tsx:365 msgctxt "action" msgid "Post" msgstr "" @@ -3045,7 +3128,7 @@ msgstr "" #~ msgid "Post" #~ msgstr "ŠŸŠ¾ŃŃ‚" -#: src/view/com/post-thread/PostThreadItem.tsx:173 +#: src/view/com/post-thread/PostThreadItem.tsx:175 msgid "Post by {0}" msgstr "" @@ -3055,11 +3138,11 @@ msgstr "" msgid "Post by @{0}" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:88 +#: src/view/com/util/forms/PostDropdownBtn.tsx:90 msgid "Post deleted" msgstr "" -#: src/view/com/post-thread/PostThread.tsx:461 +#: src/view/com/post-thread/PostThread.tsx:462 msgid "Post hidden" msgstr "ŠŸŠ¾ŃŃ‚ приховано" @@ -3071,14 +3154,22 @@ msgstr "Мова ŠæŠ¾ŃŃ‚Ńƒ" msgid "Post Languages" msgstr "Мови ŠæŠ¾ŃŃ‚Ńƒ" -#: src/view/com/post-thread/PostThread.tsx:513 +#: src/view/com/post-thread/PostThread.tsx:514 msgid "Post not found" msgstr "ŠŸŠ¾ŃŃ‚ не знайГено" +#: src/components/TagMenu/index.tsx:257 +msgid "posts" +msgstr "" + #: src/view/screens/Profile.tsx:180 msgid "Posts" msgstr "ŠŸŠ¾ŃŃ‚Šø" +#: src/components/dialogs/MutedWords.tsx:77 +msgid "Posts can be muted based on their text, their tags, or both." +msgstr "" + #: src/view/com/posts/FeedErrorMessage.tsx:64 msgid "Posts hidden" msgstr "" @@ -3143,11 +3234,11 @@ msgstr "ŠŸŃƒŠ±Š»Ń–Ń‡Š½Ń–, ŠæŠ¾ŃˆŠøŃ€ŃŽŠ²Š°Š½Ń– списки ŠŗŠ¾Ń€ŠøŃŃ‚ŃƒŠ²Š°Ń‡ msgid "Public, shareable lists which can drive feeds." msgstr "ŠŸŃƒŠ±Š»Ń–Ń‡Š½Ń–, ŠæŠ¾ŃˆŠøŃ€ŃŽŠ²Š°Š½Ń– списки Š“Š»Ń ŃŃ‚Š²Š¾Ń€ŠµŠ½Š½Ń стрічок." -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish post" msgstr "" -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish reply" msgstr "" @@ -3190,6 +3281,7 @@ msgstr "РекоменГовані стрічки" msgid "Recommended Users" msgstr "РекоменГовані ŠŗŠ¾Ń€ŠøŃŃ‚ŃƒŠ²Š°Ń‡Ń–" +#: src/components/dialogs/MutedWords.tsx:249 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/SelfLabel.tsx:83 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -3227,6 +3319,10 @@ msgstr "Š’ŠøŠ»ŃƒŃ‡ŠøŃ‚Šø Š·Š¾Š±Ń€Š°Š¶ŠµŠ½Š½Ń" msgid "Remove image preview" msgstr "Š’ŠøŠ»ŃƒŃ‡ŠøŃ‚Šø попереГній ŠæŠµŃ€ŠµŠ³Š»ŃŠ“ Š·Š¾Š±Ń€Š°Š¶ŠµŠ½Š½Ń" +#: src/components/dialogs/MutedWords.tsx:294 +msgid "Remove mute word from your list" +msgstr "" + #: src/view/com/modals/Repost.tsx:47 msgid "Remove repost" msgstr "" @@ -3261,7 +3357,7 @@ msgstr "ВіГповіГі" msgid "Replies to this thread are disabled" msgstr "ВіГповіГі Го Ń†ŃŒŠ¾Š³Š¾ ŠæŠ¾ŃŃ‚Ńƒ вимкнено" -#: src/view/com/composer/Composer.tsx:348 +#: src/view/com/composer/Composer.tsx:355 msgctxt "action" msgid "Reply" msgstr "" @@ -3271,7 +3367,7 @@ msgid "Reply Filters" msgstr "ŠÆŠŗŃ– віГповіГі ŠæŠ¾ŠŗŠ°Š·ŃƒŠ²Š°Ń‚Šø" #: src/view/com/post/Post.tsx:167 -#: src/view/com/posts/FeedItem.tsx:285 +#: src/view/com/posts/FeedItem.tsx:287 msgctxt "description" msgid "Reply to <0/>" msgstr "" @@ -3293,7 +3389,7 @@ msgid "Report List" msgstr "ŠŸŠ¾ŃŠŗŠ°Ń€Š¶ŠøŃ‚ŠøŃŃŒ на список" #: src/view/com/modals/report/SendReportButton.tsx:37 -#: src/view/com/util/forms/PostDropdownBtn.tsx:239 +#: src/view/com/util/forms/PostDropdownBtn.tsx:255 msgid "Report post" msgstr "ŠŸŠ¾ŃŠŗŠ°Ń€Š¶ŠøŃ‚ŠøŃŃŒ на пост" @@ -3322,7 +3418,7 @@ msgstr "Репостити або Ń†ŠøŃ‚ŃƒŠ²Š°Ń‚Šø" msgid "Reposted By" msgstr "" -#: src/view/com/posts/FeedItem.tsx:205 +#: src/view/com/posts/FeedItem.tsx:207 msgid "Reposted by {0}" msgstr "" @@ -3330,7 +3426,7 @@ msgstr "" #~ msgid "Reposted by {0})" #~ msgstr "" -#: src/view/com/posts/FeedItem.tsx:222 +#: src/view/com/posts/FeedItem.tsx:224 msgid "Reposted by <0/>" msgstr "" @@ -3338,7 +3434,7 @@ msgstr "" msgid "reposted your post" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:186 +#: src/view/com/post-thread/PostThreadItem.tsx:188 msgid "Reposts of this post" msgstr "" @@ -3501,9 +3597,9 @@ msgstr "" #: src/view/com/modals/ListAddRemoveUsers.tsx:75 #: src/view/com/util/forms/SearchInput.tsx:67 #: src/view/com/util/forms/SearchInput.tsx:79 -#: src/view/screens/Search/Search.tsx:418 -#: src/view/screens/Search/Search.tsx:645 -#: src/view/screens/Search/Search.tsx:663 +#: src/view/screens/Search/Search.tsx:419 +#: src/view/screens/Search/Search.tsx:668 +#: src/view/screens/Search/Search.tsx:686 #: src/view/shell/bottom-bar/BottomBar.tsx:159 #: src/view/shell/desktop/LeftNav.tsx:324 #: src/view/shell/desktop/Search.tsx:214 @@ -3513,11 +3609,19 @@ msgstr "" msgid "Search" msgstr "Пошук" -#: src/view/screens/Search/Search.tsx:712 +#: src/view/screens/Search/Search.tsx:735 #: src/view/shell/desktop/Search.tsx:255 msgid "Search for \"{query}\"" msgstr "" +#: src/components/TagMenu/index.tsx:145 +msgid "Search for all posts by @{authorHandle} with tag {tag}" +msgstr "" + +#: src/components/TagMenu/index.tsx:90 +msgid "Search for all posts with tag {tag}" +msgstr "" + #: src/view/screens/Search/Search.tsx:390 #~ msgid "Search for posts and users." #~ msgstr "" @@ -3532,6 +3636,22 @@ msgstr "Пошук ŠŗŠ¾Ń€ŠøŃŃ‚ŃƒŠ²Š°Ń‡Ń–Š²" msgid "Security Step Required" msgstr "ŠŸŠ¾Ń‚Ń€Ń–Š±ŠµŠ½ коГ ŠæŃ–Š“Ń‚Š²ŠµŃ€Š“Š¶ŠµŠ½Š½Ń" +#: src/components/TagMenu/index.web.tsx:50 +msgid "See {truncatedTag} posts" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:67 +msgid "See {truncatedTag} posts by user" +msgstr "" + +#: src/components/TagMenu/index.tsx:128 +msgid "See <0>{tag} posts" +msgstr "" + +#: src/components/TagMenu/index.tsx:189 +msgid "See <0>{tag} posts by this user" +msgstr "" + #: src/view/screens/SavedFeeds.tsx:163 msgid "See this guide" msgstr "" @@ -3749,7 +3869,7 @@ msgid "Share" msgstr "" #: src/view/com/profile/ProfileHeader.tsx:295 -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 #: src/view/screens/ProfileList.tsx:418 msgid "Share" msgstr "ŠŸŠ¾ŃˆŠøŃ€ŠøŃ‚Šø" @@ -3786,9 +3906,9 @@ msgstr "ŠŸŠ¾ŠŗŠ°Š·Š°Ń‚Šø Š²Š±ŃƒŠ“ŃƒŠ²Š°Š½Š½Ń Š· {0}" msgid "Show follows similar to {0}" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:532 -#: src/view/com/post/Post.tsx:196 -#: src/view/com/posts/FeedItem.tsx:359 +#: src/view/com/post-thread/PostThreadItem.tsx:538 +#: src/view/com/post/Post.tsx:198 +#: src/view/com/posts/FeedItem.tsx:363 msgid "Show More" msgstr "" @@ -3956,7 +4076,7 @@ msgstr "" msgid "Something went wrong. Check your email and try again." msgstr "" -#: src/App.native.tsx:61 +#: src/App.native.tsx:63 msgid "Sorry! Your session expired. Please log in again." msgstr "" @@ -4022,7 +4142,7 @@ msgstr "ŠŸŃ–Š“ŠæŠøŃŠ°Ń‚ŠøŃŃ на цей список" #~ msgid "Subscribed" #~ msgstr "" -#: src/view/screens/Search/Search.tsx:373 +#: src/view/screens/Search/Search.tsx:374 msgid "Suggested Follows" msgstr "ŠŸŃ€Š¾ŠæŠ¾Š½Š¾Š²Š°Š½Ń– піГписки" @@ -4066,6 +4186,14 @@ msgstr "" msgid "System log" msgstr "Дистемний Š¶ŃƒŃ€Š½Š°Š»" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "tag" +msgstr "" + +#: src/components/TagMenu/index.tsx:74 +msgid "Tag menu: {tag}" +msgstr "" + #: src/view/com/modals/crop-image/CropImage.web.tsx:112 msgid "Tall" msgstr "Високе" @@ -4089,6 +4217,10 @@ msgstr "Умови" msgid "Terms of Service" msgstr "Умови Š’ŠøŠŗŠ¾Ń€ŠøŃŃ‚Š°Š½Š½Ń" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "text" +msgstr "" + #: src/view/com/modals/AppealLabel.tsx:70 #: src/view/com/modals/report/InputIssueDetails.tsx:51 msgid "Text input field" @@ -4114,7 +4246,7 @@ msgstr "ŠŸŠ¾Š»Ń–Ń‚ŠøŠŗŃƒ Š·Š°Ń…ŠøŃŃ‚Ńƒ Š°Š²Ń‚Š¾Ń€ŃŃŒŠŗŠ¾Š³Š¾ права пер msgid "The following steps will help customize your Bluesky experience." msgstr "" -#: src/view/com/post-thread/PostThread.tsx:516 +#: src/view/com/post-thread/PostThread.tsx:517 msgid "The post may have been deleted." msgstr "Можливо цей пост було виГалено." @@ -4296,7 +4428,7 @@ msgstr "" msgid "This name is already in use" msgstr "" -#: src/view/com/post-thread/PostThreadItem.tsx:123 +#: src/view/com/post-thread/PostThreadItem.tsx:125 msgid "This post has been deleted." msgstr "Цей пост було виГалено." @@ -4320,7 +4452,11 @@ msgstr "" msgid "This warning is only available for posts with media attached." msgstr "Це ŠæŠ¾ŠæŠµŃ€ŠµŠ“Š¶ŠµŠ½Š½Ń Š“Š¾ŃŃ‚ŃƒŠæŠ½Šµ Ń‚Ń–Š»ŃŒŠŗŠø Š“Š»Ń записів Š· прикріпленими меГіа-файлами." -#: src/view/com/util/forms/PostDropdownBtn.tsx:221 +#: src/components/dialogs/MutedWords.tsx:236 +msgid "This will delete {0} from your muted words. You can always add it back later." +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:237 msgid "This will hide this post from your feeds." msgstr "Це приховає цей пост Ń–Š· Š²Š°ŃˆŠ¾Ń— стрічки." @@ -4337,6 +4473,10 @@ msgstr "Режим гілок" msgid "Threads Preferences" msgstr "" +#: src/components/dialogs/MutedWords.tsx:95 +msgid "Toggle between muted word options." +msgstr "" + #: src/view/com/util/forms/DropdownButton.tsx:246 msgid "Toggle dropdown" msgstr "Розкрити/сховати" @@ -4345,9 +4485,9 @@ msgstr "Розкрити/сховати" msgid "Transformations" msgstr "Š ŠµŠ“Š°Š³ŃƒŠ²Š°Š½Š½Ń" -#: src/view/com/post-thread/PostThreadItem.tsx:679 -#: src/view/com/post-thread/PostThreadItem.tsx:681 -#: src/view/com/util/forms/PostDropdownBtn.tsx:154 +#: src/view/com/post-thread/PostThreadItem.tsx:685 +#: src/view/com/post-thread/PostThreadItem.tsx:687 +#: src/view/com/util/forms/PostDropdownBtn.tsx:156 msgid "Translate" msgstr "ŠŸŠµŃ€ŠµŠŗŠ»Š°ŃŃ‚Šø" @@ -4416,15 +4556,24 @@ msgstr "ŠŠ° жаль, ви не віГповіГаєте вимогам Š“Š»Ń msgid "Unlike" msgstr "" +#: src/components/TagMenu/index.tsx:253 #: src/view/screens/ProfileList.tsx:597 msgid "Unmute" msgstr "" +#: src/components/TagMenu/index.web.tsx:90 +msgid "Unmute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:326 msgid "Unmute Account" msgstr "ŠŸŠµŃ€ŠµŃŃ‚Š°Ń‚Šø Ń–Š³Š½Š¾Ń€ŃƒŠ²Š°Ń‚Šø" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/TagMenu/index.tsx:210 +msgid "Unmute all {tag} posts" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Unmute thread" msgstr "ŠŸŠµŃ€ŠµŃŃ‚Š°Ń‚Šø Ń–Š³Š½Š¾Ń€ŃƒŠ²Š°Ń‚Šø" @@ -4633,6 +4782,10 @@ msgstr "" #~ msgid "We recommend \"For You\" by Skygaze:" #~ msgstr "" +#: src/components/dialogs/MutedWords.tsx:161 +msgid "We recommend avoiding common words that appear in many posts, since it can result in no posts being shown." +msgstr "" + #: src/screens/Onboarding/StepAlgoFeeds/index.tsx:124 msgid "We recommend our \"Discover\" feed:" msgstr "" @@ -4669,7 +4822,11 @@ msgstr "Ми Гуже раГі, що ви ŠæŃ€ŠøŃ”Š“Š½Š°Š»ŠøŃŃ!" msgid "We're sorry, but we were unable to resolve this list. If this persists, please contact the list creator, @{handleOrDid}." msgstr "" -#: src/view/screens/Search/Search.tsx:253 +#: src/components/dialogs/MutedWords.tsx:182 +msgid "We're sorry, but we weren't able to load your muted words at this time. Please try again." +msgstr "" + +#: src/view/screens/Search/Search.tsx:254 msgid "We're sorry, but your search could not be completed. Please try again in a few minutes." msgstr "Š”Š°Ń€ŃƒŠ¹Ń‚Šµ, нам не Š²Š“Š°Š»Š¾ŃŃ виконати пошук за вашим запитом. Š‘ŃƒŠ“ŃŒ ласка, ŃŠæŃ€Š¾Š±ŃƒŠ¹Ń‚Šµ ще раз через ŠŗŃ–Š»ŃŒŠŗŠ° хвилин." @@ -4690,7 +4847,7 @@ msgid "What is the issue with this {collectionName}?" msgstr "Яка проблема Š· {collectionName}?" #: src/view/com/auth/SplashScreen.tsx:59 -#: src/view/com/composer/Composer.tsx:279 +#: src/view/com/composer/Composer.tsx:286 msgid "What's up?" msgstr "ŠÆŠŗ справи?" @@ -4715,11 +4872,11 @@ msgstr "Єто може віГповіГати" msgid "Wide" msgstr "Широке" -#: src/view/com/composer/Composer.tsx:415 +#: src/view/com/composer/Composer.tsx:422 msgid "Write post" msgstr "ŠŠ°ŠæŠøŃŠ°Ń‚Šø пост" -#: src/view/com/composer/Composer.tsx:278 +#: src/view/com/composer/Composer.tsx:285 #: src/view/com/composer/Prompt.tsx:33 msgid "Write your reply" msgstr "ŠŠ°ŠæŠøŃŠ°Ń‚Šø Š²Ń–Š“ŠæŠ¾Š²Ń–Š“ŃŒ" @@ -4788,7 +4945,7 @@ msgstr "Š£ вас немає збережених стрічок!" msgid "You don't have any saved feeds." msgstr "Š£ вас немає збережених стрічок." -#: src/view/com/post-thread/PostThread.tsx:464 +#: src/view/com/post-thread/PostThread.tsx:465 msgid "You have blocked the author or you have been blocked by the author." msgstr "Š’Šø заблокували автора або автор заблокував вас." @@ -4828,6 +4985,10 @@ msgstr "Š’Šø ще не створили жоГного ŠæŠ°Ń€Š¾Š»Ń Š“Š»Ń за msgid "You have not muted any accounts yet. To mute an account, go to their profile and selected \"Mute account\" from the menu on their account." msgstr "Š’Šø ще не Ń–Š³Š½Š¾Ń€ŃƒŃ”Ń‚Šµ жоГного облікового запису. Щоб Ń–Š³Š½Š¾Ń€ŃƒŠ²Š°Ń‚Šø когось, ŠæŠµŃ€ŠµŠ¹Š“Ń–Ń‚ŃŒ Го їх ŠæŃ€Š¾Ń„Ń–Š»ŃŽ та Š²ŠøŠ±ŠµŃ€Ń–Ń‚ŃŒ Š¾ŠæŃ†Ń–ŃŽ \"Š†Š³Š½Š¾Ń€ŃƒŠ²Š°Ń‚Šø\" у Š¼ŠµŠ½ŃŽ їх облікового запису." +#: src/components/dialogs/MutedWords.tsx:202 +msgid "You haven't muted any words or tags yet" +msgstr "" + #: src/view/com/modals/ContentFilteringSettings.tsx:175 msgid "You must be 18 or older to enable adult content." msgstr "" @@ -4836,11 +4997,11 @@ msgstr "" msgid "You must be 18 years or older to enable adult content" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:127 +#: src/view/com/util/forms/PostDropdownBtn.tsx:129 msgid "You will no longer receive notifications for this thread" msgstr "" -#: src/view/com/util/forms/PostDropdownBtn.tsx:130 +#: src/view/com/util/forms/PostDropdownBtn.tsx:132 msgid "You will now receive notifications for this thread" msgstr "" @@ -4930,11 +5091,15 @@ msgstr "" #~ msgid "Your invite codes are hidden when logged in using an App Password" #~ msgstr "Š’Š°ŃˆŃ– коГи Š·Š°ŠæŃ€Š¾ŃˆŠµŠ½Š½Ń приховано, ŃŠŗŃ‰Š¾ ви ŃƒŠ²Ń–Š¹ŃˆŠ»Šø за Š“Š¾ŠæŠ¾Š¼Š¾Š³Š¾ŃŽ ŠæŠ°Ń€Š¾Š»Ń Š“Š»Ń Š·Š°ŃŃ‚Š¾ŃŃƒŠ½ŠŗŃ–Š²" +#: src/components/dialogs/MutedWords.tsx:173 +msgid "Your muted words" +msgstr "" + #: src/view/com/modals/ChangePassword.tsx:155 msgid "Your password has been changed successfully!" msgstr "" -#: src/view/com/composer/Composer.tsx:267 +#: src/view/com/composer/Composer.tsx:274 msgid "Your post has been published" msgstr "" @@ -4961,7 +5126,7 @@ msgstr "Š’Š°Ńˆ ŠæŃ€Š¾Ń„Ń–Š»ŃŒ" #~ msgid "Your profile and posts will not be visible to people visiting the Bluesky app or website without having an account and being logged in." #~ msgstr "" -#: src/view/com/composer/Composer.tsx:266 +#: src/view/com/composer/Composer.tsx:273 msgid "Your reply has been published" msgstr "" diff --git a/src/locale/locales/zh-CN/messages.po b/src/locale/locales/zh-CN/messages.po index aa7b24c9c6..c4447af264 100644 --- a/src/locale/locales/zh-CN/messages.po +++ b/src/locale/locales/zh-CN/messages.po @@ -76,7 +76,7 @@ msgid "A new version of the app is available. Please update to continue using th msgstr "App ę–°ē‰ˆęœ¬å·²å‘åøƒļ¼ŒčÆ·ę›“ę–°ä»„ē»§ē»­ä½æē”Øć€‚" #: src/view/com/util/ViewHeader.tsx:83 -#: src/view/screens/Search/Search.tsx:624 +#: src/view/screens/Search/Search.tsx:647 msgid "Access navigation links and settings" msgstr "č®æé—®åÆ¼čˆŖé“¾ęŽ„åŠč®¾ē½®" @@ -127,6 +127,7 @@ msgstr "å·²å–ę¶ˆå±č”½č“¦ęˆ·" msgid "Account unmuted" msgstr "å·²å–ę¶ˆéšč—č“¦ęˆ·" +#: src/components/dialogs/MutedWords.tsx:147 #: src/view/com/auth/onboarding/RecommendedFeedsItem.tsx:150 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -168,14 +169,22 @@ msgstr "ę·»åŠ ē»†čŠ‚" msgid "Add details to report" msgstr "č”„å……åé¦ˆčÆ¦ē»†å†…å®¹" -#: src/view/com/composer/Composer.tsx:446 +#: src/view/com/composer/Composer.tsx:453 msgid "Add link card" msgstr "ę·»åŠ é“¾ęŽ„å”ē‰‡" -#: src/view/com/composer/Composer.tsx:451 +#: src/view/com/composer/Composer.tsx:458 msgid "Add link card:" msgstr "ę·»åŠ é“¾ęŽ„å”ē‰‡:" +#: src/components/dialogs/MutedWords.tsx:140 +msgid "Add mute word for configured settings" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:74 +msgid "Add muted words and tags" +msgstr "" + #: src/view/com/modals/ChangeHandle.tsx:417 msgid "Add the following DNS record to your domain:" msgstr "将仄下DNSč®°å½•ę·»åŠ åˆ°ä½ ēš„åŸŸå:" @@ -295,7 +304,7 @@ msgstr "App 专用密码设置" msgid "App Passwords" msgstr "App 专用密码" -#: src/view/com/util/forms/PostDropdownBtn.tsx:279 +#: src/view/com/util/forms/PostDropdownBtn.tsx:295 msgid "Appeal content warning" msgstr "ē”³čÆ‰å†…å®¹č­¦å‘Š" @@ -319,15 +328,16 @@ msgstr "外观" msgid "Are you sure you want to delete the app password \"{name}\"?" msgstr "ä½ ē”®å®šč¦åˆ é™¤čæ™ę” App 专用密码 \"{name}\"?" -#: src/view/com/composer/Composer.tsx:143 +#: src/view/com/composer/Composer.tsx:150 msgid "Are you sure you'd like to discard this draft?" msgstr "ä½ ē”®å®šč¦äø¢å¼ƒę­¤č‰ēØæå—ļ¼Ÿ" +#: src/components/dialogs/MutedWords.tsx:233 #: src/view/screens/ProfileList.tsx:365 msgid "Are you sure?" msgstr "ä½ ē”®å®šå—ļ¼Ÿ" -#: src/view/com/util/forms/PostDropdownBtn.tsx:262 +#: src/view/com/util/forms/PostDropdownBtn.tsx:278 msgid "Are you sure? This cannot be undone." msgstr "ä½ ē”®å®šå—ļ¼Ÿę­¤ę“ä½œę— ę³•ę’¤é”€ć€‚" @@ -349,15 +359,15 @@ msgstr "č‰ŗęœÆä½œå“ęˆ–éžč‰²ęƒ…ēš„č£øä½“ć€‚" #: src/view/com/auth/login/LoginForm.tsx:259 #: src/view/com/auth/login/SetNewPasswordForm.tsx:179 #: src/view/com/modals/report/InputIssueDetails.tsx:46 -#: src/view/com/post-thread/PostThread.tsx:471 -#: src/view/com/post-thread/PostThread.tsx:521 -#: src/view/com/post-thread/PostThread.tsx:529 +#: src/view/com/post-thread/PostThread.tsx:472 +#: src/view/com/post-thread/PostThread.tsx:522 +#: src/view/com/post-thread/PostThread.tsx:530 #: src/view/com/profile/ProfileHeader.tsx:649 #: src/view/com/util/ViewHeader.tsx:81 msgid "Back" msgstr "čæ”å›ž" -#: src/view/com/post-thread/PostThread.tsx:479 +#: src/view/com/post-thread/PostThread.tsx:480 msgctxt "action" msgid "Back" msgstr "čæ”å›ž" @@ -405,7 +415,7 @@ msgstr "å±č”½čæ™äøŖåˆ—č”Ø" msgid "Blocked" msgstr "å·²å±č”½" -#: src/view/screens/Moderation.tsx:123 +#: src/view/screens/Moderation.tsx:142 msgid "Blocked accounts" msgstr "å·²å±č”½č“¦ęˆ·" @@ -464,7 +474,7 @@ msgstr "Bluesky äøŗå…¬ä¼—č€Œē”Ÿć€‚" msgid "Bluesky uses invites to build a healthier community. If you don't know anybody with an invite, you can sign up for the waitlist and we'll send one soon." msgstr "Bluesky ä½æē”Øé‚€čÆ·åˆ¶ę„ę‰“é€ ę›“å„åŗ·ēš„ē¤¾ē¾¤ēŽÆå¢ƒć€‚ å¦‚ęžœä½ äøč®¤čÆ†ę‹„ęœ‰é‚€čÆ·ē ēš„äŗŗļ¼Œä½ åÆä»„å…ˆå”«å†™å¹¶ęäŗ¤å€™č”„åˆ—č”Øļ¼Œęˆ‘ä»¬ä¼šå°½åæ«å®”ę øå¹¶å‘é€é‚€čÆ·ē ć€‚" -#: src/view/screens/Moderation.tsx:226 +#: src/view/screens/Moderation.tsx:245 msgid "Bluesky will not show your profile and posts to logged-out users. Other apps may not honor this request. This does not make your account private." msgstr "Bluesky äøä¼šå‘ęœŖē™»å½•ēš„ē”Øęˆ·ę˜¾ē¤ŗä½ ēš„äøŖäŗŗčµ„ę–™å’Œåø–å­ć€‚ä½†å…¶ä»–åŗ”ē”ØåÆčƒ½äøä¼šéµē…§ę­¤čÆ·ę±‚ļ¼Œčæ™ę— ę³•ē”®äæä½ ēš„č“¦ęˆ·éšē§ć€‚" @@ -516,8 +526,8 @@ msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must msgstr "åŖčƒ½åŒ…å«å­—ęÆć€ę•°å­—ć€ē©ŗę ¼ć€ē “ęŠ˜å·åŠäø‹åˆ’ēŗæć€‚ 长度必锻至少 4 äøŖå­—ē¬¦ļ¼Œä½†äøč¶…čæ‡ 32 个字符。" #: src/components/Prompt.tsx:91 -#: src/view/com/composer/Composer.tsx:300 -#: src/view/com/composer/Composer.tsx:305 +#: src/view/com/composer/Composer.tsx:307 +#: src/view/com/composer/Composer.tsx:312 #: src/view/com/modals/ChangeEmail.tsx:218 #: src/view/com/modals/ChangeEmail.tsx:220 #: src/view/com/modals/ChangePassword.tsx:265 @@ -531,7 +541,7 @@ msgstr "åŖčƒ½åŒ…å«å­—ęÆć€ę•°å­—ć€ē©ŗę ¼ć€ē “ęŠ˜å·åŠäø‹åˆ’ēŗæć€‚ 长度 #: src/view/com/modals/VerifyEmail.tsx:247 #: src/view/com/modals/VerifyEmail.tsx:253 #: src/view/com/modals/Waitlist.tsx:142 -#: src/view/screens/Search/Search.tsx:693 +#: src/view/screens/Search/Search.tsx:716 #: src/view/shell/desktop/Search.tsx:238 msgid "Cancel" msgstr "å–ę¶ˆ" @@ -678,7 +688,7 @@ msgid "Clear all storage data (restart after this)" msgstr "ęø…é™¤ę‰€ęœ‰ę•°ę®ļ¼ˆå¹¶é‡åÆļ¼‰" #: src/view/com/util/forms/SearchInput.tsx:88 -#: src/view/screens/Search/Search.tsx:674 +#: src/view/screens/Search/Search.tsx:697 msgid "Clear search query" msgstr "ęø…é™¤ęœē“¢åŽ†å²č®°å½•" @@ -686,6 +696,11 @@ msgstr "ęø…é™¤ęœē“¢åŽ†å²č®°å½•" msgid "click here" msgstr "ē‚¹å‡»čæ™é‡Œ" +#: src/components/RichText.tsx:189 +#: src/components/TagMenu/index.web.tsx:125 +msgid "Click here to open tag menu for {tag}" +msgstr "" + #: src/screens/Onboarding/index.tsx:35 msgid "Climate" msgstr "갔豔" @@ -716,11 +731,15 @@ msgstr "关闭图片" msgid "Close image viewer" msgstr "å…³é—­å›¾ē‰‡ęŸ„ēœ‹å™Ø" -#: src/view/shell/index.web.tsx:49 +#: src/view/shell/index.web.tsx:51 msgid "Close navigation footer" msgstr "å…³é—­åÆ¼čˆŖé”µč„š" -#: src/view/shell/index.web.tsx:50 +#: src/components/TagMenu/index.tsx:266 +msgid "Close this dialog" +msgstr "" + +#: src/view/shell/index.web.tsx:52 msgid "Closes bottom navigation bar" msgstr "å…³é—­åŗ•ę " @@ -728,7 +747,7 @@ msgstr "å…³é—­åŗ•ę " msgid "Closes password update alert" msgstr "å…³é—­åÆ†ē ę›“ę–°č­¦å‘Š" -#: src/view/com/composer/Composer.tsx:302 +#: src/view/com/composer/Composer.tsx:309 msgid "Closes post composer and discards post draft" msgstr "å…³é—­åø–å­ē¼–č¾‘é”µå¹¶äø¢å¼ƒč‰ēØæ" @@ -761,7 +780,7 @@ msgstr "å®Œęˆå¼•åÆ¼å¹¶å¼€å§‹ä½æē”Øä½ ēš„č“¦ęˆ·" msgid "Complete the challenge" msgstr "" -#: src/view/com/composer/Composer.tsx:417 +#: src/view/com/composer/Composer.tsx:424 msgid "Compose posts up to {MAX_GRAPHEME_LENGTH} characters in length" msgstr "ę’°å†™åø–å­ēš„é•æåŗ¦ęœ€å¤šäøŗ {MAX_GRAPHEME_LENGTH} 个字符" @@ -825,7 +844,7 @@ msgstr "čæžęŽ„äø­..." msgid "Contact support" msgstr "č”ē³»ę”ÆęŒ" -#: src/view/screens/Moderation.tsx:81 +#: src/view/screens/Moderation.tsx:83 msgid "Content filtering" msgstr "内容过滤" @@ -891,7 +910,7 @@ msgstr "å·²å¤åˆ¶ęž„å»ŗē‰ˆęœ¬å·č‡³å‰Ŗč““ęæ" #: src/view/com/modals/AddAppPasswords.tsx:76 #: src/view/com/modals/InviteCodes.tsx:152 -#: src/view/com/util/forms/PostDropdownBtn.tsx:141 +#: src/view/com/util/forms/PostDropdownBtn.tsx:143 msgid "Copied to clipboard" msgstr "å·²å¤åˆ¶č‡³å‰Ŗč““ęæ" @@ -907,7 +926,7 @@ msgstr "复制" msgid "Copy link to list" msgstr "å¤åˆ¶åˆ—č”Øé“¾ęŽ„" -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 msgid "Copy link to post" msgstr "å¤åˆ¶åø–å­é“¾ęŽ„" @@ -915,7 +934,7 @@ msgstr "å¤åˆ¶åø–å­é“¾ęŽ„" msgid "Copy link to profile" msgstr "å¤åˆ¶äøŖäŗŗčµ„ę–™é“¾ęŽ„" -#: src/view/com/util/forms/PostDropdownBtn.tsx:168 +#: src/view/com/util/forms/PostDropdownBtn.tsx:170 msgid "Copy post text" msgstr "å¤åˆ¶åø–å­ę–‡å­—" @@ -971,7 +990,7 @@ msgstr "ē”± <0/> åˆ›å»ŗ" msgid "Created by you" msgstr "ē”±ä½ åˆ›å»ŗ" -#: src/view/com/composer/Composer.tsx:448 +#: src/view/com/composer/Composer.tsx:455 msgid "Creates a card with a thumbnail. The card links to {url}" msgstr "åˆ›å»ŗåø¦ęœ‰ē¼©ē•„å›¾ēš„å”ē‰‡ć€‚čÆ„å”ē‰‡é“¾ęŽ„åˆ° {url}" @@ -1048,11 +1067,11 @@ msgstr "åˆ é™¤ęˆ‘ēš„č“¦ęˆ·" msgid "Delete My Account…" msgstr "åˆ é™¤ęˆ‘ēš„č“¦ęˆ·ā€¦" -#: src/view/com/util/forms/PostDropdownBtn.tsx:257 +#: src/view/com/util/forms/PostDropdownBtn.tsx:273 msgid "Delete post" msgstr "åˆ é™¤åø–å­" -#: src/view/com/util/forms/PostDropdownBtn.tsx:261 +#: src/view/com/util/forms/PostDropdownBtn.tsx:277 msgid "Delete this post?" msgstr "åˆ é™¤čæ™ę”åø–å­ļ¼Ÿ" @@ -1075,7 +1094,7 @@ msgstr "ęčæ°" #~ msgid "Developer Tools" #~ msgstr "å¼€å‘č€…å·„å…·" -#: src/view/com/composer/Composer.tsx:211 +#: src/view/com/composer/Composer.tsx:218 msgid "Did you want to say anything?" msgstr "ęœ‰ä»€ä¹ˆęƒ³čÆ“ēš„å—ļ¼Ÿ" @@ -1083,15 +1102,15 @@ msgstr "ęœ‰ä»€ä¹ˆęƒ³čÆ“ēš„å—ļ¼Ÿ" msgid "Dim" msgstr "ęš—ę·”" -#: src/view/com/composer/Composer.tsx:144 +#: src/view/com/composer/Composer.tsx:151 msgid "Discard" msgstr "丢弃" -#: src/view/com/composer/Composer.tsx:138 +#: src/view/com/composer/Composer.tsx:145 msgid "Discard draft" msgstr "äø¢å¼ƒč‰ēØæ" -#: src/view/screens/Moderation.tsx:207 +#: src/view/screens/Moderation.tsx:226 msgid "Discourage apps from showing my account to logged-out users" msgstr "é˜»ę­¢åŗ”ē”Øå‘ęœŖē™»å½•ē”Øęˆ·ę˜¾ē¤ŗęˆ‘ēš„č“¦ęˆ·" @@ -1170,7 +1189,7 @@ msgstr "" msgid "Download CAR file" msgstr "" -#: src/view/com/composer/text-input/TextInput.web.tsx:247 +#: src/view/com/composer/text-input/TextInput.web.tsx:249 msgid "Drop to add images" msgstr "ę‹–ę”¾å³åÆę·»åŠ å›¾ē‰‡" @@ -1242,6 +1261,7 @@ msgstr "编辑资料" msgid "Edit Profile" msgstr "编辑资料" +#: src/view/com/home/HomeHeaderLayout.web.tsx:59 #: src/view/screens/Feeds.tsx:355 msgid "Edit Saved Feeds" msgstr "ē¼–č¾‘äæå­˜ēš„äæ”ęÆęµ" @@ -1324,6 +1344,11 @@ msgstr "ē»“ęŸäæ”ęÆęµ" msgid "Enter a name for this App Password" msgstr "äøŗę­¤ App äø“ē”ØåÆ†ē å‘½å" +#: src/components/dialogs/MutedWords.tsx:87 +#: src/components/dialogs/MutedWords.tsx:88 +msgid "Enter a word or tag" +msgstr "" + #: src/view/com/modals/VerifyEmail.tsx:105 msgid "Enter Confirmation Code" msgstr "č¾“å…„éŖŒčÆē " @@ -1373,7 +1398,7 @@ msgstr "č¾“å…„ä½ ēš„ē”Øęˆ·åå’ŒåÆ†ē " msgid "Error receiving captcha response." msgstr "" -#: src/view/screens/Search/Search.tsx:109 +#: src/view/screens/Search/Search.tsx:110 msgid "Error:" msgstr "é”™čÆÆļ¼š" @@ -1444,7 +1469,7 @@ msgstr "åˆ›å»ŗ App 专用密码失蓄。" msgid "Failed to create the list. Check your internet connection and try again." msgstr "ę— ę³•åˆ›å»ŗåˆ—č”Øć€‚čÆ·ę£€ęŸ„ä½ ēš„äŗ’č”ē½‘čæžęŽ„å¹¶é‡čÆ•ć€‚" -#: src/view/com/util/forms/PostDropdownBtn.tsx:108 +#: src/view/com/util/forms/PostDropdownBtn.tsx:110 msgid "Failed to delete post, please try again" msgstr "ę— ę³•åˆ é™¤åø–å­ļ¼ŒčÆ·é‡čÆ•" @@ -1466,8 +1491,8 @@ msgid "Feed offline" msgstr "俔息流已离线" #: src/view/com/feeds/FeedPage.tsx:143 -msgid "Feed Preferences" -msgstr "俔息流首选锹" +#~ msgid "Feed Preferences" +#~ msgstr "俔息流首选锹" #: src/view/shell/desktop/RightNav.tsx:61 #: src/view/shell/Drawer.tsx:311 @@ -1511,11 +1536,11 @@ msgstr "ęœ€ē»ˆē”®å®š" msgid "Find accounts to follow" msgstr "åÆ»ę‰¾äø€äŗ›č“¦ęˆ·å…³ę³Ø" -#: src/view/screens/Search/Search.tsx:439 +#: src/view/screens/Search/Search.tsx:440 msgid "Find users on Bluesky" msgstr "åÆ»ę‰¾äø€äŗ›ę­£åœØä½æē”Ø Bluesky ēš„ē”Øęˆ·" -#: src/view/screens/Search/Search.tsx:437 +#: src/view/screens/Search/Search.tsx:438 msgid "Find users with the search tool on the right" msgstr "ä½æē”Øå³ä¾§ēš„å·„å…·ę„ęœē“¢ē”Øęˆ·" @@ -1612,6 +1637,7 @@ msgid "Following {0}" msgstr "ę­£åœØå…³ę³Ø {0}" #: src/Navigation.tsx:248 +#: src/view/com/home/HomeHeaderLayout.web.tsx:45 #: src/view/com/home/HomeHeaderLayoutMobile.tsx:83 #: src/view/screens/PreferencesFollowingFeed.tsx:104 #: src/view/screens/Settings/index.tsx:543 @@ -1651,7 +1677,7 @@ msgstr "åæ˜č®°åÆ†ē " msgid "Forgot Password" msgstr "åæ˜č®°åÆ†ē " -#: src/view/com/posts/FeedItem.tsx:187 +#: src/view/com/posts/FeedItem.tsx:189 msgctxt "from-feed" msgid "From <0/>" msgstr "ę„č‡Ŗ <0/>" @@ -1684,7 +1710,7 @@ msgstr "čæ”å›ž" msgid "Go back to previous step" msgstr "čæ”å›žäøŠäø€ę­„" -#: src/view/screens/Search/Search.tsx:724 +#: src/view/screens/Search/Search.tsx:747 #: src/view/shell/desktop/Search.tsx:262 msgid "Go to @{queryMaybeHandle}" msgstr "转到 @{queryMaybeHandle}" @@ -1701,6 +1727,10 @@ msgstr "č½¬åˆ°äø‹äø€äøŖ" msgid "Handle" msgstr "ē”Øęˆ·čÆ†åˆ«ē¬¦" +#: src/components/RichText.tsx:188 +msgid "Hashtag: {tag}" +msgstr "" + #: src/view/com/auth/create/CreateAccount.tsx:208 msgid "Having trouble?" msgstr "ä»»ä½•ē–‘é—®ļ¼Ÿ" @@ -1739,7 +1769,7 @@ msgctxt "action" msgid "Hide" msgstr "隐藏" -#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +#: src/view/com/util/forms/PostDropdownBtn.tsx:232 msgid "Hide post" msgstr "éšč—åø–å­" @@ -1748,7 +1778,7 @@ msgstr "éšč—åø–å­" msgid "Hide the content" msgstr "éšč—å†…å®¹" -#: src/view/com/util/forms/PostDropdownBtn.tsx:220 +#: src/view/com/util/forms/PostDropdownBtn.tsx:236 msgid "Hide this post?" msgstr "éšč—čæ™ę”åø–å­ļ¼Ÿ" @@ -1897,7 +1927,7 @@ msgstr "č¾“å…„ä½ ēš„åÆ†ē " msgid "Input your user handle" msgstr "č¾“å…„ä½ ēš„ē”Øęˆ·čÆ†åˆ«ē¬¦" -#: src/view/com/post-thread/PostThreadItem.tsx:224 +#: src/view/com/post-thread/PostThreadItem.tsx:226 msgid "Invalid or unsupported post record" msgstr "åø–å­č®°å½•ę— ę•ˆęˆ–äøå—ę”ÆęŒ" @@ -1999,7 +2029,7 @@ msgstr "äŗ†č§£čÆ¦ęƒ…" msgid "Learn more about this warning" msgstr "äŗ†č§£å…³äŗŽčæ™äøŖč­¦å‘Šēš„ę›“å¤ščÆ¦ęƒ…" -#: src/view/screens/Moderation.tsx:243 +#: src/view/screens/Moderation.tsx:262 msgid "Learn more about what is public on Bluesky." msgstr "äŗ†č§£ęœ‰å…³ Bluesky å…¬å¼€å†…å®¹ēš„ę›“å¤ščÆ¦ęƒ…ć€‚" @@ -2075,7 +2105,7 @@ msgstr "ē‚¹čµžä½ ēš„åø–å­" msgid "Likes" msgstr "ē‚¹čµž" -#: src/view/com/post-thread/PostThreadItem.tsx:181 +#: src/view/com/post-thread/PostThreadItem.tsx:183 msgid "Likes on this post" msgstr "ē‚¹čµžčæ™ę”åø–å­" @@ -2132,7 +2162,7 @@ msgstr "åŠ č½½ę›“å¤šåø–å­" msgid "Load new notifications" msgstr "åŠ č½½ę–°ēš„é€šēŸ„" -#: src/view/com/feeds/FeedPage.tsx:181 +#: src/view/com/feeds/FeedPage.tsx:115 #: src/view/screens/Profile.tsx:440 #: src/view/screens/ProfileFeed.tsx:495 #: src/view/screens/ProfileList.tsx:681 @@ -2158,7 +2188,7 @@ msgstr "ę—„åæ—" msgid "Log out" msgstr "登出" -#: src/view/screens/Moderation.tsx:136 +#: src/view/screens/Moderation.tsx:155 msgid "Logged-out visibility" msgstr "ęœŖē™»å½•ē”Øęˆ·åÆč§ę€§" @@ -2170,6 +2200,10 @@ msgstr "ē™»å½•ęœŖåˆ—å‡ŗēš„č“¦ęˆ·" msgid "Make sure this is where you intend to go!" msgstr "请甮认!" +#: src/components/dialogs/MutedWords.tsx:71 +msgid "Manage your muted words and tags" +msgstr "" + #: src/view/com/auth/create/Step2.tsx:118 msgid "May not be longer than 253 characters" msgstr "" @@ -2191,7 +2225,7 @@ msgid "Mentioned users" msgstr "ęåˆ°ēš„ē”Øęˆ·" #: src/view/com/util/ViewHeader.tsx:81 -#: src/view/screens/Search/Search.tsx:623 +#: src/view/screens/Search/Search.tsx:646 msgid "Menu" msgstr "čœå•" @@ -2200,7 +2234,7 @@ msgid "Message from server: {0}" msgstr "ę„č‡ŖęœåŠ”å™Øēš„äæ”ęÆļ¼š{0}" #: src/Navigation.tsx:115 -#: src/view/screens/Moderation.tsx:64 +#: src/view/screens/Moderation.tsx:66 #: src/view/screens/Settings/index.tsx:625 #: src/view/shell/desktop/LeftNav.tsx:397 #: src/view/shell/Drawer.tsx:511 @@ -2231,7 +2265,7 @@ msgstr "é™åˆ¶åˆ—č”Øå·²åˆ›å»ŗ" msgid "Moderation list updated" msgstr "é™åˆ¶åˆ—č”Øå·²ę›“ę–°" -#: src/view/screens/Moderation.tsx:95 +#: src/view/screens/Moderation.tsx:114 msgid "Moderation lists" msgstr "é™åˆ¶åˆ—č”Ø" @@ -2258,7 +2292,7 @@ msgstr "ę›“å¤šäæ”ęÆęµ" msgid "More options" msgstr "ę›“å¤šé€‰é”¹" -#: src/view/com/util/forms/PostDropdownBtn.tsx:299 +#: src/view/com/util/forms/PostDropdownBtn.tsx:315 msgid "More post options" msgstr "ę›“å¤šåø–å­é€‰é”¹" @@ -2270,6 +2304,14 @@ msgstr "ęœ€å¤šē‚¹čµžä¼˜å…ˆ" msgid "Must be at least 3 characters" msgstr "" +#: src/components/TagMenu/index.tsx:253 +msgid "Mute" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:91 +msgid "Mute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:327 msgid "Mute Account" msgstr "éšč—č“¦ęˆ·" @@ -2278,6 +2320,18 @@ msgstr "éšč—č“¦ęˆ·" msgid "Mute accounts" msgstr "éšč—č“¦ęˆ·" +#: src/components/TagMenu/index.tsx:211 +msgid "Mute all {tag} posts" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:131 +msgid "Mute in tags only" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:116 +msgid "Mute in text & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:491 msgid "Mute list" msgstr "éšč—åˆ—č”Ø" @@ -2290,15 +2344,27 @@ msgstr "éšč—čæ™äŗ›č“¦ęˆ·ļ¼Ÿ" msgid "Mute this List" msgstr "éšč—čæ™äøŖåˆ—č”Ø" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/dialogs/MutedWords.tsx:109 +msgid "Mute this word in post text and tags" +msgstr "" + +#: src/components/dialogs/MutedWords.tsx:124 +msgid "Mute this word in tags only" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Mute thread" msgstr "éšč—č®Øč®ŗäø²" +#: src/view/com/util/forms/PostDropdownBtn.tsx:216 +msgid "Mute words & tags" +msgstr "" + #: src/view/com/lists/ListCard.tsx:102 msgid "Muted" msgstr "å·²éšč—" -#: src/view/screens/Moderation.tsx:109 +#: src/view/screens/Moderation.tsx:128 msgid "Muted accounts" msgstr "å·²éšč—č“¦ęˆ·" @@ -2311,6 +2377,10 @@ msgstr "å·²éšč—č“¦ęˆ·" msgid "Muted accounts have their posts removed from your feed and from your notifications. Mutes are completely private." msgstr "å·²éšč—ēš„č“¦ęˆ·å°†äøä¼šåœØä½ ēš„é€šēŸ„ęˆ–ę—¶é—“ēŗæäø­ę˜¾ē¤ŗļ¼Œč¢«éšč—č“¦ęˆ·å°†äøä¼šę”¶åˆ°é€šēŸ„ć€‚" +#: src/view/screens/Moderation.tsx:100 +msgid "Muted words & tags" +msgstr "" + #: src/view/screens/ProfileList.tsx:277 msgid "Muting is private. Muted accounts can interact with you, but you will not see their posts or receive notifications from them." msgstr "č¢«éšč—ēš„č“¦ęˆ·å°†äøä¼šå¾—ēŸ„ä½ å·²å°†ä»–éšč—ļ¼Œå·²éšč—ēš„č“¦ęˆ·å°†äøä¼šåœØä½ ēš„é€šēŸ„ęˆ–ę—¶é—“ēŗæäø­ę˜¾ē¤ŗć€‚" @@ -2374,6 +2444,10 @@ msgstr "ę°øčæœäøä¼šå¤±åŽ»åÆ¹ä½ ēš„å…³ę³Øč€…å’Œę•°ę®ēš„č®æé—®ć€‚" msgid "Never lose access to your followers or data." msgstr "ę°øčæœäøä¼šå¤±åŽ»åÆ¹ä½ ēš„å…³ę³Øč€…ęˆ–ę•°ę®ēš„č®æé—®ć€‚" +#: src/components/dialogs/MutedWords.tsx:244 +msgid "Nevermind" +msgstr "" + #: src/view/screens/Lists.tsx:76 msgctxt "action" msgid "New" @@ -2395,7 +2469,7 @@ msgstr "新密码" msgid "New Password" msgstr "新密码" -#: src/view/com/feeds/FeedPage.tsx:192 +#: src/view/com/feeds/FeedPage.tsx:126 msgctxt "action" msgid "New post" msgstr "新帖子" @@ -2480,8 +2554,8 @@ msgid "No results found for \"{query}\"" msgstr "ęœŖę‰¾åˆ°\"{query}\"ēš„ē»“ęžœ" #: src/view/com/modals/ListAddRemoveUsers.tsx:127 -#: src/view/screens/Search/Search.tsx:280 -#: src/view/screens/Search/Search.tsx:308 +#: src/view/screens/Search/Search.tsx:281 +#: src/view/screens/Search/Search.tsx:309 msgid "No results found for {query}" msgstr "ęœŖę‰¾åˆ° {query} ēš„ē»“ęžœ" @@ -2507,7 +2581,7 @@ msgstr "ęœŖę‰¾åˆ°" msgid "Not right now" msgstr "äøę˜ÆēŽ°åœØ" -#: src/view/screens/Moderation.tsx:233 +#: src/view/screens/Moderation.tsx:252 msgid "Note: Bluesky is an open and public network. This setting only limits the visibility of your content on the Bluesky app and website, and other apps may not respect this setting. Your content may still be shown to logged-out users by other apps and websites." msgstr "ę³Øę„ļ¼šBluesky ę˜Æäø€äøŖå¼€ę”¾ēš„å…¬å…±ē½‘ē»œć€‚ę­¤č®¾ē½®é”¹ä»…é™åˆ¶ä½ ēš„å†…å®¹åœØ Bluesky åŗ”ē”Øå’Œē½‘ē«™äøŠēš„åÆč§ę€§ļ¼Œå…¶ä»–åŗ”ē”ØåÆčƒ½äøå°Šä»Žę­¤č®¾ē½®é”¹ļ¼Œä»åÆčƒ½ä¼šå‘ęœŖē™»å½•ēš„ē”Øęˆ·ę˜¾ē¤ŗä½ ēš„åŠØę€ć€‚" @@ -2545,7 +2619,7 @@ msgstr "ęœ€ę—§ēš„å›žå¤ä¼˜å…ˆ" msgid "Onboarding reset" msgstr "é‡ę–°å¼€å§‹å¼•åÆ¼ęµēØ‹" -#: src/view/com/composer/Composer.tsx:375 +#: src/view/com/composer/Composer.tsx:382 msgid "One or more images is missing alt text." msgstr "č‡³å°‘ęœ‰äø€å¼ å›¾ē‰‡ē¼ŗå¤±äŗ†ę›æä»£ę–‡å­—ć€‚" @@ -2562,8 +2636,12 @@ msgstr "Oops!" msgid "Open" msgstr "打开" -#: src/view/com/composer/Composer.tsx:470 -#: src/view/com/composer/Composer.tsx:471 +#: src/view/screens/Moderation.tsx:75 +msgid "Open content filtering settings" +msgstr "" + +#: src/view/com/composer/Composer.tsx:477 +#: src/view/com/composer/Composer.tsx:478 msgid "Open emoji picker" msgstr "打开 emoji 选择器" @@ -2571,6 +2649,10 @@ msgstr "打开 emoji 选择器" msgid "Open links with in-app browser" msgstr "åœØå†…ē½®ęµč§ˆå™Øäø­ę‰“å¼€é“¾ęŽ„" +#: src/view/screens/Moderation.tsx:92 +msgid "Open muted words settings" +msgstr "" + #: src/view/com/home/HomeHeaderLayoutMobile.tsx:49 msgid "Open navigation" msgstr "ę‰“å¼€åÆ¼čˆŖ" @@ -2647,6 +2729,7 @@ msgstr "ę‰“å¼€é™åˆ¶č®¾ē½®" msgid "Opens password reset form" msgstr "ę‰“å¼€åÆ†ē é‡ē½®ē”³čÆ·" +#: src/view/com/home/HomeHeaderLayout.web.tsx:60 #: src/view/screens/Feeds.tsx:356 msgid "Opens screen to edit Saved Feeds" msgstr "ę‰“å¼€ē”ØäŗŽē¼–č¾‘å·²äæå­˜äæ”ęÆęµēš„ē•Œé¢" @@ -2822,7 +2905,7 @@ msgstr "čÆ·å‘ŠčÆ‰ęˆ‘ä»¬ä½ č®¤äøŗę­¤å†…å®¹č­¦å‘Šč¢«é”™čÆÆč®¾ē½®ēš„åŽŸå› ļ¼" msgid "Please Verify Your Email" msgstr "čÆ·éŖŒčÆä½ ēš„ē”µå­é‚®ē®±" -#: src/view/com/composer/Composer.tsx:215 +#: src/view/com/composer/Composer.tsx:222 msgid "Please wait for your link card to finish loading" msgstr "čÆ·ē­‰å¾…ä½ ēš„é“¾ęŽ„å”ē‰‡åŠ č½½å®Œęˆ" @@ -2834,8 +2917,8 @@ msgstr "政治" msgid "Porn" msgstr "č‰²ęƒ…å†…å®¹" -#: src/view/com/composer/Composer.tsx:350 -#: src/view/com/composer/Composer.tsx:358 +#: src/view/com/composer/Composer.tsx:357 +#: src/view/com/composer/Composer.tsx:365 msgctxt "action" msgid "Post" msgstr "å‘åøƒ" @@ -2845,7 +2928,7 @@ msgctxt "description" msgid "Post" msgstr "å‘åøƒ" -#: src/view/com/post-thread/PostThreadItem.tsx:173 +#: src/view/com/post-thread/PostThreadItem.tsx:175 msgid "Post by {0}" msgstr "å‘åøƒč€… {0}" @@ -2855,11 +2938,11 @@ msgstr "å‘åøƒč€… {0}" msgid "Post by @{0}" msgstr "å‘åøƒč€… @{0}" -#: src/view/com/util/forms/PostDropdownBtn.tsx:88 +#: src/view/com/util/forms/PostDropdownBtn.tsx:90 msgid "Post deleted" msgstr "å·²åˆ é™¤åø–å­" -#: src/view/com/post-thread/PostThread.tsx:461 +#: src/view/com/post-thread/PostThread.tsx:462 msgid "Post hidden" msgstr "å·²éšč—åø–å­" @@ -2871,14 +2954,22 @@ msgstr "帖子语言" msgid "Post Languages" msgstr "帖子语言" -#: src/view/com/post-thread/PostThread.tsx:513 +#: src/view/com/post-thread/PostThread.tsx:514 msgid "Post not found" msgstr "ę— ę³•ę‰¾åˆ°åø–å­" +#: src/components/TagMenu/index.tsx:257 +msgid "posts" +msgstr "" + #: src/view/screens/Profile.tsx:180 msgid "Posts" msgstr "帖子" +#: src/components/dialogs/MutedWords.tsx:77 +msgid "Posts can be muted based on their text, their tags, or both." +msgstr "" + #: src/view/com/posts/FeedErrorMessage.tsx:64 msgid "Posts hidden" msgstr "å·²éšč—åø–å­" @@ -2943,11 +3034,11 @@ msgstr "å…¬å¼€äø”åÆå…±äŗ«ēš„ę‰¹é‡éšč—ęˆ–å±č”½åˆ—č”Øć€‚" msgid "Public, shareable lists which can drive feeds." msgstr "å…¬å¼€äø”åÆå…±äŗ«ēš„åˆ—č”Øļ¼ŒåÆä½œäøŗäæ”ęÆęµä½æē”Øć€‚" -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish post" msgstr "å‘åøƒåø–å­" -#: src/view/com/composer/Composer.tsx:335 +#: src/view/com/composer/Composer.tsx:342 msgid "Publish reply" msgstr "å‘åøƒå›žå¤" @@ -2981,6 +3072,7 @@ msgstr "ęŽØčäæ”ęÆęµ" msgid "Recommended Users" msgstr "ęŽØčēš„ē”Øęˆ·" +#: src/components/dialogs/MutedWords.tsx:249 #: src/view/com/modals/ListAddRemoveUsers.tsx:264 #: src/view/com/modals/SelfLabel.tsx:83 #: src/view/com/modals/UserAddRemoveLists.tsx:219 @@ -3018,6 +3110,10 @@ msgstr "åˆ é™¤å›¾ē‰‡" msgid "Remove image preview" msgstr "åˆ é™¤å›¾ē‰‡é¢„č§ˆ" +#: src/components/dialogs/MutedWords.tsx:294 +msgid "Remove mute word from your list" +msgstr "" + #: src/view/com/modals/Repost.tsx:47 msgid "Remove repost" msgstr "åˆ é™¤č½¬å‘" @@ -3052,7 +3148,7 @@ msgstr "回复" msgid "Replies to this thread are disabled" msgstr "åÆ¹ę­¤č®Øč®ŗäø²ēš„å›žå¤å·²č¢«ē¦ē”Ø" -#: src/view/com/composer/Composer.tsx:348 +#: src/view/com/composer/Composer.tsx:355 msgctxt "action" msgid "Reply" msgstr "回复" @@ -3062,7 +3158,7 @@ msgid "Reply Filters" msgstr "å›žå¤čæ‡ę»¤å™Ø" #: src/view/com/post/Post.tsx:167 -#: src/view/com/posts/FeedItem.tsx:285 +#: src/view/com/posts/FeedItem.tsx:287 msgctxt "description" msgid "Reply to <0/>" msgstr "回复 <0/>" @@ -3084,7 +3180,7 @@ msgid "Report List" msgstr "äø¾ęŠ„åˆ—č”Ø" #: src/view/com/modals/report/SendReportButton.tsx:37 -#: src/view/com/util/forms/PostDropdownBtn.tsx:239 +#: src/view/com/util/forms/PostDropdownBtn.tsx:255 msgid "Report post" msgstr "äø¾ęŠ„åø–å­" @@ -3109,11 +3205,11 @@ msgstr "č½¬å‘ęˆ–å¼•ē”Øåø–å­" msgid "Reposted By" msgstr "č½¬å‘" -#: src/view/com/posts/FeedItem.tsx:205 +#: src/view/com/posts/FeedItem.tsx:207 msgid "Reposted by {0}" msgstr "ē”± {0} č½¬å‘" -#: src/view/com/posts/FeedItem.tsx:222 +#: src/view/com/posts/FeedItem.tsx:224 msgid "Reposted by <0/>" msgstr "ē”± <0/> č½¬å‘" @@ -3121,7 +3217,7 @@ msgstr "ē”± <0/> č½¬å‘" msgid "reposted your post" msgstr "č½¬å‘ä½ ēš„åø–å­" -#: src/view/com/post-thread/PostThreadItem.tsx:186 +#: src/view/com/post-thread/PostThreadItem.tsx:188 msgid "Reposts of this post" msgstr "č½¬å‘čæ™ę”åø–å­" @@ -3272,9 +3368,9 @@ msgstr "滚动到锶部" #: src/view/com/modals/ListAddRemoveUsers.tsx:75 #: src/view/com/util/forms/SearchInput.tsx:67 #: src/view/com/util/forms/SearchInput.tsx:79 -#: src/view/screens/Search/Search.tsx:418 -#: src/view/screens/Search/Search.tsx:645 -#: src/view/screens/Search/Search.tsx:663 +#: src/view/screens/Search/Search.tsx:419 +#: src/view/screens/Search/Search.tsx:668 +#: src/view/screens/Search/Search.tsx:686 #: src/view/shell/bottom-bar/BottomBar.tsx:159 #: src/view/shell/desktop/LeftNav.tsx:324 #: src/view/shell/desktop/Search.tsx:214 @@ -3284,11 +3380,19 @@ msgstr "滚动到锶部" msgid "Search" msgstr "搜瓢" -#: src/view/screens/Search/Search.tsx:712 +#: src/view/screens/Search/Search.tsx:735 #: src/view/shell/desktop/Search.tsx:255 msgid "Search for \"{query}\"" msgstr "搜瓢 \"{query}\"" +#: src/components/TagMenu/index.tsx:145 +msgid "Search for all posts by @{authorHandle} with tag {tag}" +msgstr "" + +#: src/components/TagMenu/index.tsx:90 +msgid "Search for all posts with tag {tag}" +msgstr "" + #: src/view/com/auth/LoggedOut.tsx:104 #: src/view/com/auth/LoggedOut.tsx:105 #: src/view/com/modals/ListAddRemoveUsers.tsx:70 @@ -3299,6 +3403,22 @@ msgstr "ęœē“¢ē”Øęˆ·" msgid "Security Step Required" msgstr "ę‰€éœ€ēš„å®‰å…Øę­„éŖ¤" +#: src/components/TagMenu/index.web.tsx:50 +msgid "See {truncatedTag} posts" +msgstr "" + +#: src/components/TagMenu/index.web.tsx:67 +msgid "See {truncatedTag} posts by user" +msgstr "" + +#: src/components/TagMenu/index.tsx:128 +msgid "See <0>{tag} posts" +msgstr "" + +#: src/components/TagMenu/index.tsx:189 +msgid "See <0>{tag} posts by this user" +msgstr "" + #: src/view/screens/SavedFeeds.tsx:163 msgid "See this guide" msgstr "ęŸ„ēœ‹ęŒ‡å—" @@ -3504,7 +3624,7 @@ msgid "Share" msgstr "åˆ†äŗ«" #: src/view/com/profile/ProfileHeader.tsx:295 -#: src/view/com/util/forms/PostDropdownBtn.tsx:182 +#: src/view/com/util/forms/PostDropdownBtn.tsx:184 #: src/view/screens/ProfileList.tsx:418 msgid "Share" msgstr "åˆ†äŗ«" @@ -3537,9 +3657,9 @@ msgstr "ę˜¾ē¤ŗę„č‡Ŗ {0} ēš„åµŒå…„å†…å®¹" msgid "Show follows similar to {0}" msgstr "ę˜¾ē¤ŗē±»ä¼¼äŗŽ {0} ēš„å…³ę³Øč€…" -#: src/view/com/post-thread/PostThreadItem.tsx:532 -#: src/view/com/post/Post.tsx:196 -#: src/view/com/posts/FeedItem.tsx:359 +#: src/view/com/post-thread/PostThreadItem.tsx:538 +#: src/view/com/post/Post.tsx:198 +#: src/view/com/posts/FeedItem.tsx:363 msgid "Show More" msgstr "ę˜¾ē¤ŗę›“å¤š" @@ -3707,7 +3827,7 @@ msgstr "ēØ‹åŗå¼€å‘" msgid "Something went wrong. Check your email and try again." msgstr "å‡ŗäŗ†ē‚¹é—®é¢˜ļ¼ŒčÆ·ę£€ęŸ„ä½ ēš„ē”µå­é‚®ē®±å¹¶é‡čÆ•ć€‚" -#: src/App.native.tsx:61 +#: src/App.native.tsx:63 msgid "Sorry! Your session expired. Please log in again." msgstr "å¾ˆęŠ±ę­‰ļ¼Œä½ ēš„ä¼ščÆå·²čæ‡ęœŸļ¼ŒčÆ·é‡ę–°ē™»å½•ć€‚" @@ -3765,7 +3885,7 @@ msgstr "č®¢é˜… {0} 俔息流" msgid "Subscribe to this list" msgstr "č®¢é˜…čæ™äøŖåˆ—č”Ø" -#: src/view/screens/Search/Search.tsx:373 +#: src/view/screens/Search/Search.tsx:374 msgid "Suggested Follows" msgstr "ęŽØčēš„å…³ę³Øč€…" @@ -3809,6 +3929,14 @@ msgstr "系统" msgid "System log" msgstr "ē³»ē»Ÿę—„åæ—" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "tag" +msgstr "" + +#: src/components/TagMenu/index.tsx:74 +msgid "Tag menu: {tag}" +msgstr "" + #: src/view/com/modals/crop-image/CropImage.web.tsx:112 msgid "Tall" msgstr "高" @@ -3832,6 +3960,10 @@ msgstr "ę”ę¬¾" msgid "Terms of Service" msgstr "ęœåŠ”ę”ę¬¾" +#: src/components/dialogs/MutedWords.tsx:288 +msgid "text" +msgstr "" + #: src/view/com/modals/AppealLabel.tsx:70 #: src/view/com/modals/report/InputIssueDetails.tsx:51 msgid "Text input field" @@ -3857,7 +3989,7 @@ msgstr "ē‰ˆęƒč®øåÆå·²čæē§»č‡³ <0/>" msgid "The following steps will help customize your Bluesky experience." msgstr "ä»„äø‹ę­„éŖ¤å°†åø®åŠ©å®šåˆ¶ä½ ēš„ Bluesky ä½“éŖŒć€‚" -#: src/view/com/post-thread/PostThread.tsx:516 +#: src/view/com/post-thread/PostThread.tsx:517 msgid "The post may have been deleted." msgstr "ę­¤åø–å­ä¼¼ä¹Žå·²č¢«åˆ é™¤ć€‚" @@ -4023,7 +4155,7 @@ msgstr "ę­¤åˆ—č”Øäøŗē©ŗļ¼" msgid "This name is already in use" msgstr "čÆ„åē§°å·²č¢«ä½æē”Ø" -#: src/view/com/post-thread/PostThreadItem.tsx:123 +#: src/view/com/post-thread/PostThreadItem.tsx:125 msgid "This post has been deleted." msgstr "ę­¤åø–å·²č¢«åˆ é™¤ć€‚" @@ -4047,7 +4179,11 @@ msgstr "ę­¤ē”Øęˆ·åŒ…å«åœØä½ å·²éšč—ēš„ <0/> åˆ—č”Øäø­ć€‚" msgid "This warning is only available for posts with media attached." msgstr "ę­¤č­¦å‘Šä»…é€‚ē”ØäŗŽé™„åø¦åŖ’ä½“ēš„åø–å­ć€‚" -#: src/view/com/util/forms/PostDropdownBtn.tsx:221 +#: src/components/dialogs/MutedWords.tsx:236 +msgid "This will delete {0} from your muted words. You can always add it back later." +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:237 msgid "This will hide this post from your feeds." msgstr "čæ™å°†åœØä½ ēš„äæ”ęÆęµäø­éšč—ę­¤åø–å­ć€‚" @@ -4064,6 +4200,10 @@ msgstr "åˆ†å±‚ęØ”å¼" msgid "Threads Preferences" msgstr "讨论串首选锹" +#: src/components/dialogs/MutedWords.tsx:95 +msgid "Toggle between muted word options." +msgstr "" + #: src/view/com/util/forms/DropdownButton.tsx:246 msgid "Toggle dropdown" msgstr "åˆ‡ę¢äø‹ę‹‰čœå•" @@ -4072,9 +4212,9 @@ msgstr "åˆ‡ę¢äø‹ę‹‰čœå•" msgid "Transformations" msgstr "č½¬ę¢" -#: src/view/com/post-thread/PostThreadItem.tsx:679 -#: src/view/com/post-thread/PostThreadItem.tsx:681 -#: src/view/com/util/forms/PostDropdownBtn.tsx:154 +#: src/view/com/post-thread/PostThreadItem.tsx:685 +#: src/view/com/post-thread/PostThreadItem.tsx:687 +#: src/view/com/util/forms/PostDropdownBtn.tsx:156 msgid "Translate" msgstr "翻译" @@ -4139,15 +4279,24 @@ msgstr "å¾ˆé—ę†¾ļ¼Œä½ äøē¬¦åˆåˆ›å»ŗč“¦ęˆ·ēš„č¦ę±‚ć€‚" msgid "Unlike" msgstr "å–ę¶ˆå–œę¬¢" +#: src/components/TagMenu/index.tsx:253 #: src/view/screens/ProfileList.tsx:597 msgid "Unmute" msgstr "å–ę¶ˆéšč—" +#: src/components/TagMenu/index.web.tsx:90 +msgid "Unmute {truncatedTag}" +msgstr "" + #: src/view/com/profile/ProfileHeader.tsx:326 msgid "Unmute Account" msgstr "å–ę¶ˆéšč—č“¦ęˆ·" -#: src/view/com/util/forms/PostDropdownBtn.tsx:200 +#: src/components/TagMenu/index.tsx:210 +msgid "Unmute all {tag} posts" +msgstr "" + +#: src/view/com/util/forms/PostDropdownBtn.tsx:202 msgid "Unmute thread" msgstr "å–ę¶ˆéšč—č®Øč®ŗäø²" @@ -4344,6 +4493,10 @@ msgstr "ęˆ‘ä»¬åøŒęœ›ä½ åœØę­¤åŗ¦čæ‡ę„‰åæ«ēš„ę—¶å…‰ć€‚čÆ·č®°ä½ļ¼ŒBluesky 是:" msgid "We ran out of posts from your follows. Here's the latest from <0/>." msgstr "ęˆ‘ä»¬å·²ē»ēœ‹å®Œäŗ†ä½ å…³ę³Øēš„åø–å­ć€‚čæ™ę˜Æę„č‡Ŗ <0/> ēš„ęœ€ę–°ę¶ˆęÆć€‚" +#: src/components/dialogs/MutedWords.tsx:161 +msgid "We recommend avoiding common words that appear in many posts, since it can result in no posts being shown." +msgstr "" + #: src/screens/Onboarding/StepAlgoFeeds/index.tsx:124 msgid "We recommend our \"Discover\" feed:" msgstr "ęˆ‘ä»¬ęŽØčęˆ‘ä»¬ēš„ \"Discover\" 俔息流:" @@ -4372,7 +4525,11 @@ msgstr "ęˆ‘ä»¬éžåøøé«˜å…“ä½ åŠ å…„ęˆ‘ä»¬ļ¼" msgid "We're sorry, but we were unable to resolve this list. If this persists, please contact the list creator, @{handleOrDid}." msgstr "å¾ˆęŠ±ę­‰ļ¼Œęˆ‘ä»¬ę— ę³•č§£ęžę­¤åˆ—č”Øć€‚å¦‚ęžœé—®é¢˜ęŒē»­å‘ē”Ÿļ¼ŒčÆ·č”ē³»åˆ—č”Øåˆ›å»ŗč€…ļ¼Œ@{handleOrDid}怂" -#: src/view/screens/Search/Search.tsx:253 +#: src/components/dialogs/MutedWords.tsx:182 +msgid "We're sorry, but we weren't able to load your muted words at this time. Please try again." +msgstr "" + +#: src/view/screens/Search/Search.tsx:254 msgid "We're sorry, but your search could not be completed. Please try again in a few minutes." msgstr "å¾ˆęŠ±ę­‰ļ¼Œę— ę³•å®Œęˆä½ ēš„ęœē“¢ć€‚čÆ·ēØåŽå†čÆ•ć€‚" @@ -4393,7 +4550,7 @@ msgid "What is the issue with this {collectionName}?" msgstr "这个 {collectionName} ęœ‰ä»€ä¹ˆé—®é¢˜ļ¼Ÿ" #: src/view/com/auth/SplashScreen.tsx:59 -#: src/view/com/composer/Composer.tsx:279 +#: src/view/com/composer/Composer.tsx:286 msgid "What's up?" msgstr "å‘ē”Ÿäŗ†ä»€ä¹ˆę–°é²œäŗ‹ļ¼Ÿ" @@ -4414,11 +4571,11 @@ msgstr "č°åÆä»„å›žå¤" msgid "Wide" msgstr "宽" -#: src/view/com/composer/Composer.tsx:415 +#: src/view/com/composer/Composer.tsx:422 msgid "Write post" msgstr "撰写帖子" -#: src/view/com/composer/Composer.tsx:278 +#: src/view/com/composer/Composer.tsx:285 #: src/view/com/composer/Prompt.tsx:33 msgid "Write your reply" msgstr "ę’°å†™ä½ ēš„å›žå¤" @@ -4475,7 +4632,7 @@ msgstr "ä½ ē›®å‰čæ˜ę²”ęœ‰ä»»ä½•äæå­˜ēš„äæ”ęÆęµļ¼" msgid "You don't have any saved feeds." msgstr "ä½ ē›®å‰čæ˜ę²”ęœ‰ä»»ä½•äæå­˜ēš„äæ”ęÆęµć€‚" -#: src/view/com/post-thread/PostThread.tsx:464 +#: src/view/com/post-thread/PostThread.tsx:465 msgid "You have blocked the author or you have been blocked by the author." msgstr "ä½ å·²å±č”½čÆ„ä½œč€…ļ¼Œęˆ–ä½ å·²č¢«čÆ„ä½œč€…å±č”½ć€‚" @@ -4515,6 +4672,10 @@ msgstr "ä½ å°šęœŖåˆ›å»ŗä»»ä½• App äø“ē”ØåÆ†ē ļ¼ŒåÆä»„é€ščæ‡ē‚¹å‡»äø‹é¢ēš„ęŒ‰ msgid "You have not muted any accounts yet. To mute an account, go to their profile and selected \"Mute account\" from the menu on their account." msgstr "ä½ čæ˜ę²”ęœ‰éšč—ä»»ä½•č“¦å·ć€‚č¦éšč—č“¦å·ļ¼ŒčÆ·č½¬åˆ°å…¶äøŖäŗŗčµ„ę–™å¹¶åœØå…¶č“¦å·äøŠēš„čœå•äø­é€‰ę‹© \"éšč—č“¦å·\"怂" +#: src/components/dialogs/MutedWords.tsx:202 +msgid "You haven't muted any words or tags yet" +msgstr "" + #: src/view/com/modals/ContentFilteringSettings.tsx:175 msgid "You must be 18 or older to enable adult content." msgstr "你必锻幓滔18å²åŠä»„äøŠę‰čƒ½åÆē”Øęˆäŗŗå†…å®¹ć€‚" @@ -4523,11 +4684,11 @@ msgstr "你必锻幓滔18å²åŠä»„äøŠę‰čƒ½åÆē”Øęˆäŗŗå†…å®¹ć€‚" msgid "You must be 18 years or older to enable adult content" msgstr "你必锻幓滔18å²åŠä»„äøŠę‰čƒ½åÆē”Øęˆäŗŗå†…å®¹" -#: src/view/com/util/forms/PostDropdownBtn.tsx:127 +#: src/view/com/util/forms/PostDropdownBtn.tsx:129 msgid "You will no longer receive notifications for this thread" msgstr "ä½ å°†äøå†ę”¶åˆ°čæ™ę”č®Øč®ŗäø²ēš„é€šēŸ„" -#: src/view/com/util/forms/PostDropdownBtn.tsx:130 +#: src/view/com/util/forms/PostDropdownBtn.tsx:132 msgid "You will now receive notifications for this thread" msgstr "ä½ å°†ę”¶åˆ°čæ™ę”č®Øč®ŗäø²ēš„é€šēŸ„" @@ -4613,11 +4774,15 @@ msgstr "ä½ ēš„å®Œę•“ē”Øęˆ·čÆ†åˆ«ē¬¦å°†äæ®ę”¹äøŗ <0>@{0}" #~ msgid "Your invite codes are hidden when logged in using an App Password" #~ msgstr "åœØä½æē”Ø App äø“ē”ØåÆ†ē ē™»å½•ę—¶ļ¼Œä½ ēš„é‚€čÆ·ē å°†č¢«éšč—" +#: src/components/dialogs/MutedWords.tsx:173 +msgid "Your muted words" +msgstr "" + #: src/view/com/modals/ChangePassword.tsx:155 msgid "Your password has been changed successfully!" msgstr "ä½ ēš„åÆ†ē å·²ę›“ę”¹ęˆåŠŸļ¼" -#: src/view/com/composer/Composer.tsx:267 +#: src/view/com/composer/Composer.tsx:274 msgid "Your post has been published" msgstr "ä½ ēš„åø–å­å·²å‘é€" @@ -4632,7 +4797,7 @@ msgstr "ä½ ēš„åø–å­ć€ē‚¹čµžå’Œå±č”½ę˜Æå…¬å¼€åÆč§ēš„ļ¼Œč€Œéšč—äøåÆč§ć€‚ msgid "Your profile" msgstr "ä½ ēš„äøŖäŗŗčµ„ę–™" -#: src/view/com/composer/Composer.tsx:266 +#: src/view/com/composer/Composer.tsx:273 msgid "Your reply has been published" msgstr "ä½ ēš„å›žå¤å·²å‘é€" diff --git a/src/platform/markBundleStartTime.web.ts b/src/platform/markBundleStartTime.web.ts new file mode 100644 index 0000000000..cd64c9f1c3 --- /dev/null +++ b/src/platform/markBundleStartTime.web.ts @@ -0,0 +1,2 @@ +// @ts-ignore Web-only. On RN, this is set by Metro. +window.__BUNDLE_START_TIME__ = performance.now() diff --git a/src/routes.ts b/src/routes.ts index 62732985ce..23ec880de2 100644 --- a/src/routes.ts +++ b/src/routes.ts @@ -34,4 +34,5 @@ export const router = new Router({ TermsOfService: '/support/tos', CommunityGuidelines: '/support/community-guidelines', CopyrightPolicy: '/support/copyright', + Hashtag: '/hashtag/:tag', }) diff --git a/src/screens/Hashtag.tsx b/src/screens/Hashtag.tsx new file mode 100644 index 0000000000..776cc585e3 --- /dev/null +++ b/src/screens/Hashtag.tsx @@ -0,0 +1,165 @@ +import React from 'react' +import {ListRenderItemInfo, Pressable} from 'react-native' +import {useFocusEffect} from '@react-navigation/native' +import {useSetMinimalShellMode} from 'state/shell' +import {ViewHeader} from 'view/com/util/ViewHeader' +import {NativeStackScreenProps} from '@react-navigation/native-stack' +import {CommonNavigatorParams} from 'lib/routes/types' +import {useSearchPostsQuery} from 'state/queries/search-posts' +import {Post} from 'view/com/post/Post' +import {PostView} from '@atproto/api/dist/client/types/app/bsky/feed/defs' +import {enforceLen} from 'lib/strings/helpers' +import { + ListFooter, + ListHeaderDesktop, + ListMaybePlaceholder, +} from '#/components/Lists' +import {List} from 'view/com/util/List' +import {msg} from '@lingui/macro' +import {useLingui} from '@lingui/react' +import {sanitizeHandle} from 'lib/strings/handles' +import {ArrowOutOfBox_Stroke2_Corner0_Rounded} from '#/components/icons/ArrowOutOfBox' +import {shareUrl} from 'lib/sharing' +import {HITSLOP_10} from 'lib/constants' +import {isNative} from 'platform/detection' +import {useInitialNumToRender} from 'lib/hooks/useInitialNumToRender' + +const renderItem = ({item}: ListRenderItemInfo) => { + return +} + +const keyExtractor = (item: PostView, index: number) => { + return `${item.uri}-${index}` +} + +export default function HashtagScreen({ + route, +}: NativeStackScreenProps) { + const {tag, author} = route.params + const setMinimalShellMode = useSetMinimalShellMode() + const {_} = useLingui() + const initialNumToRender = useInitialNumToRender() + const [isPTR, setIsPTR] = React.useState(false) + + const fullTag = React.useMemo(() => { + return `#${decodeURIComponent(tag)}` + }, [tag]) + + const queryParam = React.useMemo(() => { + if (!author) return fullTag + return `${fullTag} from:${sanitizeHandle(author)}` + }, [fullTag, author]) + + const headerTitle = React.useMemo(() => { + return enforceLen(fullTag.toLowerCase(), 24, true, 'middle') + }, [fullTag]) + + const sanitizedAuthor = React.useMemo(() => { + if (!author) return + return sanitizeHandle(author) + }, [author]) + + const { + data, + isFetching, + isLoading, + isRefetching, + isError, + error, + refetch, + fetchNextPage, + hasNextPage, + } = useSearchPostsQuery({query: queryParam}) + + const posts = React.useMemo(() => { + return data?.pages.flatMap(page => page.posts) || [] + }, [data]) + + useFocusEffect( + React.useCallback(() => { + setMinimalShellMode(false) + }, [setMinimalShellMode]), + ) + + const onShare = React.useCallback(() => { + const url = new URL('https://bsky.app') + url.pathname = `/hashtag/${decodeURIComponent(tag)}` + if (author) { + url.searchParams.set('author', author) + } + shareUrl(url.toString()) + }, [tag, author]) + + const onRefresh = React.useCallback(async () => { + setIsPTR(true) + await refetch() + setIsPTR(false) + }, [refetch]) + + const onEndReached = React.useCallback(() => { + if (isFetching || !hasNextPage || error) return + fetchNextPage() + }, [isFetching, hasNextPage, error, fetchNextPage]) + + return ( + <> + ( + + + + ) + : undefined + } + /> + + {!isLoading && posts.length > 0 && ( + + data={posts} + renderItem={renderItem} + keyExtractor={keyExtractor} + refreshing={isPTR} + onRefresh={onRefresh} + onEndReached={onEndReached} + onEndReachedThreshold={4} + // @ts-ignore web only -prf + desktopFixedHeight + ListHeaderComponent={ + + } + ListFooterComponent={ + + } + initialNumToRender={initialNumToRender} + windowSize={11} + /> + )} + + ) +} diff --git a/src/screens/Onboarding/StepModeration/AdultContentEnabledPref.tsx b/src/screens/Onboarding/StepModeration/AdultContentEnabledPref.tsx index d5e730ffaf..0bff534362 100644 --- a/src/screens/Onboarding/StepModeration/AdultContentEnabledPref.tsx +++ b/src/screens/Onboarding/StepModeration/AdultContentEnabledPref.tsx @@ -119,7 +119,7 @@ export function AdultContentEnabledPref({ - OK + prompt.close()}>OK diff --git a/src/screens/Onboarding/state.ts b/src/screens/Onboarding/state.ts index bd8205ca2d..969edbdd24 100644 --- a/src/screens/Onboarding/state.ts +++ b/src/screens/Onboarding/state.ts @@ -232,7 +232,7 @@ export function reducer( }) if (s.activeStep !== state.activeStep) { - logger.info(`onboarding: step changed`, {activeStep: state.activeStep}) + logger.debug(`onboarding: step changed`, {activeStep: state.activeStep}) } return state diff --git a/src/state/dialogs/index.tsx b/src/state/dialogs/index.tsx index ae762bd97e..90aaca4f8b 100644 --- a/src/state/dialogs/index.tsx +++ b/src/state/dialogs/index.tsx @@ -1,21 +1,32 @@ import React from 'react' -import {DialogControlProps} from '#/components/Dialog' +import {DialogControlRefProps} from '#/components/Dialog' import {Provider as GlobalDialogsProvider} from '#/components/dialogs/Context' const DialogContext = React.createContext<{ + /** + * The currently active `useDialogControl` hooks. + */ activeDialogs: React.MutableRefObject< - Map> + Map> > + /** + * The currently open dialogs, referenced by their IDs, generated from + * `useId`. + */ + openDialogs: string[] }>({ activeDialogs: { current: new Map(), }, + openDialogs: [], }) const DialogControlContext = React.createContext<{ - closeAllDialogs(): void + closeAllDialogs(): boolean + setDialogIsOpen(id: string, isOpen: boolean): void }>({ - closeAllDialogs: () => {}, + closeAllDialogs: () => false, + setDialogIsOpen: () => {}, }) export function useDialogStateContext() { @@ -28,13 +39,34 @@ export function useDialogStateControlContext() { export function Provider({children}: React.PropsWithChildren<{}>) { const activeDialogs = React.useRef< - Map> + Map> >(new Map()) + const [openDialogs, setOpenDialogs] = React.useState([]) + const closeAllDialogs = React.useCallback(() => { activeDialogs.current.forEach(dialog => dialog.current.close()) - }, []) - const context = React.useMemo(() => ({activeDialogs}), []) - const controls = React.useMemo(() => ({closeAllDialogs}), [closeAllDialogs]) + return openDialogs.length > 0 + }, [openDialogs]) + + const setDialogIsOpen = React.useCallback( + (id: string, isOpen: boolean) => { + setOpenDialogs(prev => { + const filtered = prev.filter(dialogId => dialogId !== id) as string[] + return isOpen ? [...filtered, id] : filtered + }) + }, + [setOpenDialogs], + ) + + const context = React.useMemo( + () => ({activeDialogs, openDialogs}), + [openDialogs], + ) + const controls = React.useMemo( + () => ({closeAllDialogs, setDialogIsOpen}), + [closeAllDialogs, setDialogIsOpen], + ) + return ( diff --git a/src/state/models/media/gallery.ts b/src/state/models/media/gallery.ts index 04023bf820..9c8c13010d 100644 --- a/src/state/models/media/gallery.ts +++ b/src/state/models/media/gallery.ts @@ -4,11 +4,21 @@ import {Image as RNImage} from 'react-native-image-crop-picker' import {openPicker} from 'lib/media/picker' import {getImageDim} from 'lib/media/manip' +interface InitialImageUri { + uri: string + width: number + height: number +} + export class GalleryModel { images: ImageModel[] = [] - constructor() { + constructor(uris?: {uri: string; width: number; height: number}[]) { makeAutoObservable(this) + + if (uris) { + this.addFromUris(uris) + } } get isEmpty() { @@ -23,7 +33,7 @@ export class GalleryModel { return this.images.some(image => image.altText.trim() === '') } - async add(image_: Omit) { + *add(image_: Omit) { if (this.size >= 4) { return } @@ -86,4 +96,15 @@ export class GalleryModel { }), ) } + + async addFromUris(uris: InitialImageUri[]) { + for (const uriObj of uris) { + this.add({ + mime: 'image/jpeg', + height: uriObj.height, + width: uriObj.width, + path: uriObj.uri, + }) + } + } } diff --git a/src/state/persisted/__tests__/migrate.test.ts b/src/state/persisted/__tests__/migrate.test.ts index e4b55d5da6..97767e2732 100644 --- a/src/state/persisted/__tests__/migrate.test.ts +++ b/src/state/persisted/__tests__/migrate.test.ts @@ -26,7 +26,7 @@ test('migrate: fresh install', async () => { expect(AsyncStorage.getItem).toHaveBeenCalledWith('root') expect(read).toHaveBeenCalledTimes(1) - expect(logger.info).toHaveBeenCalledWith( + expect(logger.debug).toHaveBeenCalledWith( 'persisted state: no migration needed', ) }) @@ -38,7 +38,7 @@ test('migrate: fresh install, existing new storage', async () => { expect(AsyncStorage.getItem).toHaveBeenCalledWith('root') expect(read).toHaveBeenCalledTimes(1) - expect(logger.info).toHaveBeenCalledWith( + expect(logger.debug).toHaveBeenCalledWith( 'persisted state: no migration needed', ) }) @@ -68,7 +68,7 @@ test('migrate: has legacy data', async () => { await migrate() expect(write).toHaveBeenCalledWith(transform(fixtures.LEGACY_DATA_DUMP)) - expect(logger.info).toHaveBeenCalledWith( + expect(logger.debug).toHaveBeenCalledWith( 'persisted state: migrated legacy storage', ) }) diff --git a/src/state/persisted/index.ts b/src/state/persisted/index.ts index 2f34c2dbff..f57172d2fe 100644 --- a/src/state/persisted/index.ts +++ b/src/state/persisted/index.ts @@ -19,7 +19,7 @@ const _emitter = new EventEmitter() * the Provider. */ export async function init() { - logger.info('persisted state: initializing') + logger.debug('persisted state: initializing') broadcast.onmessage = onBroadcastMessage @@ -27,11 +27,11 @@ export async function init() { await migrate() // migrate old store const stored = await store.read() // check for new store if (!stored) { - logger.info('persisted state: initializing default storage') + logger.debug('persisted state: initializing default storage') await store.write(defaults) // opt: init new store } _state = stored || defaults // return new store - logger.log('persisted state: initialized') + logger.debug('persisted state: initialized') } catch (e) { logger.error('persisted state: failed to load root state from storage', { message: e, diff --git a/src/state/persisted/legacy.ts b/src/state/persisted/legacy.ts index cce080c84c..fd94a96a24 100644 --- a/src/state/persisted/legacy.ts +++ b/src/state/persisted/legacy.ts @@ -121,7 +121,7 @@ export function transform(legacy: Partial): Schema { * local storage AND old storage exists. */ export async function migrate() { - logger.info('persisted state: check need to migrate') + logger.debug('persisted state: check need to migrate') try { const rawLegacyData = await AsyncStorage.getItem( @@ -131,7 +131,7 @@ export async function migrate() { const alreadyMigrated = Boolean(newData) if (!alreadyMigrated && rawLegacyData) { - logger.info('persisted state: migrating legacy storage') + logger.debug('persisted state: migrating legacy storage') const legacyData = JSON.parse(rawLegacyData) const newData = transform(legacyData) @@ -139,14 +139,14 @@ export async function migrate() { if (validate.success) { await write(newData) - logger.info('persisted state: migrated legacy storage') + logger.debug('persisted state: migrated legacy storage') } else { logger.error('persisted state: legacy data failed validation', { message: validate.error, }) } } else { - logger.info('persisted state: no migration needed') + logger.debug('persisted state: no migration needed') } } catch (e: any) { logger.error(e, { diff --git a/src/state/queries/feed.ts b/src/state/queries/feed.ts index 67294ece27..1fa92c291f 100644 --- a/src/state/queries/feed.ts +++ b/src/state/queries/feed.ts @@ -1,11 +1,9 @@ -import React from 'react' import { useQuery, useInfiniteQuery, InfiniteData, QueryKey, useMutation, - useQueryClient, } from '@tanstack/react-query' import { AtUri, @@ -15,7 +13,6 @@ import { AppBskyUnspeccedGetPopularFeedGenerators, } from '@atproto/api' -import {logger} from '#/logger' import {router} from '#/routes' import {sanitizeDisplayName} from '#/lib/strings/display-names' import {sanitizeHandle} from '#/lib/strings/handles' @@ -219,83 +216,59 @@ const FOLLOWING_FEED_STUB: FeedSourceInfo = { likeUri: '', } -export function usePinnedFeedsInfos(): { - feeds: FeedSourceInfo[] - hasPinnedCustom: boolean - isLoading: boolean -} { - const queryClient = useQueryClient() - const [tabs, setTabs] = React.useState([ - FOLLOWING_FEED_STUB, - ]) - const [isLoading, setLoading] = React.useState(true) - const {data: preferences} = usePreferencesQuery() +export function usePinnedFeedsInfos() { + const {data: preferences, isLoading: isLoadingPrefs} = usePreferencesQuery() + const pinnedUris = preferences?.feeds?.pinned ?? [] - const hasPinnedCustom = React.useMemo(() => { - return tabs.some(tab => tab !== FOLLOWING_FEED_STUB) - }, [tabs]) + return useQuery({ + staleTime: STALE.INFINITY, + enabled: !isLoadingPrefs, + queryKey: ['pinnedFeedsInfos', pinnedUris.join(',')], + queryFn: async () => { + let resolved = new Map() - React.useEffect(() => { - if (!preferences?.feeds?.pinned) return - const uris = preferences.feeds.pinned - - async function fetchFeedInfo() { - const reqs = [] - - for (const uri of uris) { - const cached = queryClient.getQueryData( - feedSourceInfoQueryKey({uri}), - ) - - if (cached) { - reqs.push(cached) - } else { - reqs.push( - (async () => { - // these requests can fail, need to filter those out - try { - return await queryClient.fetchQuery({ - staleTime: STALE.SECONDS.FIFTEEN, - queryKey: feedSourceInfoQueryKey({uri}), - queryFn: async () => { - const type = getFeedTypeFromUri(uri) - - if (type === 'feed') { - const res = - await getAgent().app.bsky.feed.getFeedGenerator({ - feed: uri, - }) - return hydrateFeedGenerator(res.data.view) - } else { - const res = await getAgent().app.bsky.graph.getList({ - list: uri, - limit: 1, - }) - return hydrateList(res.data.list) - } - }, - }) - } catch (e) { - // expected failure - logger.info(`usePinnedFeedsInfos: failed to fetch ${uri}`, { - error: e, - }) - } - })(), - ) - } + // Get all feeds. We can do this in a batch. + const feedUris = pinnedUris.filter( + uri => getFeedTypeFromUri(uri) === 'feed', + ) + let feedsPromise = Promise.resolve() + if (feedUris.length > 0) { + feedsPromise = getAgent() + .app.bsky.feed.getFeedGenerators({ + feeds: feedUris, + }) + .then(res => { + for (let feedView of res.data.feeds) { + resolved.set(feedView.uri, hydrateFeedGenerator(feedView)) + } + }) } - const views = (await Promise.all(reqs)).filter( - Boolean, - ) as FeedSourceInfo[] + // Get all lists. This currently has to be done individually. + const listUris = pinnedUris.filter( + uri => getFeedTypeFromUri(uri) === 'list', + ) + const listsPromises = listUris.map(listUri => + getAgent() + .app.bsky.graph.getList({ + list: listUri, + limit: 1, + }) + .then(res => { + const listView = res.data.list + resolved.set(listView.uri, hydrateList(listView)) + }), + ) - setTabs([FOLLOWING_FEED_STUB].concat(views)) - setLoading(false) - } - - fetchFeedInfo() - }, [queryClient, setTabs, preferences?.feeds?.pinned]) - - return {feeds: tabs, hasPinnedCustom, isLoading} + // The returned result will have the original order. + const result = [FOLLOWING_FEED_STUB] + await Promise.allSettled([feedsPromise, ...listsPromises]) + for (let pinnedUri of pinnedUris) { + if (resolved.has(pinnedUri)) { + result.push(resolved.get(pinnedUri)) + } + } + return result + }, + }) } diff --git a/src/state/queries/post-feed.ts b/src/state/queries/post-feed.ts index 4899e53ff7..0e6eef52ca 100644 --- a/src/state/queries/post-feed.ts +++ b/src/state/queries/post-feed.ts @@ -4,6 +4,7 @@ import { AppBskyFeedDefs, AppBskyFeedPost, ModerationDecision, + AtUri, } from '@atproto/api' import { useInfiniteQuery, @@ -32,6 +33,7 @@ import {KnownError} from '#/view/com/posts/FeedErrorMessage' import {embedViewRecordToPostView, getEmbeddedPost} from './util' import {useModerationOpts} from './preferences' import {queryClient} from 'lib/react-query' +import {BSKY_FEED_OWNER_DIDS} from 'lib/constants' type ActorDid = string type AuthorFilter = @@ -140,24 +142,41 @@ export function usePostFeedQuery( cursor: undefined, } - const res = await api.fetch({cursor, limit: PAGE_SIZE}) - precacheFeedPostProfiles(queryClient, res.feed) + try { + const res = await api.fetch({cursor, limit: PAGE_SIZE}) + precacheFeedPostProfiles(queryClient, res.feed) - /* - * If this is a public view, we need to check if posts fail moderation. - * If all fail, we throw an error. If only some fail, we continue and let - * moderations happen later, which results in some posts being shown and - * some not. - */ - if (!getAgent().session) { - assertSomePostsPassModeration(res.feed) - } + /* + * If this is a public view, we need to check if posts fail moderation. + * If all fail, we throw an error. If only some fail, we continue and let + * moderations happen later, which results in some posts being shown and + * some not. + */ + if (!getAgent().session) { + assertSomePostsPassModeration(res.feed) + } - return { - api, - cursor: res.cursor, - feed: res.feed, - fetchedAt: Date.now(), + return { + api, + cursor: res.cursor, + feed: res.feed, + fetchedAt: Date.now(), + } + } catch (e) { + const feedDescParts = feedDesc.split('|') + const feedOwnerDid = new AtUri(feedDescParts[1]).hostname + + if ( + feedDescParts[0] === 'feedgen' && + BSKY_FEED_OWNER_DIDS.includes(feedOwnerDid) + ) { + logger.error(`Bluesky feed may be offline: ${feedOwnerDid}`, { + feedDesc, + jsError: e, + }) + } + + throw e } }, initialPageParam: undefined, @@ -264,7 +283,7 @@ export function usePostFeedQuery( .success ) { return { - _reactKey: `${slice._reactKey}-${i}`, + _reactKey: `${slice._reactKey}-${i}-${item.post.uri}`, uri: item.post.uri, post: item.post, record: item.post.record, diff --git a/src/state/queries/preferences/const.ts b/src/state/queries/preferences/const.ts index a5d3035d5c..bc08da9870 100644 --- a/src/state/queries/preferences/const.ts +++ b/src/state/queries/preferences/const.ts @@ -7,7 +7,7 @@ import {DEFAULT_LOGGED_OUT_LABEL_PREFERENCES} from '#/state/queries/preferences/ export const DEFAULT_HOME_FEED_PREFS: UsePreferencesQueryResponse['feedViewPrefs'] = { hideReplies: false, - hideRepliesByUnfollowed: false, + hideRepliesByUnfollowed: true, hideRepliesByLikeCount: 0, hideReposts: false, hideQuotePosts: false, diff --git a/src/state/queries/preferences/index.ts b/src/state/queries/preferences/index.ts index 0fa8f4dfbe..07d953c94c 100644 --- a/src/state/queries/preferences/index.ts +++ b/src/state/queries/preferences/index.ts @@ -4,6 +4,7 @@ import { LabelPreference, BskyFeedViewPreference, ModerationOpts, + AppBskyActorDefs, } from '@atproto/api' import {track} from '#/lib/analytics/analytics' @@ -92,6 +93,7 @@ export function useModerationOpts() { ...moderationPrefs, hiddenPosts, }, + mutedWords: prefs.data.mutedWords || [], // TODO labelDefs, } }, [override, currentAccount, labelDefs, prefs.data, hiddenPosts]) @@ -171,7 +173,7 @@ export function usePreferencesSetBirthDateMutation() { return useMutation({ mutationFn: async ({birthDate}: {birthDate: Date}) => { - await getAgent().setPersonalDetails({birthDate}) + await getAgent().setPersonalDetails({birthDate: birthDate.toISOString()}) // triggers a refetch await queryClient.invalidateQueries({ queryKey: preferencesQueryKey, @@ -285,3 +287,45 @@ export function useUnpinFeedMutation() { }, }) } + +export function useUpsertMutedWordsMutation() { + const queryClient = useQueryClient() + + return useMutation({ + mutationFn: async (mutedWords: AppBskyActorDefs.MutedWord[]) => { + await getAgent().upsertMutedWords(mutedWords) + // triggers a refetch + await queryClient.invalidateQueries({ + queryKey: preferencesQueryKey, + }) + }, + }) +} + +export function useUpdateMutedWordMutation() { + const queryClient = useQueryClient() + + return useMutation({ + mutationFn: async (mutedWord: AppBskyActorDefs.MutedWord) => { + await getAgent().updateMutedWord(mutedWord) + // triggers a refetch + await queryClient.invalidateQueries({ + queryKey: preferencesQueryKey, + }) + }, + }) +} + +export function useRemoveMutedWordMutation() { + const queryClient = useQueryClient() + + return useMutation({ + mutationFn: async (mutedWord: AppBskyActorDefs.MutedWord) => { + await getAgent().removeMutedWord(mutedWord) + // triggers a refetch + await queryClient.invalidateQueries({ + queryKey: preferencesQueryKey, + }) + }, + }) +} diff --git a/src/state/session/index.tsx b/src/state/session/index.tsx index 772daf1395..f3b3d70ae7 100644 --- a/src/state/session/index.tsx +++ b/src/state/session/index.tsx @@ -135,7 +135,7 @@ function createPersistSessionHandler( accessJwt: session?.accessJwt, } - logger.info(`session: persistSession`, { + logger.debug(`session: persistSession`, { event, deactivated: refreshedAccount.deactivated, }) @@ -324,7 +324,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) { ) const logout = React.useCallback(async () => { - logger.info(`session: logout`) + logger.debug(`session: logout`) clearCurrentAccount() setStateAndPersist(s => { return { @@ -380,7 +380,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) { } if (canReusePrevSession) { - logger.info(`session: attempting to reuse previous session`) + logger.debug(`session: attempting to reuse previous session`) agent.session = prevSession __globalAgent = agent @@ -390,7 +390,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) { if (prevSession.deactivated) { // don't attempt to resume // use will be taken to the deactivated screen - logger.info(`session: reusing session for deactivated account`) + logger.debug(`session: reusing session for deactivated account`) return } @@ -416,7 +416,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) { __globalAgent = PUBLIC_BSKY_AGENT }) } else { - logger.info(`session: attempting to resume using previous session`) + logger.debug(`session: attempting to resume using previous session`) try { const freshAccount = await resumeSessionWithFreshAccount() @@ -437,7 +437,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) { } async function resumeSessionWithFreshAccount(): Promise { - logger.info(`session: resumeSessionWithFreshAccount`) + logger.debug(`session: resumeSessionWithFreshAccount`) await networkRetry(1, () => agent.resumeSession(prevSession)) @@ -558,11 +558,11 @@ export function Provider({children}: React.PropsWithChildren<{}>) { return persisted.onUpdate(() => { const session = persisted.get('session') - logger.info(`session: persisted onUpdate`, {}) + logger.debug(`session: persisted onUpdate`, {}) if (session.currentAccount && session.currentAccount.refreshJwt) { if (session.currentAccount?.did !== state.currentAccount?.did) { - logger.info(`session: persisted onUpdate, switching accounts`, { + logger.debug(`session: persisted onUpdate, switching accounts`, { from: { did: state.currentAccount?.did, handle: state.currentAccount?.handle, @@ -575,7 +575,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) { initSession(session.currentAccount) } else { - logger.info(`session: persisted onUpdate, updating session`, {}) + logger.debug(`session: persisted onUpdate, updating session`, {}) /* * Use updated session in this tab's agent. Do not call diff --git a/src/state/shell/composer.tsx b/src/state/shell/composer.tsx index c8392b825f..a09e8fba9f 100644 --- a/src/state/shell/composer.tsx +++ b/src/state/shell/composer.tsx @@ -38,6 +38,8 @@ export interface ComposerOpts { quote?: ComposerOptsQuote mention?: string // handle of user to mention openPicker?: (pos: DOMRect | undefined) => void + text?: string + imageUris?: {uri: string; width: number; height: number}[] } type StateContext = ComposerOpts | undefined diff --git a/src/state/util.ts b/src/state/util.ts index 57f4331b05..f65d14a84c 100644 --- a/src/state/util.ts +++ b/src/state/util.ts @@ -3,6 +3,7 @@ import {useLightboxControls} from './lightbox' import {useModalControls} from './modals' import {useComposerControls} from './shell/composer' import {useSetDrawerOpen} from './shell/drawer-open' +import {useDialogStateControlContext} from '#/state/dialogs' /** * returns true if something was closed @@ -12,6 +13,7 @@ export function useCloseAnyActiveElement() { const {closeLightbox} = useLightboxControls() const {closeModal} = useModalControls() const {closeComposer} = useComposerControls() + const {closeAllDialogs} = useDialogStateControlContext() const setDrawerOpen = useSetDrawerOpen() return useCallback(() => { if (closeLightbox()) { @@ -23,9 +25,12 @@ export function useCloseAnyActiveElement() { if (closeComposer()) { return true } + if (closeAllDialogs()) { + return true + } setDrawerOpen(false) return false - }, [closeLightbox, closeModal, closeComposer, setDrawerOpen]) + }, [closeLightbox, closeModal, closeComposer, setDrawerOpen, closeAllDialogs]) } /** @@ -35,11 +40,19 @@ export function useCloseAllActiveElements() { const {closeLightbox} = useLightboxControls() const {closeAllModals} = useModalControls() const {closeComposer} = useComposerControls() + const {closeAllDialogs: closeAlfDialogs} = useDialogStateControlContext() const setDrawerOpen = useSetDrawerOpen() return useCallback(() => { closeLightbox() closeAllModals() closeComposer() + closeAlfDialogs() setDrawerOpen(false) - }, [closeLightbox, closeAllModals, closeComposer, setDrawerOpen]) + }, [ + closeLightbox, + closeAllModals, + closeComposer, + closeAlfDialogs, + setDrawerOpen, + ]) } diff --git a/src/view/com/auth/create/Step1.tsx b/src/view/com/auth/create/Step1.tsx index 4c70184850..c1bec535f5 100644 --- a/src/view/com/auth/create/Step1.tsx +++ b/src/view/com/auth/create/Step1.tsx @@ -4,7 +4,6 @@ import { Keyboard, StyleSheet, TouchableOpacity, - TouchableWithoutFeedback, View, } from 'react-native' import {CreateAccountState, CreateAccountDispatch, is18} from './state' @@ -19,7 +18,6 @@ import {ErrorMessage} from 'view/com/util/error/ErrorMessage' import {isWeb} from 'platform/detection' import {Trans, msg} from '@lingui/macro' import {useLingui} from '@lingui/react' -import {useModalControls} from '#/state/modals' import {logger} from '#/logger' import { FontAwesomeIcon, @@ -49,7 +47,6 @@ export function Step1({ }) { const pal = usePalette('default') const {_} = useLingui() - const {openModal} = useModalControls() const serverInputControl = useDialogControl() const onPressSelectService = React.useCallback(() => { @@ -57,10 +54,6 @@ export function Step1({ Keyboard.dismiss() }, [serverInputControl]) - const onPressWaitlist = React.useCallback(() => { - openModal({name: 'waitlist'}) - }, [openModal]) - const birthDate = React.useMemo(() => { return sanitizeDate(uiState.birthDate) }, [uiState.birthDate]) @@ -164,23 +157,7 @@ export function Step1({ )} - {!uiState.inviteCode && uiState.isInviteCodeRequired ? ( - - - Don't have an invite code?{' '} - - - - - Join the waitlist. - - - - - ) : ( + {uiState.inviteCode ? ( <> )} - )} + ) : undefined} )} diff --git a/src/view/com/auth/create/Step2.tsx b/src/view/com/auth/create/Step2.tsx index a389203098..5c262977f1 100644 --- a/src/view/com/auth/create/Step2.tsx +++ b/src/view/com/auth/create/Step2.tsx @@ -133,8 +133,8 @@ function IsValidIcon({valid}: {valid: boolean}) { const t = useTheme() if (!valid) { - return + return } - return + return } diff --git a/src/view/com/auth/login/LoginForm.tsx b/src/view/com/auth/login/LoginForm.tsx index e480de7a4c..fdba9f203f 100644 --- a/src/view/com/auth/login/LoginForm.tsx +++ b/src/view/com/auth/login/LoginForm.tsx @@ -107,7 +107,7 @@ export const LoginForm = ({ const errMsg = e.toString() setIsProcessing(false) if (errMsg.includes('Authentication Required')) { - logger.info('Failed to login due to invalid credentials', { + logger.debug('Failed to login due to invalid credentials', { error: errMsg, }) setError(_(msg`Invalid username or password`)) diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx index f52b0890cc..399d420a68 100644 --- a/src/view/com/composer/Composer.tsx +++ b/src/view/com/composer/Composer.tsx @@ -71,6 +71,8 @@ export const ComposePost = observer(function ComposePost({ quote: initQuote, mention: initMention, openPicker, + text: initText, + imageUris: initImageUris, }: Props) { const {currentAccount} = useSession() const {data: currentProfile} = useProfileQuery({did: currentAccount!.did}) @@ -91,7 +93,9 @@ export const ComposePost = observer(function ComposePost({ const [error, setError] = useState('') const [richtext, setRichText] = useState( new RichText({ - text: initMention + text: initText + ? initText + : initMention ? insertMentionAt( `@${initMention}`, initMention.length + 1, @@ -110,7 +114,10 @@ export const ComposePost = observer(function ComposePost({ const [labels, setLabels] = useState([]) const [threadgate, setThreadgate] = useState([]) const [suggestedLinks, setSuggestedLinks] = useState>(new Set()) - const gallery = useMemo(() => new GalleryModel(), []) + const gallery = useMemo( + () => new GalleryModel(initImageUris), + [initImageUris], + ) const onClose = useCallback(() => { closeComposer() }, [closeComposer]) diff --git a/src/view/com/composer/text-input/TextInput.tsx b/src/view/com/composer/text-input/TextInput.tsx index 17f9513b72..20be585c25 100644 --- a/src/view/com/composer/text-input/TextInput.tsx +++ b/src/view/com/composer/text-input/TextInput.tsx @@ -190,12 +190,11 @@ export const TextInput = forwardRef(function TextInputImpl( let i = 0 return Array.from(richtext.segments()).map(segment => { - const isTag = AppBskyRichtextFacet.isTag(segment.facet?.features?.[0]) return ( {segment.text} diff --git a/src/view/com/composer/text-input/TextInput.web.tsx b/src/view/com/composer/text-input/TextInput.web.tsx index 199f1f7499..c62d11201f 100644 --- a/src/view/com/composer/text-input/TextInput.web.tsx +++ b/src/view/com/composer/text-input/TextInput.web.tsx @@ -23,6 +23,7 @@ import {Portal} from '#/components/Portal' import {Text} from '../../util/text/Text' import {Trans} from '@lingui/macro' import Animated, {FadeIn, FadeOut} from 'react-native-reanimated' +import {TagDecorator} from './web/TagDecorator' export interface TextInputRef { focus: () => void @@ -67,6 +68,7 @@ export const TextInput = React.forwardRef(function TextInputImpl( () => [ Document, LinkDecorator, + TagDecorator, Mention.configure({ HTMLAttributes: { class: 'mention', diff --git a/src/view/com/composer/text-input/web/LinkDecorator.ts b/src/view/com/composer/text-input/web/LinkDecorator.ts index 19945de086..e36ac80e42 100644 --- a/src/view/com/composer/text-input/web/LinkDecorator.ts +++ b/src/view/com/composer/text-input/web/LinkDecorator.ts @@ -18,6 +18,8 @@ import {Mark} from '@tiptap/core' import {Plugin, PluginKey} from '@tiptap/pm/state' import {Node as ProsemirrorNode} from '@tiptap/pm/model' import {Decoration, DecorationSet} from '@tiptap/pm/view' +import {URL_REGEX} from '@atproto/api' + import {isValidDomain} from 'lib/strings/url-helpers' export const LinkDecorator = Mark.create({ @@ -78,8 +80,7 @@ function linkDecorator() { function iterateUris(str: string, cb: (from: number, to: number) => void) { let match - const re = - /(^|\s|\()((https?:\/\/[\S]+)|((?[a-z][a-z0-9]*(\.[a-z0-9]+)+)[\S]*))/gim + const re = URL_REGEX while ((match = re.exec(str))) { let uri = match[2] if (!uri.startsWith('http')) { diff --git a/src/view/com/composer/text-input/web/TagDecorator.ts b/src/view/com/composer/text-input/web/TagDecorator.ts new file mode 100644 index 0000000000..2bf3184a8c --- /dev/null +++ b/src/view/com/composer/text-input/web/TagDecorator.ts @@ -0,0 +1,91 @@ +/** + * TipTap is a stateful rich-text editor, which is extremely useful + * when you _want_ it to be stateful formatting such as bold and italics. + * + * However we also use "stateless" behaviors, specifically for URLs + * where the text itself drives the formatting. + * + * This plugin uses a regex to detect URIs and then applies + * link decorations (a with the "autolink") class. That avoids + * adding any stateful formatting to TipTap's document model. + * + * We then run the URI detection again when constructing the + * RichText object from TipTap's output and merge their features into + * the facet-set. + */ + +import {Mark} from '@tiptap/core' +import {Plugin, PluginKey} from '@tiptap/pm/state' +import {Node as ProsemirrorNode} from '@tiptap/pm/model' +import {Decoration, DecorationSet} from '@tiptap/pm/view' +import {TAG_REGEX, TRAILING_PUNCTUATION_REGEX} from '@atproto/api' + +function getDecorations(doc: ProsemirrorNode) { + const decorations: Decoration[] = [] + + doc.descendants((node, pos) => { + if (node.isText && node.text) { + const regex = TAG_REGEX + const textContent = node.textContent + + let match + while ((match = regex.exec(textContent))) { + const [matchedString, _, tag] = match + + if (!tag || tag.replace(TRAILING_PUNCTUATION_REGEX, '').length > 64) + continue + + const [trailingPunc = ''] = tag.match(TRAILING_PUNCTUATION_REGEX) || [] + const matchedFrom = match.index + matchedString.indexOf(tag) + const matchedTo = matchedFrom + (tag.length - trailingPunc.length) + + /* + * The match is exclusive of `#` so we need to adjust the start of the + * highlight by -1 to include the `#` + */ + const start = pos + matchedFrom - 1 + const end = pos + matchedTo + + decorations.push( + Decoration.inline(start, end, { + class: 'autolink', + }), + ) + } + } + }) + + return DecorationSet.create(doc, decorations) +} + +const tagDecoratorPlugin: Plugin = new Plugin({ + key: new PluginKey('link-decorator'), + + state: { + init: (_, {doc}) => getDecorations(doc), + apply: (transaction, decorationSet) => { + if (transaction.docChanged) { + return getDecorations(transaction.doc) + } + return decorationSet.map(transaction.mapping, transaction.doc) + }, + }, + + props: { + decorations(state) { + return tagDecoratorPlugin.getState(state) + }, + }, +}) + +export const TagDecorator = Mark.create({ + name: 'tag-decorator', + priority: 1000, + keepOnSplit: false, + inclusive() { + return true + }, + addProseMirrorPlugins() { + return [tagDecoratorPlugin] + }, +}) diff --git a/src/view/com/feeds/FeedPage.tsx b/src/view/com/feeds/FeedPage.tsx index 60814e8372..e6b5d1fb68 100644 --- a/src/view/com/feeds/FeedPage.tsx +++ b/src/view/com/feeds/FeedPage.tsx @@ -1,30 +1,24 @@ import React from 'react' -import { - FontAwesomeIcon, - FontAwesomeIconStyle, -} from '@fortawesome/react-native-fontawesome' 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 {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 {s} from 'lib/styles' 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' import {LoadLatestBtn} from '../util/load-latest/LoadLatestBtn' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useSession} from '#/state/session' import {useComposerControls} from '#/state/shell/composer' -import {listenSoftReset, emitSoftReset} from '#/state/events' +import {listenSoftReset} from '#/state/events' import {truncateAndInvalidate} from '#/state/queries/util' import {TabState, getTabState, getRootNavigation} from '#/lib/routes/helpers' import {isNative} from '#/platform/detection' @@ -47,10 +41,8 @@ export function FeedPage({ renderEndOfFeed?: () => JSX.Element }) { const {hasSession} = useSession() - const pal = usePalette('default') const {_} = useLingui() const navigation = useNavigation() - const {isDesktop} = useWebMediaQueries() const queryClient = useQueryClient() const {openComposer} = useComposerControls() const [isScrolledDown, setIsScrolledDown] = React.useState(false) @@ -99,63 +91,6 @@ export function FeedPage({ setHasNew(false) }, [scrollToTop, feed, queryClient, setHasNew]) - const ListHeaderComponent = React.useCallback(() => { - if (isDesktop) { - return ( - - - Bluesky{' '} - {hasNew && ( - - )} - - } - onPress={emitSoftReset} - /> - {hasSession && ( - - } - /> - )} - - ) - } - return <> - }, [isDesktop, pal.view, pal.text, pal.textLight, hasNew, _, hasSession]) - return ( @@ -171,7 +106,6 @@ export function FeedPage({ onHasNew={setHasNew} renderEmptyState={renderEmptyState} renderEndOfFeed={renderEndOfFeed} - ListHeaderComponent={ListHeaderComponent} headerOffset={headerOffset} /> @@ -200,21 +134,12 @@ export function FeedPage({ function useHeaderOffset() { const {isDesktop, isTablet} = useWebMediaQueries() const {fontScale} = useWindowDimensions() - const {hasSession} = useSession() if (isDesktop || isTablet) { return 0 } - if (hasSession) { - const navBarPad = 16 - const navBarText = 21 * fontScale - const tabBarPad = 20 + 3 // nav bar padding + border - const tabBarText = 16 * fontScale - const magic = 7 * fontScale - return navBarPad + navBarText + tabBarPad + tabBarText + magic - } else { - const navBarPad = 16 - const navBarText = 21 * fontScale - const magic = 4 * fontScale - return navBarPad + navBarText + magic - } + const navBarHeight = 42 + const tabBarPad = 10 + 10 + 3 // padding + border + const normalLineHeight = 1.2 + const tabBarText = 16 * normalLineHeight * fontScale + return navBarHeight + tabBarPad + tabBarText } diff --git a/src/view/com/home/HomeHeader.tsx b/src/view/com/home/HomeHeader.tsx index 5ffa31f392..aa3ecb7fc2 100644 --- a/src/view/com/home/HomeHeader.tsx +++ b/src/view/com/home/HomeHeader.tsx @@ -1,8 +1,7 @@ import React from 'react' import {RenderTabBarFnProps} from 'view/com/pager/Pager' import {HomeHeaderLayout} from './HomeHeaderLayout' -import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' -import {usePinnedFeedsInfos} from '#/state/queries/feed' +import {FeedSourceInfo} from '#/state/queries/feed' import {useNavigation} from '@react-navigation/native' import {NavigationProp} from 'lib/routes/types' import {isWeb} from 'platform/detection' @@ -10,25 +9,22 @@ import {TabBar} from '../pager/TabBar' import {usePalette} from '#/lib/hooks/usePalette' export function HomeHeader( - props: RenderTabBarFnProps & {testID?: string; onPressSelected: () => void}, -) { - const {isDesktop} = useWebMediaQueries() - if (isDesktop) { - return null - } - return -} - -export function HomeHeaderInner( - props: RenderTabBarFnProps & {testID?: string; onPressSelected: () => void}, + props: RenderTabBarFnProps & { + testID?: string + onPressSelected: () => void + feeds: FeedSourceInfo[] + }, ) { + const {feeds} = props const navigation = useNavigation() - const {feeds, hasPinnedCustom} = usePinnedFeedsInfos() const pal = usePalette('default') + const hasPinnedCustom = React.useMemo(() => { + return feeds.some(tab => tab.uri !== '') + }, [feeds]) + const items = React.useMemo(() => { const pinnedNames = feeds.map(f => f.displayName) - if (!hasPinnedCustom) { return pinnedNames.concat('Feeds ✨') } @@ -56,7 +52,7 @@ export function HomeHeaderInner( ) return ( - + {children} + return } else { - return {children} + return } } -function HomeHeaderLayoutTablet({children}: {children: React.ReactNode}) { +function HomeHeaderLayoutDesktopAndTablet({ + children, + tabBarAnchor, +}: { + children: React.ReactNode + tabBarAnchor: JSX.Element | null | undefined +}) { const pal = usePalette('default') const {headerMinimalShellTransform} = useMinimalShellMode() const {headerHeight} = useShellLayout() + const {_} = useLingui() return ( - // @ts-ignore the type signature for transform wrong here, translateX and translateY need to be in separate objects -prf - { - headerHeight.value = e.nativeEvent.layout.height - }}> - {children} - + <> + + + + + + + + + + {tabBarAnchor} + { + headerHeight.value = e.nativeEvent.layout.height + }} + style={[ + pal.view, + pal.border, + styles.bar, + styles.tabBar, + headerMinimalShellTransform, + ]}> + {children} + + ) } const styles = StyleSheet.create({ - tabBar: { + bar: { // @ts-ignore Web only - position: 'sticky', - zIndex: 1, - // @ts-ignore Web only -prf left: 'calc(50% - 300px)', width: 600, - top: 0, - flexDirection: 'row', - alignItems: 'center', borderLeftWidth: 1, borderRightWidth: 1, }, + topBar: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + paddingHorizontal: 18, + paddingTop: 16, + paddingBottom: 8, + }, + tabBar: { + // @ts-ignore Web only + position: 'sticky', + top: 0, + flexDirection: 'column', + alignItems: 'center', + borderLeftWidth: 1, + borderRightWidth: 1, + zIndex: 1, + }, }) diff --git a/src/view/com/home/HomeHeaderLayoutMobile.tsx b/src/view/com/home/HomeHeaderLayoutMobile.tsx index 6c4b911f07..d7b7231c60 100644 --- a/src/view/com/home/HomeHeaderLayoutMobile.tsx +++ b/src/view/com/home/HomeHeaderLayoutMobile.tsx @@ -23,6 +23,7 @@ export function HomeHeaderLayoutMobile({ children, }: { children: React.ReactNode + tabBarAnchor: JSX.Element | null | undefined }) { const pal = usePalette('default') const {_} = useLingui() @@ -103,7 +104,6 @@ const styles = StyleSheet.create({ right: 0, top: 0, flexDirection: 'column', - borderBottomWidth: 1, }, topBar: { flexDirection: 'row', diff --git a/src/view/com/modals/Modal.tsx b/src/view/com/modals/Modal.tsx index 822e1020c0..a9207607b1 100644 --- a/src/view/com/modals/Modal.tsx +++ b/src/view/com/modals/Modal.tsx @@ -19,7 +19,6 @@ import * as EditImageModal from './AltImage' import * as ReportModal from './report/Modal' import * as DeleteAccountModal from './DeleteAccount' import * as ChangeHandleModal from './ChangeHandle' -import * as WaitlistModal from './Waitlist' import * as InviteCodesModal from './InviteCodes' import * as AddAppPassword from './AddAppPasswords' import * as ContentLanguagesSettingsModal from './lang-settings/ContentLanguagesSettings' @@ -103,9 +102,6 @@ export function ModalsContainer() { } else if (activeModal?.name === 'change-handle') { snapPoints = ChangeHandleModal.snapPoints element = - } else if (activeModal?.name === 'waitlist') { - snapPoints = WaitlistModal.snapPoints - element = } else if (activeModal?.name === 'invite-codes') { snapPoints = InviteCodesModal.snapPoints element = diff --git a/src/view/com/modals/Modal.web.tsx b/src/view/com/modals/Modal.web.tsx index 2d2a6f6e6e..347057062e 100644 --- a/src/view/com/modals/Modal.web.tsx +++ b/src/view/com/modals/Modal.web.tsx @@ -21,7 +21,6 @@ import * as CropImageModal from './crop-image/CropImage.web' import * as AltTextImageModal from './AltImage' import * as EditImageModal from './EditImage' import * as ChangeHandleModal from './ChangeHandle' -import * as WaitlistModal from './Waitlist' import * as InviteCodesModal from './InviteCodes' import * as AddAppPassword from './AddAppPasswords' import * as ContentLanguagesSettingsModal from './lang-settings/ContentLanguagesSettings' @@ -100,8 +99,6 @@ function Modal({modal}: {modal: ModalIface}) { element = } else if (modal.name === 'change-handle') { element = - } else if (modal.name === 'waitlist') { - element = } else if (modal.name === 'invite-codes') { element = } else if (modal.name === 'add-app-password') { diff --git a/src/view/com/modals/Waitlist.tsx b/src/view/com/modals/Waitlist.tsx deleted file mode 100644 index 263dd27a2f..0000000000 --- a/src/view/com/modals/Waitlist.tsx +++ /dev/null @@ -1,190 +0,0 @@ -import React from 'react' -import { - ActivityIndicator, - StyleSheet, - TouchableOpacity, - View, -} from 'react-native' -import {TextInput} from './util' -import { - FontAwesomeIcon, - FontAwesomeIconStyle, -} from '@fortawesome/react-native-fontawesome' -import LinearGradient from 'react-native-linear-gradient' -import {Text} from '../util/text/Text' -import {s, gradients} from 'lib/styles' -import {usePalette} from 'lib/hooks/usePalette' -import {useTheme} from 'lib/ThemeContext' -import {ErrorMessage} from '../util/error/ErrorMessage' -import {cleanError} from 'lib/strings/errors' -import {Trans, msg} from '@lingui/macro' -import {useLingui} from '@lingui/react' -import {useModalControls} from '#/state/modals' - -export const snapPoints = ['80%'] - -export function Component({}: {}) { - const pal = usePalette('default') - const theme = useTheme() - const {_} = useLingui() - const {closeModal} = useModalControls() - const [email, setEmail] = React.useState('') - const [isEmailSent, setIsEmailSent] = React.useState(false) - const [isProcessing, setIsProcessing] = React.useState(false) - const [error, setError] = React.useState('') - - const onPressSignup = async () => { - setError('') - setIsProcessing(true) - try { - const res = await fetch('https://bsky.app/api/waitlist', { - method: 'POST', - headers: {'Content-Type': 'application/json'}, - body: JSON.stringify({email}), - }) - const resBody = await res.json() - if (resBody.success) { - setIsEmailSent(true) - } else { - setError( - resBody.error || - _(msg`Something went wrong. Check your email and try again.`), - ) - } - } catch (e: any) { - setError(cleanError(e)) - } - setIsProcessing(false) - } - const onCancel = () => { - closeModal() - } - - return ( - - - - Join the waitlist - - - - Bluesky uses invites to build a healthier community. If you don't - know anybody with an invite, you can sign up for the waitlist and - we'll send one soon. - - - - {error ? ( - - - - ) : undefined} - {isProcessing ? ( - - - - ) : isEmailSent ? ( - - - - - Your email has been saved! We'll be in touch soon. - - - - ) : ( - <> - - - - Join Waitlist - - - - - - Cancel - - - - )} - - - ) -} - -const styles = StyleSheet.create({ - container: { - flex: 1, - }, - innerContainer: { - paddingBottom: 20, - }, - title: { - textAlign: 'center', - marginTop: 12, - marginBottom: 12, - }, - description: { - textAlign: 'center', - paddingHorizontal: 22, - marginBottom: 10, - }, - textInput: { - borderWidth: 1, - borderRadius: 6, - paddingHorizontal: 16, - paddingVertical: 12, - fontSize: 20, - marginHorizontal: 20, - }, - btn: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - borderRadius: 32, - padding: 14, - marginHorizontal: 20, - }, - error: { - borderRadius: 6, - marginHorizontal: 20, - marginBottom: 20, - }, -}) diff --git a/src/view/com/notifications/FeedItem.tsx b/src/view/com/notifications/FeedItem.tsx index 7567b264ec..3d99146ead 100644 --- a/src/view/com/notifications/FeedItem.tsx +++ b/src/view/com/notifications/FeedItem.tsx @@ -228,6 +228,7 @@ let FeedItem = ({ text={sanitizeDisplayName( authors[0].displayName || authors[0].handle, )} + disableMismatchWarning /> {authors.length > 1 ? ( <> diff --git a/src/view/com/pager/TabBar.tsx b/src/view/com/pager/TabBar.tsx index dadcfcebd9..ff8acd60cc 100644 --- a/src/view/com/pager/TabBar.tsx +++ b/src/view/com/pager/TabBar.tsx @@ -4,8 +4,8 @@ import {Text} from '../util/text/Text' import {PressableWithHover} from '../util/PressableWithHover' import {usePalette} from 'lib/hooks/usePalette' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' -import {isWeb} from 'platform/detection' import {DraggableScrollView} from './DraggableScrollView' +import {isNative} from '#/platform/detection' export interface TabBarProps { testID?: string @@ -16,6 +16,10 @@ export interface TabBarProps { onPressSelected?: (index: number) => void } +// How much of the previous/next item we're showing +// to give the user a hint there's more to scroll. +const OFFSCREEN_ITEM_WIDTH = 20 + export function TabBar({ testID, selectedPage, @@ -26,19 +30,68 @@ export function TabBar({ }: TabBarProps) { const pal = usePalette('default') const scrollElRef = useRef(null) + const itemRefs = useRef>([]) const [itemXs, setItemXs] = useState([]) const indicatorStyle = useMemo( () => ({borderBottomColor: indicatorColor || pal.colors.link}), [indicatorColor, pal], ) const {isDesktop, isTablet} = useWebMediaQueries() + const styles = isDesktop || isTablet ? desktopStyles : mobileStyles - // scrolls to the selected item when the page changes useEffect(() => { - scrollElRef.current?.scrollTo({ - x: itemXs[selectedPage] || 0, - }) - }, [scrollElRef, itemXs, selectedPage]) + if (isNative) { + // On native, the primary interaction is swiping. + // We adjust the scroll little by little on every tab change. + // Scroll into view but keep the end of the previous item visible. + let x = itemXs[selectedPage] || 0 + x = Math.max(0, x - OFFSCREEN_ITEM_WIDTH) + scrollElRef.current?.scrollTo({x}) + } else { + // On the web, the primary interaction is tapping. + // Scrolling under tap feels disorienting so only adjust the scroll offset + // when tapping on an item out of view--and we adjust by almost an entire page. + const parent = scrollElRef?.current?.getScrollableNode?.() + if (!parent) { + return + } + const parentRect = parent.getBoundingClientRect() + if (!parentRect) { + return + } + const { + left: parentLeft, + right: parentRight, + width: parentWidth, + } = parentRect + const child = itemRefs.current[selectedPage] + if (!child) { + return + } + const childRect = child.getBoundingClientRect?.() + if (!childRect) { + return + } + const {left: childLeft, right: childRight, width: childWidth} = childRect + let dx = 0 + if (childRight >= parentRight) { + dx += childRight - parentRight + dx += parentWidth - childWidth - OFFSCREEN_ITEM_WIDTH + } else if (childLeft <= parentLeft) { + dx -= parentLeft - childLeft + dx -= parentWidth - childWidth - OFFSCREEN_ITEM_WIDTH + } + let x = parent.scrollLeft + dx + x = Math.max(0, x) + x = Math.min(x, parent.scrollWidth - parentWidth) + if (dx !== 0) { + parent.scroll({ + left: x, + behavior: 'smooth', + }) + } + } + }, [scrollElRef, itemXs, selectedPage, styles]) const onPressItem = useCallback( (index: number) => { @@ -63,8 +116,6 @@ export function TabBar({ [], ) - const styles = isDesktop || isTablet ? desktopStyles : mobileStyles - return ( (itemRefs.current[i] = node)} onLayout={e => onItemLayout(e, i)} - style={[styles.item, selected && indicatorStyle]} + style={styles.item} hoverStyle={pal.viewLight} onPress={() => onPressItem(i)}> - - {item} - + + + {item} + + ) })} + ) } @@ -103,18 +158,25 @@ const desktopStyles = StyleSheet.create({ width: 598, }, contentContainer: { - columnGap: 8, - marginLeft: 14, - paddingRight: 14, + paddingHorizontal: 0, backgroundColor: 'transparent', }, item: { paddingTop: 14, + paddingHorizontal: 14, + justifyContent: 'center', + }, + itemInner: { paddingBottom: 12, - paddingHorizontal: 10, borderBottomWidth: 3, borderBottomColor: 'transparent', - justifyContent: 'center', + }, + outerBottomBorder: { + position: 'absolute', + left: 0, + right: 0, + bottom: -1, + borderBottomWidth: 1, }, }) @@ -123,17 +185,24 @@ const mobileStyles = StyleSheet.create({ flexDirection: 'row', }, contentContainer: { - columnGap: isWeb ? 0 : 20, - marginLeft: isWeb ? 0 : 18, - paddingRight: isWeb ? 0 : 36, backgroundColor: 'transparent', + paddingHorizontal: 8, }, item: { paddingTop: 10, - paddingBottom: 10, - paddingHorizontal: isWeb ? 8 : 0, - borderBottomWidth: 3, - borderBottomColor: 'transparent', + paddingHorizontal: 10, justifyContent: 'center', }, + itemInner: { + paddingBottom: 10, + borderBottomWidth: 3, + borderBottomColor: 'transparent', + }, + outerBottomBorder: { + position: 'absolute', + left: 0, + right: 0, + bottom: -1, + borderBottomWidth: 1, + }, }) diff --git a/src/view/com/post-thread/PostThread.tsx b/src/view/com/post-thread/PostThread.tsx index 280f7208f1..bac7018c34 100644 --- a/src/view/com/post-thread/PostThread.tsx +++ b/src/view/com/post-thread/PostThread.tsx @@ -438,6 +438,7 @@ function PostThreadLoaded({ // @ts-ignore our .web version only -prf desktopFixedHeight removeClippedSubviews={isAndroid ? false : undefined} + windowSize={11} /> ) } diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx index 004c3ee6d4..51e08a1acb 100644 --- a/src/view/com/post-thread/PostThreadItem.tsx +++ b/src/view/com/post-thread/PostThreadItem.tsx @@ -94,6 +94,8 @@ export function PostThreadItem({ if (richText && moderation) { return ( ) : undefined} @@ -489,9 +493,11 @@ let PostThreadItemLoaded = ({ {richText?.text ? ( ) : undefined} diff --git a/src/view/com/post/Post.tsx b/src/view/com/post/Post.tsx index 719a8592e6..37092d4d76 100644 --- a/src/view/com/post/Post.tsx +++ b/src/view/com/post/Post.tsx @@ -190,10 +190,12 @@ function PostInner({ {richText.text ? ( ) : undefined} diff --git a/src/view/com/posts/Feed.tsx b/src/view/com/posts/Feed.tsx index 54d8aa2240..cd3e98785d 100644 --- a/src/view/com/posts/Feed.tsx +++ b/src/view/com/posts/Feed.tsx @@ -32,6 +32,7 @@ import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {DiscoverFallbackHeader} from './DiscoverFallbackHeader' import {FALLBACK_MARKER_POST} from '#/lib/api/feed/home' +import {useInitialNumToRender} from 'lib/hooks/useInitialNumToRender' const LOADING_ITEM = {_reactKey: '__loading__'} const EMPTY_FEED_ITEM = {_reactKey: '__empty__'} @@ -84,6 +85,7 @@ let Feed = ({ const {_} = useLingui() const queryClient = useQueryClient() const {currentAccount} = useSession() + const initialNumToRender = useInitialNumToRender() const [isPTRing, setIsPTRing] = React.useState(false) const checkForNewRef = React.useRef<(() => void) | null>(null) const lastFetchRef = React.useRef(Date.now()) @@ -327,6 +329,8 @@ let Feed = ({ desktopFixedHeight={ desktopFixedHeightOffset ? desktopFixedHeightOffset : true } + initialNumToRender={initialNumToRender} + windowSize={11} /> ) diff --git a/src/view/com/posts/FeedItem.tsx b/src/view/com/posts/FeedItem.tsx index a90ced32c2..3604f9d124 100644 --- a/src/view/com/posts/FeedItem.tsx +++ b/src/view/com/posts/FeedItem.tsx @@ -69,6 +69,8 @@ export function FeedItem({ if (richText && moderation) { return ( ) : undefined} diff --git a/src/view/com/util/Link.tsx b/src/view/com/util/Link.tsx index e4e02e4d76..97efb9b14b 100644 --- a/src/view/com/util/Link.tsx +++ b/src/view/com/util/Link.tsx @@ -162,7 +162,7 @@ export const TextLink = memo(function TextLink({ dataSet, title, onPress, - warnOnMismatchingLabel, + disableMismatchWarning, navigationAction, ...orgProps }: { @@ -175,7 +175,7 @@ export const TextLink = memo(function TextLink({ lineHeight?: number dataSet?: any title?: string - warnOnMismatchingLabel?: boolean + disableMismatchWarning?: boolean navigationAction?: 'push' | 'replace' | 'navigate' } & TextProps) { const {...props} = useLinkProps({to: sanitizeUrl(href)}) @@ -183,14 +183,14 @@ export const TextLink = memo(function TextLink({ const {openModal, closeModal} = useModalControls() const openLink = useOpenLink() - if (warnOnMismatchingLabel && typeof text !== 'string') { + if (!disableMismatchWarning && typeof text !== 'string') { console.error('Unable to detect mismatching label') } props.onPress = React.useCallback( (e?: Event) => { const requiresWarning = - warnOnMismatchingLabel && + !disableMismatchWarning && linkRequiresWarning(href, typeof text === 'string' ? text : '') if (requiresWarning) { e?.preventDefault?.() @@ -230,7 +230,7 @@ export const TextLink = memo(function TextLink({ navigation, href, text, - warnOnMismatchingLabel, + disableMismatchWarning, navigationAction, openLink, ], diff --git a/src/view/com/util/List.web.tsx b/src/view/com/util/List.web.tsx index 29bad2db8b..936bac198d 100644 --- a/src/view/com/util/List.web.tsx +++ b/src/view/com/util/List.web.tsx @@ -172,7 +172,7 @@ function ListImpl( ( const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent) const styles = StyleSheet.create({ - contentContainer: { + sideBorders: { borderLeftWidth: 1, borderRightWidth: 1, }, diff --git a/src/view/com/util/MainScrollProvider.tsx b/src/view/com/util/MainScrollProvider.tsx index 2c90e33ff1..01b8a954d5 100644 --- a/src/view/com/util/MainScrollProvider.tsx +++ b/src/view/com/util/MainScrollProvider.tsx @@ -20,12 +20,14 @@ export function MainScrollProvider({children}: {children: React.ReactNode}) { const setMode = useSetMinimalShellMode() const startDragOffset = useSharedValue(null) const startMode = useSharedValue(null) + const didJustRestoreScroll = useSharedValue(false) useEffect(() => { if (isWeb) { return listenToForcedWindowScroll(() => { startDragOffset.value = null startMode.value = null + didJustRestoreScroll.value = true }) } }) @@ -86,6 +88,11 @@ export function MainScrollProvider({children}: {children: React.ReactNode}) { mode.value = newValue } } else { + if (didJustRestoreScroll.value) { + didJustRestoreScroll.value = false + // Don't hide/show navbar based on scroll restoratoin. + return + } // On the web, we don't try to follow the drag because we don't know when it ends. // Instead, show/hide immediately based on whether we're scrolling up or down. const dy = e.contentOffset.y - (startDragOffset.value ?? 0) @@ -98,7 +105,14 @@ export function MainScrollProvider({children}: {children: React.ReactNode}) { } } }, - [headerHeight, mode, setMode, startDragOffset, startMode], + [ + headerHeight, + mode, + setMode, + startDragOffset, + startMode, + didJustRestoreScroll, + ], ) return ( diff --git a/src/view/com/util/ViewHeader.tsx b/src/view/com/util/ViewHeader.tsx index 1ccfcf56c5..872e10eef0 100644 --- a/src/view/com/util/ViewHeader.tsx +++ b/src/view/com/util/ViewHeader.tsx @@ -13,11 +13,13 @@ import Animated from 'react-native-reanimated' import {useSetDrawerOpen} from '#/state/shell' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' +import {useTheme} from '#/alf' const BACK_HITSLOP = {left: 20, top: 20, right: 50, bottom: 20} export function ViewHeader({ title, + subtitle, canGoBack, showBackButton = true, hideOnScroll, @@ -26,6 +28,7 @@ export function ViewHeader({ renderButton, }: { title: string + subtitle?: string canGoBack?: boolean showBackButton?: boolean hideOnScroll?: boolean @@ -39,6 +42,7 @@ export function ViewHeader({ const navigation = useNavigation() const {track} = useAnalytics() const {isDesktop, isTablet} = useWebMediaQueries() + const t = useTheme() const onPressBack = React.useCallback(() => { if (navigation.canGoBack()) { @@ -71,42 +75,60 @@ export function ViewHeader({ return ( - {showBackButton ? ( - - {canGoBack ? ( - - ) : !isTablet ? ( - + + + {showBackButton ? ( + + {canGoBack ? ( + + ) : !isTablet ? ( + + ) : null} + ) : null} - - ) : null} - - - {title} - + + + {title} + + + {renderButton ? ( + renderButton() + ) : showBackButton ? ( + + ) : null} + + {subtitle ? ( + + + {subtitle} + + + ) : undefined} - {renderButton ? ( - renderButton() - ) : showBackButton ? ( - - ) : null} ) } @@ -185,7 +207,6 @@ function Container({ const styles = StyleSheet.create({ header: { flexDirection: 'row', - alignItems: 'center', paddingHorizontal: 12, paddingVertical: 6, width: '100%', @@ -207,12 +228,14 @@ const styles = StyleSheet.create({ titleContainer: { marginLeft: 'auto', marginRight: 'auto', - paddingRight: 10, + alignItems: 'center', }, title: { fontWeight: 'bold', }, - + subtitle: { + fontSize: 13, + }, backBtn: { width: 30, height: 30, diff --git a/src/view/com/util/Views.d.ts b/src/view/com/util/Views.d.ts index 6a90cc229b..16713921fb 100644 --- a/src/view/com/util/Views.d.ts +++ b/src/view/com/util/Views.d.ts @@ -5,4 +5,6 @@ export function CenteredView({ style, sideBorders, ...props -}: React.PropsWithChildren) +}: React.PropsWithChildren< + ViewProps & {sideBorders?: boolean; topBorder?: boolean} +>) diff --git a/src/view/com/util/Views.web.tsx b/src/view/com/util/Views.web.tsx index db3b9de0d8..ae165077ca 100644 --- a/src/view/com/util/Views.web.tsx +++ b/src/view/com/util/Views.web.tsx @@ -32,8 +32,11 @@ interface AddedProps { export function CenteredView({ style, sideBorders, + topBorder, ...props -}: React.PropsWithChildren) { +}: React.PropsWithChildren< + ViewProps & {sideBorders?: boolean; topBorder?: boolean} +>) { const pal = usePalette('default') const {isMobile} = useWebMediaQueries() if (!isMobile) { @@ -46,6 +49,12 @@ export function CenteredView({ }) style = addStyle(style, pal.border) } + if (topBorder) { + style = addStyle(style, { + borderTopWidth: 1, + }) + style = addStyle(style, pal.border) + } return } diff --git a/src/view/com/util/forms/DateInput.tsx b/src/view/com/util/forms/DateInput.tsx index c5f0afc8fc..0104562aa5 100644 --- a/src/view/com/util/forms/DateInput.tsx +++ b/src/view/com/util/forms/DateInput.tsx @@ -1,8 +1,5 @@ import React, {useState, useCallback} from 'react' import {StyleProp, StyleSheet, TextStyle, View, ViewStyle} from 'react-native' -import DateTimePicker, { - DateTimePickerEvent, -} from '@react-native-community/datetimepicker' import { FontAwesomeIcon, FontAwesomeIconStyle, @@ -14,6 +11,7 @@ import {TypographyVariant} from 'lib/ThemeContext' import {useTheme} from 'lib/ThemeContext' import {usePalette} from 'lib/hooks/usePalette' import {getLocales} from 'expo-localization' +import DatePicker from 'react-native-date-picker' const LOCALE = getLocales()[0] @@ -43,11 +41,9 @@ export function DateInput(props: Props) { }, [props.handleAsUTC]) const onChangeInternal = useCallback( - (event: DateTimePickerEvent, date: Date | undefined) => { + (date: Date) => { setShow(false) - if (date) { - props.onChange(date) - } + props.onChange(date) }, [setShow, props], ) @@ -56,6 +52,10 @@ export function DateInput(props: Props) { setShow(true) }, [setShow]) + const onCancel = useCallback(() => { + setShow(false) + }, []) + return ( {isAndroid && ( @@ -80,15 +80,17 @@ export function DateInput(props: Props) { )} {(isIOS || show) && ( - { return ( ) { const pal = usePalette('default') const theme = useTheme() @@ -119,7 +122,8 @@ export function NativeDropdown({ accessibilityLabel={accessibilityLabel} accessibilityHint={accessibilityHint} onPress={() => setOpen(o => !o)} - hitSlop={HITSLOP_10}> + hitSlop={HITSLOP_10} + style={triggerStyle}> {children} @@ -232,6 +236,10 @@ const styles = StyleSheet.create({ paddingLeft: 12, paddingRight: 12, borderRadius: 8, + fontFamily: + '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif', + outline: 0, + border: 0, }, itemTitle: { fontSize: 16, diff --git a/src/view/com/util/forms/PostDropdownBtn.tsx b/src/view/com/util/forms/PostDropdownBtn.tsx index ccfaff301d..00dfe6a7ac 100644 --- a/src/view/com/util/forms/PostDropdownBtn.tsx +++ b/src/view/com/util/forms/PostDropdownBtn.tsx @@ -36,6 +36,7 @@ import {isWeb} from '#/platform/detection' import {richTextToString} from '#/lib/strings/rich-text-helpers' import {ReportDialog, useReportDialogControl} from '#/components/ReportDialog' import {NEW_REPORT_DIALOG_ENABLED} from '#/lib/build-flags' +import {useGlobalDialogsControlContext} from '#/components/dialogs/Context' let PostDropdownBtn = ({ testID, @@ -68,6 +69,7 @@ let PostDropdownBtn = ({ const openLink = useOpenLink() const control = useReportDialogControl() const navigation = useNavigation() + const {mutedWordsDialogControl} = useGlobalDialogsControlContext() const rootUri = record.reply?.root?.uri || postUri const isThreadMuted = mutedThreads.includes(rootUri) @@ -211,6 +213,20 @@ let PostDropdownBtn = ({ web: 'comment-slash', }, }, + hasSession && { + label: _(msg`Mute words & tags`), + onPress() { + mutedWordsDialogControl.open() + }, + testID: 'postDropdownMuteWordsBtn', + icon: { + ios: { + name: 'speaker.slash', + }, + android: 'ic_lock_silent_mode', + web: 'filter', + }, + }, hasSession && !isAuthor && !isPostHidden && { diff --git a/src/view/com/util/text/RichText.tsx b/src/view/com/util/text/RichText.tsx index b6d461224c..f4ade30e55 100644 --- a/src/view/com/util/text/RichText.tsx +++ b/src/view/com/util/text/RichText.tsx @@ -7,6 +7,9 @@ import {lh} from 'lib/styles' import {toShortUrl} from 'lib/strings/url-helpers' import {useTheme, TypographyVariant} from 'lib/ThemeContext' import {usePalette} from 'lib/hooks/usePalette' +import {makeTagLink} from 'lib/routes/links' +import {TagMenu, useTagMenuControl} from '#/components/TagMenu' +import {isNative} from '#/platform/detection' const WORD_WRAP = {wordWrap: 1} @@ -82,6 +85,7 @@ export function RichText({ for (const segment of richText.segments()) { const link = segment.link const mention = segment.mention + const tag = segment.tag if ( !noLinks && mention && @@ -110,11 +114,25 @@ export function RichText({ href={link.uri} style={[style, lineHeightStyle, pal.link, {pointerEvents: 'auto'}]} dataSet={WORD_WRAP} - warnOnMismatchingLabel selectable={selectable} />, ) } + } else if ( + !noLinks && + tag && + AppBskyRichtextFacet.validateTag(tag).success + ) { + els.push( + , + ) } else { els.push(segment.text) } @@ -133,3 +151,50 @@ export function RichText({ ) } + +function RichTextTag({ + text: tag, + type, + style, + lineHeightStyle, + selectable, +}: { + text: string + type?: TypographyVariant + style?: StyleProp + lineHeightStyle?: TextStyle + selectable?: boolean +}) { + const pal = usePalette('default') + const control = useTagMenuControl() + + const open = React.useCallback(() => { + control.open() + }, [control]) + + return ( + + + {isNative ? ( + + ) : ( + + {tag} + + )} + + + ) +} diff --git a/src/view/icons/index.tsx b/src/view/icons/index.tsx index b7bbf16009..ede1e63355 100644 --- a/src/view/icons/index.tsx +++ b/src/view/icons/index.tsx @@ -103,6 +103,7 @@ import {faUsersSlash} from '@fortawesome/free-solid-svg-icons/faUsersSlash' import {faX} from '@fortawesome/free-solid-svg-icons/faX' import {faXmark} from '@fortawesome/free-solid-svg-icons/faXmark' import {faChevronDown} from '@fortawesome/free-solid-svg-icons/faChevronDown' +import {faFilter} from '@fortawesome/free-solid-svg-icons/faFilter' library.add( faAddressCard, @@ -208,4 +209,5 @@ library.add( faX, faXmark, faChevronDown, + faFilter, ) diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx index 856c237f6e..99ac8c44af 100644 --- a/src/view/screens/Home.tsx +++ b/src/view/screens/Home.tsx @@ -17,11 +17,12 @@ import {UsePreferencesQueryResponse} from '#/state/queries/preferences/types' import {emitSoftReset} from '#/state/events' import {useSession} from '#/state/session' import {useSelectedFeed, useSetSelectedFeed} from '#/state/shell/selected-feed' +import {useSetTitle} from '#/lib/hooks/useSetTitle' type Props = NativeStackScreenProps export function HomeScreen(props: Props) { const {data: preferences} = usePreferencesQuery() - const {feeds: pinnedFeedInfos, isLoading: isPinnedFeedsLoading} = + const {data: pinnedFeedInfos, isLoading: isPinnedFeedsLoading} = usePinnedFeedsInfos() if (preferences && pinnedFeedInfos && !isPinnedFeedsLoading) { return ( @@ -66,6 +67,8 @@ function HomeScreenReady({ const selectedIndex = Math.max(0, maybeFoundIndex) const selectedFeed = allFeeds[selectedIndex] + useSetTitle(pinnedFeedInfos[selectedIndex]?.displayName) + const pagerRef = React.useRef(null) const lastPagerReportedIndexRef = React.useRef(selectedIndex) React.useLayoutEffect(() => { @@ -120,14 +123,14 @@ function HomeScreenReady({ return ( ) }, - [onPressSelected], + [onPressSelected, pinnedFeedInfos], ) const renderFollowingEmptyState = React.useCallback(() => { diff --git a/src/view/screens/Profile.tsx b/src/view/screens/Profile.tsx index 7dae1c9639..36c73fefb3 100644 --- a/src/view/screens/Profile.tsx +++ b/src/view/screens/Profile.tsx @@ -488,6 +488,8 @@ const styles = StyleSheet.create({ container: { flexDirection: 'column', height: '100%', + // @ts-ignore Web-only. + overflowAnchor: 'none', // Fixes jumps when switching tabs while scrolled down. }, loading: { paddingVertical: 10, diff --git a/src/view/screens/ProfileList.tsx b/src/view/screens/ProfileList.tsx index d86b569e25..9e98757efa 100644 --- a/src/view/screens/ProfileList.tsx +++ b/src/view/screens/ProfileList.tsx @@ -60,7 +60,7 @@ import { import {logger} from '#/logger' import {useAnalytics} from '#/lib/analytics/analytics' import {listenSoftReset} from '#/state/events' -import {atoms as a} from '#/alf' +import {atoms as a, useTheme} from '#/alf' const SECTION_TITLES_CURATE = ['Posts', 'About'] const SECTION_TITLES_MOD = ['About'] @@ -699,6 +699,7 @@ const AboutSection = React.forwardRef( ref, ) { const pal = usePalette('default') + const t = useTheme() const {_} = useLingui() const {isMobile} = useWebMediaQueries() const {currentAccount} = useSession() @@ -792,7 +793,7 @@ const AboutSection = React.forwardRef( paddingBottom: isMobile ? 14 : 18, }, ]}> - + Users {isOwner && ( @@ -817,14 +818,18 @@ const AboutSection = React.forwardRef( ) }, [ - pal, - list, isMobile, + pal.border, + pal.textLight, + pal.colors.link, + pal.link, descriptionRT, isCurateList, isOwner, - onPressAddUser, + list.creator, + t.atoms.text, _, + onPressAddUser, ]) const renderEmptyState = useCallback(() => { diff --git a/src/view/screens/Search/Search.tsx b/src/view/screens/Search/Search.tsx index 142726701e..42eec53d31 100644 --- a/src/view/screens/Search/Search.tsx +++ b/src/view/screens/Search/Search.tsx @@ -16,7 +16,7 @@ import { FontAwesomeIcon, FontAwesomeIconStyle, } from '@fortawesome/react-native-fontawesome' -import {useFocusEffect} from '@react-navigation/native' +import {useFocusEffect, useNavigation} from '@react-navigation/native' import {logger} from '#/logger' import { @@ -53,6 +53,7 @@ import {listenSoftReset} from '#/state/events' import {s} from '#/lib/styles' import AsyncStorage from '@react-native-async-storage/async-storage' import {augmentSearchQuery} from '#/lib/strings/helpers' +import {NavigationProp} from '#/lib/routes/types' function Loader() { const pal = usePalette('default') @@ -448,6 +449,7 @@ export function SearchScreenInner({ export function SearchScreen( props: NativeStackScreenProps, ) { + const navigation = useNavigation() const theme = useTheme() const textInput = React.useRef(null) const {_} = useLingui() @@ -472,6 +474,27 @@ export function SearchScreen( React.useState(false) const [searchHistory, setSearchHistory] = React.useState([]) + /** + * The Search screen's `q` param + */ + const queryParam = props.route?.params?.q + + /** + * If `true`, this means we received new instructions from the router. This + * is handled in a effect, and used to update the value of `query` locally + * within this screen. + */ + const routeParamsMismatch = queryParam && queryParam !== query + + React.useEffect(() => { + if (queryParam && routeParamsMismatch) { + // reset immediately and let local state take over + navigation.setParams({q: ''}) + // update query for next search + setQuery(queryParam) + } + }, [queryParam, routeParamsMismatch, navigation]) + React.useEffect(() => { const loadSearchHistory = async () => { try { @@ -774,6 +797,8 @@ export function SearchScreen( )} + ) : routeParamsMismatch ? ( + ) : ( )} diff --git a/src/view/screens/Storybook/Links.tsx b/src/view/screens/Storybook/Links.tsx index 3f18069069..f9ecfba554 100644 --- a/src/view/screens/Storybook/Links.tsx +++ b/src/view/screens/Storybook/Links.tsx @@ -4,7 +4,7 @@ import {View} from 'react-native' import {useTheme, atoms as a} from '#/alf' import {ButtonText} from '#/components/Button' import {InlineLink, Link} from '#/components/Link' -import {H1, H3, Text} from '#/components/Typography' +import {H1, Text} from '#/components/Typography' export function Links() { const t = useTheme() @@ -13,31 +13,19 @@ export function Links() {

Links

- - External + + https://google.com - -

External with custom children

+ + External with custom children (google.com) - External with custom children + Internal (bsky.social) - - https://bsky.social - - - Internal + + Internal (bsky.app) + + + + {({state, props}) => { + return ( + + Open + + ) + }} + + + + + {}}> + + Click me + + + menuControl.close()}> + Another item + + + + + + + {}}> + + Click me + + + menuControl.close()}> + Another item + + + + + + {}}> + + Click me + + + + +
+ ) +} diff --git a/src/view/screens/Storybook/Palette.tsx b/src/view/screens/Storybook/Palette.tsx index 900754681c..42000aa810 100644 --- a/src/view/screens/Storybook/Palette.tsx +++ b/src/view/screens/Storybook/Palette.tsx @@ -1,7 +1,6 @@ import React from 'react' import {View} from 'react-native' -import * as tokens from '#/alf/tokens' import {atoms as a, useTheme} from '#/alf' export function Palette() { @@ -28,79 +27,79 @@ export function Palette() { @@ -108,153 +107,159 @@ export function Palette() { - - + + diff --git a/src/view/screens/Storybook/Typography.tsx b/src/view/screens/Storybook/Typography.tsx index 8ee4270b20..f0d67c5281 100644 --- a/src/view/screens/Storybook/Typography.tsx +++ b/src/view/screens/Storybook/Typography.tsx @@ -22,12 +22,14 @@ export function Typography() { atoms.text_2xs diff --git a/src/view/screens/Storybook/index.tsx b/src/view/screens/Storybook/index.tsx index 56cfbfaf98..3a2e2f3696 100644 --- a/src/view/screens/Storybook/index.tsx +++ b/src/view/screens/Storybook/index.tsx @@ -16,6 +16,7 @@ import {Dialogs} from './Dialogs' import {Breakpoints} from './Breakpoints' import {Shadows} from './Shadows' import {Icons} from './Icons' +import {Menus} from './Menus' export function Storybook() { const t = useTheme() @@ -84,6 +85,8 @@ export function Storybook() { + + diff --git a/src/view/shell/Composer.tsx b/src/view/shell/Composer.tsx index d37ff4fb7c..1937fcb6ea 100644 --- a/src/view/shell/Composer.tsx +++ b/src/view/shell/Composer.tsx @@ -55,6 +55,8 @@ export const Composer = observer(function ComposerImpl({ onPost={state.onPost} quote={state.quote} mention={state.mention} + text={state.text} + imageUris={state.imageUris} /> ) diff --git a/src/view/shell/Composer.web.tsx b/src/view/shell/Composer.web.tsx index 99e659d62d..00233f66af 100644 --- a/src/view/shell/Composer.web.tsx +++ b/src/view/shell/Composer.web.tsx @@ -9,7 +9,7 @@ import {useWebBodyScrollLock} from '#/lib/hooks/useWebBodyScrollLock' import { EmojiPicker, EmojiPickerState, -} from 'view/com/composer/text-input/web/EmojiPicker.web.tsx' +} from 'view/com/composer/text-input/web/EmojiPicker.web' const BOTTOM_BAR_HEIGHT = 61 @@ -69,6 +69,7 @@ export function Composer({}: {winHeight: number}) { onPost={state.onPost} mention={state.mention} openPicker={onOpenPicker} + text={state.text} /> diff --git a/src/view/shell/desktop/Feeds.tsx b/src/view/shell/desktop/Feeds.tsx index c3b1caa354..f447490b36 100644 --- a/src/view/shell/desktop/Feeds.tsx +++ b/src/view/shell/desktop/Feeds.tsx @@ -15,7 +15,7 @@ import {emitSoftReset} from '#/state/events' export function DesktopFeeds() { const pal = usePalette('default') const {_} = useLingui() - const {feeds: pinnedFeedInfos} = usePinnedFeedsInfos() + const {data: pinnedFeedInfos} = usePinnedFeedsInfos() const selectedFeed = useSelectedFeed() const setSelectedFeed = useSetSelectedFeed() const navigation = useNavigation() @@ -25,7 +25,9 @@ export function DesktopFeeds() { } return getCurrentRoute(state) }) - + if (!pinnedFeedInfos) { + return null + } return ( {pinnedFeedInfos.map(feedInfo => { diff --git a/src/view/shell/desktop/LeftNav.tsx b/src/view/shell/desktop/LeftNav.tsx index fbc90bfc6d..c56ba941ed 100644 --- a/src/view/shell/desktop/LeftNav.tsx +++ b/src/view/shell/desktop/LeftNav.tsx @@ -200,10 +200,10 @@ function ComposeBtn() { const fetchHandle = useFetchHandle() const getProfileHandle = async () => { - const {routes} = getState() - const currentRoute = routes[routes.length - 1] + const routes = getState()?.routes + const currentRoute = routes?.[routes?.length - 1] - if (currentRoute.name === 'Profile') { + if (currentRoute?.name === 'Profile') { let handle: string | undefined = ( currentRoute.params as CommonNavigatorParams['Profile'] ).name @@ -391,7 +391,7 @@ export function DesktopLeftNav() { } label={_(msg`Moderation`)} diff --git a/src/view/shell/index.tsx b/src/view/shell/index.tsx index e40865cde0..55a21e53f8 100644 --- a/src/view/shell/index.tsx +++ b/src/view/shell/index.tsx @@ -29,6 +29,8 @@ import {useSession} from '#/state/session' import {useCloseAnyActiveElement} from '#/state/util' import * as notifications from 'lib/notifications/notifications' import {Outlet as PortalOutlet} from '#/components/Portal' +import {MutedWordsDialog} from '#/components/dialogs/MutedWords' +import {useDialogStateContext} from '#/state/dialogs' function ShellInner() { const isDrawerOpen = useIsDrawerOpen() @@ -54,6 +56,7 @@ function ShellInner() { const closeAnyActiveElement = useCloseAnyActiveElement() // start undefined const currentAccountDid = React.useRef(undefined) + const {openDialogs} = useDialogStateContext() React.useEffect(() => { let listener = {remove() {}} @@ -77,9 +80,21 @@ function ShellInner() { } }, [currentAccount]) + /** + * The counterpart to `accessibilityViewIsModal` for Android. This property + * applies to the parent of all non-modal views, and prevents TalkBack from + * navigating within content beneath an open dialog. + * + * @see https://reactnative.dev/docs/accessibility#importantforaccessibility-android + */ + const importantForAccessibility = + openDialogs.length > 0 ? 'no-hide-descendants' : undefined + return ( <> - + + + diff --git a/src/view/shell/index.web.tsx b/src/view/shell/index.web.tsx index 0e7767eae8..9aeb1c860f 100644 --- a/src/view/shell/index.web.tsx +++ b/src/view/shell/index.web.tsx @@ -16,6 +16,7 @@ import {useIsDrawerOpen, useSetDrawerOpen} from '#/state/shell' import {useCloseAllActiveElements} from '#/state/util' import {useWebBodyScrollLock} from '#/lib/hooks/useWebBodyScrollLock' import {Outlet as PortalOutlet} from '#/components/Portal' +import {MutedWordsDialog} from '#/components/dialogs/MutedWords' function ShellInner() { const isDrawerOpen = useIsDrawerOpen() @@ -40,6 +41,8 @@ function ShellInner() { + + diff --git a/web/index.html b/web/index.html index 992e69e053..b6e01ba4c2 100644 --- a/web/index.html +++ b/web/index.html @@ -48,6 +48,12 @@ scrollbar-gutter: stable both-edges; } + /* Buttons and inputs have a font set by UA, so we'll have to reset that */ + button, input, textarea { + font: inherit; + line-height: inherit; + } + /* Color theming */ /* Default will always be white */ :root { @@ -209,6 +215,12 @@ [data-tooltip]:hover::before { display:block; } + + /* NativeDropdown component */ + .radix-dropdown-item:focus, + .nativeDropdown-item:focus { + outline: none; + } diff --git a/yarn.lock b/yarn.lock index 14fd49c477..4b9ba74153 100644 --- a/yarn.lock +++ b/yarn.lock @@ -34,6 +34,20 @@ jsonpointer "^5.0.0" leven "^3.1.0" +"@atproto/api@^0.10.5": + version "0.10.5" + resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.10.5.tgz#e778e2843d08690df8df81f24028a7578e9b3cb4" + integrity sha512-GYdST5sPKU2JnPmm8x3KqjOSlDiYXrp4GkW7bpQTVLPabnUNq5NLN6HJEoJABjjOAsaLF12rBoV+JpRb1UjNsQ== + dependencies: + "@atproto/common-web" "^0.2.3" + "@atproto/lexicon" "^0.3.2" + "@atproto/syntax" "^0.2.0" + "@atproto/xrpc" "^0.4.2" + multiformats "^9.9.0" + tlds "^1.234.0" + typed-emitter "^2.1.0" + zod "^3.21.4" + "@atproto/api@^0.9.5": version "0.9.5" resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.9.5.tgz#630e5d9520bba38d0cd348c8028ddbb73bd074f8" @@ -231,6 +245,17 @@ multiformats "^9.9.0" zod "^3.21.4" +"@atproto/lexicon@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@atproto/lexicon/-/lexicon-0.3.2.tgz#0085a3acd3a77867b8efe188297a1bbacc55ce5c" + integrity sha512-kmGCkrRwpWIqmn/KO4BZwUf8Nmfndk3XvFC06V0ygCWc42g6+t4QP/6ywNW4PgqfZY0Q5aW4EuDfD7KjAFkFtQ== + dependencies: + "@atproto/common-web" "^0.2.3" + "@atproto/syntax" "^0.2.0" + iso-datestring-validator "^2.2.2" + multiformats "^9.9.0" + zod "^3.21.4" + "@atproto/ozone@^0.0.7": version "0.0.7" resolved "https://registry.yarnpkg.com/@atproto/ozone/-/ozone-0.0.7.tgz#bfad82bc1d0900e79401a82f13581f707415505a" @@ -326,6 +351,13 @@ dependencies: "@atproto/common-web" "^0.2.3" +"@atproto/syntax@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@atproto/syntax/-/syntax-0.2.0.tgz#4bab724c02e11f8943b8ec101251082cf55067e9" + integrity sha512-K+9jl6mtxC9ytlR7msSiP9jVNqtdxEBSt0kOfsC924lqGwuD8nlUAMi1GSMgAZJGg/Rd+0MKXh789heTdeL3HQ== + dependencies: + "@atproto/common-web" "^0.2.3" + "@atproto/xrpc-server@^0.4.2": version "0.4.2" resolved "https://registry.yarnpkg.com/@atproto/xrpc-server/-/xrpc-server-0.4.2.tgz#23efd89086b85933f1b0cc00c86e895adcaac315" @@ -351,6 +383,14 @@ "@atproto/lexicon" "^0.3.1" zod "^3.21.4" +"@atproto/xrpc@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@atproto/xrpc/-/xrpc-0.4.2.tgz#57812e0624be597b85f21471acf336513f35ccda" + integrity sha512-x4x2QB4nWmLjIpz2Ue9n/QVbVyJkk6tQMhvmDQaVFF89E3FcVI4rxF4uhzSxaLpbNtyVQBNEEmNHOr5EJLeHVA== + dependencies: + "@atproto/lexicon" "^0.3.2" + zod "^3.21.4" + "@aws-crypto/crc32@3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@aws-crypto/crc32/-/crc32-3.0.0.tgz#07300eca214409c33e3ff769cd5697b57fdd38fa" @@ -3075,6 +3115,27 @@ xcode "^3.0.1" xml2js "0.6.0" +"@expo/config-plugins@~5.0.3": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-5.0.4.tgz#216fea6558fe66615af1370de55193f4181cb23e" + integrity sha512-vzUcVpqOMs3h+hyRdhGwk+eGIOhXa5xYdd92yO17RMNHav3v/+ekMbs7XA2c3lepMO8Yd4/5hqmRw9ZTL6jGzg== + dependencies: + "@expo/config-types" "^47.0.0" + "@expo/json-file" "8.2.36" + "@expo/plist" "0.0.18" + "@expo/sdk-runtime-versions" "^1.0.0" + "@react-native/normalize-color" "^2.0.0" + chalk "^4.1.2" + debug "^4.3.1" + find-up "~5.0.0" + getenv "^1.0.0" + glob "7.1.6" + resolve-from "^5.0.0" + semver "^7.3.5" + slash "^3.0.0" + xcode "^3.0.1" + xml2js "0.4.23" + "@expo/config-plugins@~7.8.2": version "7.8.2" resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-7.8.2.tgz#c00ce93c4d6c2cb9e345ed9cd56ceeea05ab8ddb" @@ -3098,6 +3159,11 @@ xcode "^3.0.1" xml2js "0.6.0" +"@expo/config-types@^47.0.0": + version "47.0.0" + resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-47.0.0.tgz#99eeabe0bba7a776e0f252b78beb0c574692c38d" + integrity sha512-r0pWfuhkv7KIcXMUiNACJmJKKwlTBGMw9VZHNdppS8/0Nve8HZMTkNRFQzTHW1uH3pBj8jEXpyw/2vSWDHex9g== + "@expo/config-types@^50.0.0", "@expo/config-types@^50.0.0-alpha.1": version "50.0.0" resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-50.0.0.tgz#b534d3ec997ec60f8af24f6ad56244c8afc71a0b" @@ -3120,6 +3186,23 @@ slugify "^1.3.4" sucrase "^3.20.0" +"@expo/config@~7.0.0": + version "7.0.3" + resolved "https://registry.yarnpkg.com/@expo/config/-/config-7.0.3.tgz#c9c634e76186de25e296485e51418f1e52966e6e" + integrity sha512-joVtB5o+NF40Tmsdp65UzryRtbnCuMbXkVO4wJnNJO4aaK0EYLdHCYSewORVqNcDfGN0LphQr8VTG2npbd9CJA== + dependencies: + "@babel/code-frame" "~7.10.4" + "@expo/config-plugins" "~5.0.3" + "@expo/config-types" "^47.0.0" + "@expo/json-file" "8.2.36" + getenv "^1.0.0" + glob "7.1.6" + require-from-string "^2.0.2" + resolve-from "^5.0.0" + semver "7.3.2" + slugify "^1.3.4" + sucrase "^3.20.0" + "@expo/config@~8.5.0": version "8.5.0" resolved "https://registry.yarnpkg.com/@expo/config/-/config-8.5.0.tgz#c618e016c3272335e33fec02fb7fd67e4dcc3342" @@ -3219,6 +3302,15 @@ semver "7.3.2" tempy "0.3.0" +"@expo/json-file@8.2.36": + version "8.2.36" + resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-8.2.36.tgz#62a505cb7f30a34d097386476794680a3f7385ff" + integrity sha512-tOZfTiIFA5KmMpdW9KF7bc6CFiGjb0xnbieJhTGlHrLL+ps2G0OkqmuZ3pFEXBOMnJYUVpnSy++52LFxvpa5ZQ== + dependencies: + "@babel/code-frame" "~7.10.4" + json5 "^1.0.1" + write-file-atomic "^2.3.0" + "@expo/json-file@^8.2.37": version "8.2.37" resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-8.2.37.tgz#9c02d3b42134907c69cc0a027b18671b69344049" @@ -3288,6 +3380,15 @@ split "^1.0.1" sudo-prompt "9.1.1" +"@expo/plist@0.0.18": + version "0.0.18" + resolved "https://registry.yarnpkg.com/@expo/plist/-/plist-0.0.18.tgz#9abcde78df703a88f6d9fa1a557ee2f045d178b0" + integrity sha512-+48gRqUiz65R21CZ/IXa7RNBXgAI/uPSdvJqoN9x1hfL44DNbUoWHgHiEXTx7XelcATpDwNTz6sHLfy0iNqf+w== + dependencies: + "@xmldom/xmldom" "~0.7.0" + base64-js "^1.2.3" + xmlbuilder "^14.0.0" + "@expo/plist@^0.1.0": version "0.1.0" resolved "https://registry.yarnpkg.com/@expo/plist/-/plist-0.1.0.tgz#eabc95f951d14e10c87fd0443ee01d567371f058" @@ -4427,6 +4528,18 @@ "@radix-ui/react-use-callback-ref" "1.0.1" "@radix-ui/react-use-escape-keydown" "1.0.3" +"@radix-ui/react-dismissable-layer@1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz#3f98425b82b9068dfbab5db5fff3df6ebf48b9d4" + integrity sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-use-callback-ref" "1.0.1" + "@radix-ui/react-use-escape-keydown" "1.0.3" + "@radix-ui/react-dropdown-menu@^2.0.1": version "2.0.5" resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.0.5.tgz#19bf4de8ffa348b4eb6a86842f14eff93d741170" @@ -4441,6 +4554,20 @@ "@radix-ui/react-primitive" "1.0.3" "@radix-ui/react-use-controllable-state" "1.0.1" +"@radix-ui/react-dropdown-menu@^2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.0.6.tgz#cdf13c956c5e263afe4e5f3587b3071a25755b63" + integrity sha512-i6TuFOoWmLWq+M/eCLGd/bQ2HfAX1RJgvrBQ6AQLmzfvsLdefxbWu8G9zczcPFfcSPehz9GcpF6K9QYreFV8hA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-id" "1.0.1" + "@radix-ui/react-menu" "2.0.6" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-use-controllable-state" "1.0.1" + "@radix-ui/react-focus-guards@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz#1ea7e32092216b946397866199d892f71f7f98ad" @@ -4458,6 +4585,16 @@ "@radix-ui/react-primitive" "1.0.3" "@radix-ui/react-use-callback-ref" "1.0.1" +"@radix-ui/react-focus-scope@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz#2ac45fce8c5bb33eb18419cdc1905ef4f1906525" + integrity sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-use-callback-ref" "1.0.1" + "@radix-ui/react-id@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.0.1.tgz#73cdc181f650e4df24f0b6a5b7aa426b912c88c0" @@ -4491,6 +4628,31 @@ aria-hidden "^1.1.1" react-remove-scroll "2.5.5" +"@radix-ui/react-menu@2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@radix-ui/react-menu/-/react-menu-2.0.6.tgz#2c9e093c1a5d5daa87304b2a2f884e32288ae79e" + integrity sha512-BVkFLS+bUC8HcImkRKPSiVumA1VPOOEC5WBMiT+QAVsPzW1FJzI9KnqgGxVDPBcql5xXrHkD3JOVoXWEXD8SYA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.1" + "@radix-ui/react-collection" "1.0.3" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-direction" "1.0.1" + "@radix-ui/react-dismissable-layer" "1.0.5" + "@radix-ui/react-focus-guards" "1.0.1" + "@radix-ui/react-focus-scope" "1.0.4" + "@radix-ui/react-id" "1.0.1" + "@radix-ui/react-popper" "1.1.3" + "@radix-ui/react-portal" "1.0.4" + "@radix-ui/react-presence" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-roving-focus" "1.0.4" + "@radix-ui/react-slot" "1.0.2" + "@radix-ui/react-use-callback-ref" "1.0.1" + aria-hidden "^1.1.1" + react-remove-scroll "2.5.5" + "@radix-ui/react-popper@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.1.2.tgz#4c0b96fcd188dc1f334e02dba2d538973ad842e9" @@ -4508,6 +4670,23 @@ "@radix-ui/react-use-size" "1.0.1" "@radix-ui/rect" "1.0.1" +"@radix-ui/react-popper@1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.1.3.tgz#24c03f527e7ac348fabf18c89795d85d21b00b42" + integrity sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w== + dependencies: + "@babel/runtime" "^7.13.10" + "@floating-ui/react-dom" "^2.0.0" + "@radix-ui/react-arrow" "1.0.3" + "@radix-ui/react-compose-refs" "1.0.1" + "@radix-ui/react-context" "1.0.1" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-use-callback-ref" "1.0.1" + "@radix-ui/react-use-layout-effect" "1.0.1" + "@radix-ui/react-use-rect" "1.0.1" + "@radix-ui/react-use-size" "1.0.1" + "@radix-ui/rect" "1.0.1" + "@radix-ui/react-portal@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.0.3.tgz#ffb961244c8ed1b46f039e6c215a6c4d9989bda1" @@ -4516,6 +4695,14 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-primitive" "1.0.3" +"@radix-ui/react-portal@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.0.4.tgz#df4bfd353db3b1e84e639e9c63a5f2565fb00e15" + integrity sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-presence@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.0.1.tgz#491990ba913b8e2a5db1b06b203cb24b5cdef9ba" @@ -4624,6 +4811,13 @@ dependencies: merge-options "^3.0.4" +"@react-native-async-storage/async-storage@^1.15.2": + version "1.22.0" + resolved "https://registry.yarnpkg.com/@react-native-async-storage/async-storage/-/async-storage-1.22.0.tgz#202a9afd15a5b829c39b709d0ca3942612441efc" + integrity sha512-b5KD010iiZnot86RbAaHpLuHwmPW2qA3SSN/OSZhd1kBoINEQEVBuv+uFtcaTxAhX27bT0wd13GOb2IOSDUXSA== + dependencies: + merge-options "^3.0.4" + "@react-native-camera-roll/camera-roll@^5.2.2": version "5.7.2" resolved "https://registry.yarnpkg.com/@react-native-camera-roll/camera-roll/-/camera-roll-5.7.2.tgz#db11525ae26c8a61630c424aebd323a7c784a921" @@ -4792,13 +4986,6 @@ prompts "^2.4.2" semver "^7.5.2" -"@react-native-community/datetimepicker@7.6.1": - version "7.6.1" - resolved "https://registry.yarnpkg.com/@react-native-community/datetimepicker/-/datetimepicker-7.6.1.tgz#98bdee01e3df490526ee1125e438c2030becac1f" - integrity sha512-g66Q2Kd9Uw3eRL7kkrTsGhi+eXxNoPDRFYH6z78sZQuYjPkUQgJDDMUYgBmaBsQx/fKMtemPrCj1ulGmyi0OSw== - dependencies: - invariant "^2.2.4" - "@react-native-community/eslint-config@^3.0.0": version "3.2.0" resolved "https://registry.yarnpkg.com/@react-native-community/eslint-config/-/eslint-config-3.2.0.tgz#42f677d5fff385bccf1be1d3b8faa8c086cf998d" @@ -8024,7 +8211,7 @@ resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz#a1337ca426aa61cef9fe15b5b28e340a72f6fa99" integrity sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw== -"@xmldom/xmldom@~0.7.7": +"@xmldom/xmldom@~0.7.0", "@xmldom/xmldom@~0.7.7": version "0.7.13" resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.7.13.tgz#ff34942667a4e19a9f4a0996a76814daac364cf3" integrity sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g== @@ -11637,6 +11824,14 @@ expo-camera@~14.0.1: dependencies: invariant "^2.2.4" +expo-constants@^13.0.2: + version "13.2.4" + resolved "https://registry.yarnpkg.com/expo-constants/-/expo-constants-13.2.4.tgz#eab4a553f074b2c60ad7a158d3b82e3484a94606" + integrity sha512-Zobau8EuTk2GgafwkfGnWM6CmSLB7X8qnQXVuXe0nd3v92hfQUmRWGhJwH88uxXj3LrfqctM6PaJ8taG1vxfBw== + dependencies: + "@expo/config" "~7.0.0" + uuid "^3.3.2" + expo-constants@~15.4.0: version "15.4.1" resolved "https://registry.yarnpkg.com/expo-constants/-/expo-constants-15.4.1.tgz#f76f347cf687b6630e1e3b9a385a4e42771671a4" @@ -11686,6 +11881,13 @@ expo-dev-menu@4.5.3: expo-dev-menu-interface "1.7.2" semver "^7.5.3" +expo-device@~4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/expo-device/-/expo-device-4.1.1.tgz#5de94144113ffb7fa0f37fa3d70e452113954c10" + integrity sha512-It0SGtKcvzQSf+Co6zdPdB63zZvG2/rDolB1lqswMNKj03Y7KVU41s5tcQCqNczj7tmeN3CJy7A8YhYGKdb7gA== + dependencies: + ua-parser-js "^0.7.19" + expo-device@~5.9.2: version "5.9.2" resolved "https://registry.yarnpkg.com/expo-device/-/expo-device-5.9.2.tgz#697e96f52d213a141b6f265f1e274e9d5e98c92c" @@ -11751,6 +11953,14 @@ expo-keep-awake@~12.8.1: resolved "https://registry.yarnpkg.com/expo-keep-awake/-/expo-keep-awake-12.8.1.tgz#3c8df9d86c265741b5e7bdd36965aa0c6fc17df0" integrity sha512-P/VZFV02Rzgj13skMwH+ceGOGZSEdaUu5n7pCS3wThh2LppZjPJ7sBxUwyzeLa3DXEVUtwLZi+BiQ91wPwy9Gg== +expo-linking@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/expo-linking/-/expo-linking-6.2.2.tgz#b7e148068ae49fd9ad814428c16fdf7a236e8aca" + integrity sha512-FEe6lP4f7xFT/vjoHRG+tt6EPVtkEGaWNK1smpaUevmNdyCJKqW0PDB8o8sfG6y7fly8ULe8qg3HhKh5J7aqUQ== + dependencies: + expo-constants "~15.4.3" + invariant "^2.2.4" + expo-localization@~14.8.2: version "14.8.2" resolved "https://registry.yarnpkg.com/expo-localization/-/expo-localization-14.8.2.tgz#e0bbed2293265834d21a1c58d3a5f8d265bd04ae" @@ -14870,6 +15080,16 @@ js-queue@2.0.2: dependencies: easy-stack "^1.0.1" +js-sha256@^0.10.1: + version "0.10.1" + resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.10.1.tgz#b40104ba1368e823fdd5f41b66b104b15a0da60d" + integrity sha512-5obBtsz9301ULlsgggLg542s/jqtddfOpV5KJc4hajc9JV8GeY2gZHSVpYBn4nWqAUTJ9v+xwtbJ1mIBgIH5Vw== + +js-sha256@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.11.0.tgz#256a921d9292f7fe98905face82e367abaca9576" + integrity sha512-6xNlKayMZvds9h1Y1VWc0fQHQ82BxTXizWPEtEeGvmOUYpBRy4gbWroHLpzowe6xiQhHpelCQiE7HEdznyBL9Q== + js-sha256@^0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966" @@ -15054,7 +15274,7 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== -json5@^1.0.2: +json5@^1.0.1, json5@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== @@ -18350,11 +18570,23 @@ react-is@^17.0.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== +react-keyed-flatten-children@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/react-keyed-flatten-children/-/react-keyed-flatten-children-3.0.0.tgz#b6ad0bde437d3ab86c8af3a1902d164be2a29d67" + integrity sha512-tSH6gvOyQjt3qtjG+kU9sTypclL1672yjpVufcE3aHNM0FhvjBUQZqsb/awIux4zEuVC3k/DP4p0GdTT/QUt/Q== + dependencies: + react-is "^18.2.0" + react-native-appstate-hook@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/react-native-appstate-hook/-/react-native-appstate-hook-1.0.6.tgz#cbc16e7b89cfaea034cabd999f00e99053cabd06" integrity sha512-0hPVyf5yLxCSVrrNEuGqN1ZnSSj3Ye2gZex0NtcK/AHYwMc0rXWFNZjBKOoZSouspqu3hXBbQ6NOUSTzrME1AQ== +react-native-date-picker@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/react-native-date-picker/-/react-native-date-picker-4.4.0.tgz#fe5b6eb8d85a4a30b2991ada5169a30ce5023ead" + integrity sha512-Axx3byihwwhKRLRVjPAr/UaEysapkRcKmjjM8/05UaVm4Q0xDn2RFUcRdy1QAahhRcjLjlVYhepxvU5bdgy7ZQ== + react-native-dotenv@^3.3.1: version "3.4.9" resolved "https://registry.yarnpkg.com/react-native-dotenv/-/react-native-dotenv-3.4.9.tgz#621c5b0c1d0c5c7f569bfe5a1d804bec7885c010" @@ -18388,6 +18620,13 @@ react-native-gesture-handler@~2.14.0: lodash "^4.17.21" prop-types "^15.7.2" +react-native-get-random-values@^1.6.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/react-native-get-random-values/-/react-native-get-random-values-1.10.0.tgz#c2c5f12a4ef8b1175145347b4a4b9f9a40d9ffc8" + integrity sha512-gZ1zbXhbb8+Jy9qYTV8c4Nf45/VB4g1jmXuavY5rPfUn7x3ok9Vl3FTl0dnE92Z4FFtfbUNNwtSfcmomdtWg+A== + dependencies: + fast-base64-decode "^1.0.0" + react-native-get-random-values@~1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/react-native-get-random-values/-/react-native-get-random-values-1.8.0.tgz#1cb4bd4bd3966a356e59697b8f372999fe97cb16" @@ -19861,6 +20100,49 @@ standard-as-callback@^2.1.0: resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45" integrity sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A== +statsig-js@4.45.1: + version "4.45.1" + resolved "https://registry.yarnpkg.com/statsig-js/-/statsig-js-4.45.1.tgz#b1f5b9c52adc4a8aece376fb011416c89227932f" + integrity sha512-h94RzFQsJCQCNwQXpZ9OBXcvCxDnkXF6OrCekd81ySvY2l4JSowpxMWX3Iw6IDFzfTfKdER9JQzFLhMSQbT+YQ== + dependencies: + js-sha256 "^0.10.1" + uuid "^8.3.2" + +statsig-js@4.49.0: + version "4.49.0" + resolved "https://registry.yarnpkg.com/statsig-js/-/statsig-js-4.49.0.tgz#8470a9ac218a93d36f4b7b306ff9377e48064740" + integrity sha512-N4drx6fzI168Q4NndFY3IJbSDqpWSBWvS290H/RnT/g3Et58SvtXzG5qqgzmqy4CwcmwH+IL8K15pL7hPnfvUQ== + dependencies: + js-sha256 "^0.11.0" + uuid "^8.3.2" + +statsig-react-native-expo@^4.6.1: + version "4.6.1" + resolved "https://registry.yarnpkg.com/statsig-react-native-expo/-/statsig-react-native-expo-4.6.1.tgz#0bdf49fee7112f7f28bff2405f4ba0c1727bb3d6" + integrity sha512-rB60c+WSrQPmjW9j75d+acUtwSOe38PE2KTDHiOv1Mf+0TCcFtGYlJmKCibWvbeXR7ZAyjjGeroh23bCSEZauQ== + dependencies: + "@react-native-async-storage/async-storage" "^1.15.2" + expo-constants "^13.0.2" + expo-device "~4.1.1" + js-sha256 "^0.9.0" + react-native-get-random-values "^1.6.0" + statsig-react "^1.21.1" + uuid "^8.3.2" + +statsig-react@^1.21.1: + version "1.35.0" + resolved "https://registry.yarnpkg.com/statsig-react/-/statsig-react-1.35.0.tgz#ad5730b83f564c640623e954fcbcbe848e939946" + integrity sha512-KLN7dhq6FvAl25Z0QN6IINFBgM3yn0GMafoE698tYZqRf911xvevFaR7qUXiTz3W9vmFYrmFRouqVMfCv7DW0A== + dependencies: + statsig-js "4.45.1" + +statsig-react@^1.36.0: + version "1.36.0" + resolved "https://registry.yarnpkg.com/statsig-react/-/statsig-react-1.36.0.tgz#c2171268a6c76eee534849ec9556b836baba04b6" + integrity sha512-QcTHla3ypfn2RvrnHGNlqWbiC2W/ZjcMM5LT6ExNV4skH7Xhspto3dMS3JVzBhOb74OEDZK4DbxQj9Wdz6XW0w== + dependencies: + statsig-js "4.49.0" + statuses@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" @@ -20805,6 +21087,11 @@ typescript@^5.3.3: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== +ua-parser-js@^0.7.19: + version "0.7.37" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.37.tgz#e464e66dac2d33a7a1251d7d7a99d6157ec27832" + integrity sha512-xV8kqRKM+jhMvcHWUKthV9fNebIzrNy//2O9ZwWcfiBFR5f25XVZPLlEajk/sf3Ra15V92isyQqnIEXRDaZWEA== + ua-parser-js@^0.7.33: version "0.7.35" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.35.tgz#8bda4827be4f0b1dda91699a29499575a1f1d307" @@ -21086,7 +21373,7 @@ utils-merge@1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== -uuid@^3.0.1: +uuid@^3.0.1, uuid@^3.3.2: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== @@ -21838,6 +22125,14 @@ xml-name-validator@^4.0.0: resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835" integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw== +xml2js@0.4.23: + version "0.4.23" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" + integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + xml2js@0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.0.tgz#07afc447a97d2bd6507a1f76eeadddb09f7a8282"