Merge remote-tracking branch 'origin/main' into next/base
* origin/main: (39 commits) Revert "fix quote & feed padding not being pressable (#7694)" (#7733) Nightly source-language update Add dev mode for easy copying of at:// URIs and DIDs (#7723) Improved search language select (#7591) Improved search page (#7590) Animate drawer menu on mobile web (#7711) Special treatment for recommended starter packs (#7706) invert new postonboarding gate (#7695) Animate dropdown menus (#7704) Better animations for dialogs, animate web composer (#7703) fix quote & feed padding not being pressable (#7694) ungate trending (#7696) run prettier (#7727) Nightly source-language update Add deploy key to nightly commit (#7722) [APP-1031] Add new followerRule to threadgate settings (#7681) Fix bug in GH action nightly-update-source-languages.yaml More i18n process updates (#7720) Run intl:extract on english to see if crowdin picks up on the changes Refine accessibilityHint (#7554) ...
This commit is contained in:
@@ -0,0 +1,38 @@
|
|||||||
|
name: Nightly Update Source Languages
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 2 * * *' # run at 2 AM UTC
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
extract-languages:
|
||||||
|
name: Nightly Update Source Languages
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
# Give the default GITHUB_TOKEN write permission to commit and push the
|
||||||
|
# added or changed files to the repository.
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check out Git repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
ssh-key: ${{secrets.GH_ACTION_DEPLOY_KEY}}
|
||||||
|
- name: Install node
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version-file: .nvmrc
|
||||||
|
- name: Yarn install
|
||||||
|
uses: Wandalen/wretry.action@master
|
||||||
|
with:
|
||||||
|
command: yarn --frozen-lockfile
|
||||||
|
attempt_limit: 3
|
||||||
|
attempt_delay: 2000
|
||||||
|
- name: Extract language strings
|
||||||
|
run: yarn intl:extract
|
||||||
|
- name: Create commit
|
||||||
|
uses: stefanzweifel/git-auto-commit-action@v5
|
||||||
|
with:
|
||||||
|
commit_message: Nightly source-language update
|
||||||
|
file_pattern: ./src/locale/locales/en/messages.po
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import {IsValidHandle, validateServiceHandle} from '#/lib/strings/handles'
|
||||||
|
|
||||||
|
describe('handle validation', () => {
|
||||||
|
const valid = [
|
||||||
|
['ali', 'bsky.social'],
|
||||||
|
['alice', 'bsky.social'],
|
||||||
|
['a-lice', 'bsky.social'],
|
||||||
|
['a-----lice', 'bsky.social'],
|
||||||
|
['123', 'bsky.social'],
|
||||||
|
['123456789012345678', 'bsky.social'],
|
||||||
|
['alice', 'custom-pds.com'],
|
||||||
|
['alice', 'my-custom-pds-with-long-name.social'],
|
||||||
|
['123456789012345678', 'my-custom-pds-with-long-name.social'],
|
||||||
|
]
|
||||||
|
it.each(valid)(`should be valid: %s.%s`, (handle, service) => {
|
||||||
|
const result = validateServiceHandle(handle, service)
|
||||||
|
expect(result.overall).toEqual(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
const invalid = [
|
||||||
|
['al', 'bsky.social', 'frontLength'],
|
||||||
|
['-alice', 'bsky.social', 'hyphenStartOrEnd'],
|
||||||
|
['alice-', 'bsky.social', 'hyphenStartOrEnd'],
|
||||||
|
['%%%', 'bsky.social', 'handleChars'],
|
||||||
|
['1234567890123456789', 'bsky.social', 'frontLength'],
|
||||||
|
[
|
||||||
|
'1234567890123456789',
|
||||||
|
'my-custom-pds-with-long-name.social',
|
||||||
|
'frontLength',
|
||||||
|
],
|
||||||
|
['al', 'my-custom-pds-with-long-name.social', 'frontLength'],
|
||||||
|
['a'.repeat(300), 'toolong.com', 'totalLength'],
|
||||||
|
] satisfies [string, string, keyof IsValidHandle][]
|
||||||
|
it.each(invalid)(
|
||||||
|
`should be invalid: %s.%s due to %s`,
|
||||||
|
(handle, service, expectedError) => {
|
||||||
|
const result = validateServiceHandle(handle, service)
|
||||||
|
expect(result.overall).toEqual(false)
|
||||||
|
expect(result[expectedError]).toEqual(false)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
@@ -86,6 +86,7 @@ module.exports = function (config) {
|
|||||||
'gl',
|
'gl',
|
||||||
'hi',
|
'hi',
|
||||||
'hu',
|
'hu',
|
||||||
|
'ia',
|
||||||
'id',
|
'id',
|
||||||
'it',
|
'it',
|
||||||
'ja',
|
'ja',
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M11.293 4.293a1 1 0 0 1 1.414 0l4 4a1 1 0 0 1-1.414 1.414L12 6.414 8.707 9.707a1 1 0 0 1-1.414-1.414l4-4Zm-4 10a1 1 0 0 1 1.414 0L12 17.586l3.293-3.293a1 1 0 0 1 1.414 1.414l-4 4a1 1 0 0 1-1.414 0l-4-4a1 1 0 0 1 0-1.414Z" clip-rule="evenodd"/></svg>
|
||||||
|
After Width: | Height: | Size: 363 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M7 2a1 1 0 0 1 1 1v2a1 1 0 0 1-2 0V3a1 1 0 0 1 1-1Zm4 0a1 1 0 0 1 1 1v2a1 1 0 1 1-2 0V3a1 1 0 0 1 1-1Zm4 0a1 1 0 0 1 1 1v2a1 1 0 1 1-2 0V3a1 1 0 0 1 1-1ZM4 9a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2h.5a3.5 3.5 0 1 1 0 7H18v4a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V9Zm12 0H6v11h10V9Zm2 5h.5a1.5 1.5 0 0 0 0-3H18v3Z" clip-rule="evenodd"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 437 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M6.5 4.999Zm0 0a.1.1 0 0 1-.016.024.2.2 0 0 1-.152.043q.086.014.168.032V7.5a1 1 0 0 1-.33.742c-.543.49-.917 1.176-1.23 2.036a1 1 0 0 1-.94.657H3V14h1a1 1 0 0 1 .866.5c.436.754.879 1.195 1.637 1.636A1 1 0 0 1 7 17v2h2a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2h2v-2.537a1 1 0 0 1 .332-.744A4.98 4.98 0 0 0 19 11.999 5 5 0 0 0 14 7H9.474a1 1 0 0 1-.893-.55v-.001l-.001-.002-.005-.008L9.474 6l-.9.438h.001v.002l.002.001.001.003.002.003v.003a2.6 2.6 0 0 0-.443-.538c-.319-.298-.839-.648-1.637-.814V5Zm2.082 1.452ZM9.5 4.447c.211.196.379.387.508.553H14a7 7 0 0 1 6.72 8.96 1.003 1.003 0 0 0 1.146-1.46 1 1 0 1 1 1.731-1 3 3 0 0 1-3.714 4.286A7 7 0 0 1 19 16.888V19a2 2 0 0 1-2 2h-2a2 2 0 0 1-2-2h-2a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v-1.45A5.8 5.8 0 0 1 3.448 16H3a2 2 0 0 1-2-2v-3.065a2 2 0 0 1 2-2h.324c.286-.649.657-1.291 1.176-1.852V5c0-1.047.89-2.12 2.161-1.907 1.33.223 2.248.805 2.839 1.354ZM8.25 12a1.25 1.25 0 1 0 0-2.5 1.25 1.25 0 0 0 0 2.5Z" clip-rule="evenodd"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.0 KiB |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#000" fill-rule="evenodd" d="M12 4c0-1.012.894-2.187 2.237-1.846a5.002 5.002 0 0 1 3.218 7.119 4 4 0 0 1 2.345 4.976A3.501 3.501 0 0 1 18.5 21h-13a3.5 3.5 0 0 1-1.3-6.75 4 4 0 0 1 2.052-4.848A4 4 0 0 1 10 4h2.001Zm-4.187 7.009A2 2 0 0 0 6 13c0 .366.098.706.271 1H12a1 1 0 1 1 0 2H5.5a1.5 1.5 0 0 0 0 3h13a1.5 1.5 0 1 0 0-3H17a1 1 0 1 1 0-2h.729A1.96 1.96 0 0 0 18 13a2 2 0 0 0-2-2h-2a1 1 0 1 1 0-2h1.236a3.002 3.002 0 0 0-1.243-4.832A2 2 0 0 1 12 6h-2a2 2 0 0 0-1.728 3.009H9a1 1 0 0 1 0 2H7.813Z" clip-rule="evenodd"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 610 B |
+20
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"project_id": "664276",
|
||||||
|
"base_path": ".",
|
||||||
|
"preserve_hierarchy": true,
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"source": "/src/locale/locales/en/messages.po",
|
||||||
|
"translation": "/src/locale/locales/%two_letters_code%/messages.po",
|
||||||
|
"languages_mapping": {
|
||||||
|
"two_letters_code": {
|
||||||
|
"pt-BR": "pt-BR",
|
||||||
|
"en-GB": "en-GB",
|
||||||
|
"zh-CN": "zh-CN",
|
||||||
|
"zh-TW": "zh-TW",
|
||||||
|
"zh-HK": "zh-HK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
+57
-7
@@ -3,9 +3,64 @@
|
|||||||
We want the official Bluesky app to be supported in as many languages as possible. If you want to help us translate the app, please open a PR or issue on the [Bluesky app repo on GitHub](https://github.com/bluesky-social/social-app)
|
We want the official Bluesky app to be supported in as many languages as possible. If you want to help us translate the app, please open a PR or issue on the [Bluesky app repo on GitHub](https://github.com/bluesky-social/social-app)
|
||||||
|
|
||||||
## Tools
|
## Tools
|
||||||
We are using Lingui to manage translations. You can find the documentation [here](https://lingui.dev/).
|
|
||||||
|
- We use Lingui to implement translations. You can find the documentation [here](https://lingui.dev/).
|
||||||
|
- We use Crowdin to manage translations.
|
||||||
|
- Bluesky Crowdin: https://crowdin.com/project/bluesky-social
|
||||||
|
- Introduction to Crowdin: https://support.crowdin.com/for-translators/
|
||||||
|
|
||||||
|
## Translators
|
||||||
|
|
||||||
|
Much of the app is translated by community contributions. (We <3 our translators!) If you want to participate in the translation of the app, read this section.
|
||||||
|
|
||||||
|
### Using Crowdin
|
||||||
|
|
||||||
|
[Crowdin](https://crowdin.com/project/bluesky-social) is our primary tool for managing translations. There are two roles:
|
||||||
|
|
||||||
|
- **Proof-readers**. Can create new translations and approve submitted translations.
|
||||||
|
- **Translators**. Can create new translations.
|
||||||
|
|
||||||
|
All translations must be approved by proof-readers before they are accepted into the app.
|
||||||
|
|
||||||
|
### Using other platforms
|
||||||
|
|
||||||
|
You may contribute PRs separately from Crowdin, however we strongly recommend using Crowdin to avoid conflicts.
|
||||||
|
|
||||||
|
### Code of conduct on Crowdin
|
||||||
|
|
||||||
|
Please treat everyone with respect. Proof-readers are given final say on translations. Translators who frequently come into conflict with other translators, or who contribute noticably incorrect translations, will have their membership to the Crowdin project revoked.
|
||||||
|
|
||||||
|
### Adding a new language
|
||||||
|
|
||||||
|
Create a new [Crowdin discussion](https://crowdin.com/project/bluesky-social/discussions) or [GitHub issue](https://github.com/bluesky-social/social-app/issues) requesting the new language be added to the project.
|
||||||
|
|
||||||
|
Please only request a new language when you are certain you will be able to contribute a substantive portion of translations for the language.
|
||||||
|
|
||||||
|
## Maintainers
|
||||||
|
|
||||||
|
Install the [Crowdin CLI](https://crowdin.github.io/crowdin-cli/). You will need to [configure your API token](https://crowdin.github.io/crowdin-cli/configuration) to access the project.
|
||||||
|
|
||||||
|
### English source-file sync with Crowdin
|
||||||
|
|
||||||
|
Every night, a GitHub action will run `yarn intl:extract` to update the english `messages.po` file. This will be automatically synced with Crowdin. Crowdin should notify all subscribed users of new translations.
|
||||||
|
|
||||||
|
### Release process
|
||||||
|
|
||||||
|
1. Pull main and create a branch.
|
||||||
|
1. Run `yarn intl:pull` to fetch all translation updates from Crowdin.
|
||||||
|
1. Create a PR, ensure the translations all look correct, and merge.
|
||||||
|
1. If needed:
|
||||||
|
1. Merge all approved translation PRs (contributions from outside crowdin).
|
||||||
|
1. Run `yarn intl:push` to sync Crowdin with the state of the repo.
|
||||||
|
|
||||||
|
### Testing the translations in Crowdin
|
||||||
|
|
||||||
|
You can run `yarn intl:pull` to pull the currently-approved translations from Crowdin.
|
||||||
|
|
||||||
|
## Developers
|
||||||
|
|
||||||
### Adding new strings
|
### Adding new strings
|
||||||
|
|
||||||
When adding a new string, do it as follows:
|
When adding a new string, do it as follows:
|
||||||
```jsx
|
```jsx
|
||||||
// Before
|
// Before
|
||||||
@@ -61,6 +116,7 @@ So the workflow is as follows:
|
|||||||
6. Enjoy translated app!
|
6. Enjoy translated app!
|
||||||
|
|
||||||
### Common pitfalls
|
### Common pitfalls
|
||||||
|
|
||||||
These pitfalls are memoization pitfalls that will cause the components to not re-render when the locale is changed -- causing stale translations to be shown.
|
These pitfalls are memoization pitfalls that will cause the components to not re-render when the locale is changed -- causing stale translations to be shown.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
@@ -111,9 +167,3 @@ export function Welcome() {
|
|||||||
return <div>{welcome}</div>;
|
return <div>{welcome}</div>;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Credits
|
|
||||||
Please check each individual `messages.po` file for the credits of the translators. We are very grateful for their help!
|
|
||||||
|
|
||||||
If you would like to translate the Bluesky app into your language, please open a PR or issue on this repo.
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ module.exports = {
|
|||||||
'gl',
|
'gl',
|
||||||
'hi',
|
'hi',
|
||||||
'hu',
|
'hu',
|
||||||
|
'ia',
|
||||||
'id',
|
'id',
|
||||||
'it',
|
'it',
|
||||||
'ja',
|
'ja',
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ import {MessagesScreen} from '#/screens/Messages/ChatList'
|
|||||||
import {MessagesConversationScreen} from '#/screens/Messages/Conversation'
|
import {MessagesConversationScreen} from '#/screens/Messages/Conversation'
|
||||||
import {MessagesSettingsScreen} from '#/screens/Messages/Settings'
|
import {MessagesSettingsScreen} from '#/screens/Messages/Settings'
|
||||||
import {ModerationScreen} from '#/screens/Moderation'
|
import {ModerationScreen} from '#/screens/Moderation'
|
||||||
|
import {Screen as ModerationInteractionSettings} from '#/screens/ModerationInteractionSettings'
|
||||||
import {PostLikedByScreen} from '#/screens/Post/PostLikedBy'
|
import {PostLikedByScreen} from '#/screens/Post/PostLikedBy'
|
||||||
import {PostQuotesScreen} from '#/screens/Post/PostQuotes'
|
import {PostQuotesScreen} from '#/screens/Post/PostQuotes'
|
||||||
import {PostRepostedByScreen} from '#/screens/Post/PostRepostedBy'
|
import {PostRepostedByScreen} from '#/screens/Post/PostRepostedBy'
|
||||||
@@ -155,6 +156,14 @@ function commonScreens(Stack: typeof HomeTab, unreadCountLabel?: string) {
|
|||||||
getComponent={() => ModerationBlockedAccounts}
|
getComponent={() => ModerationBlockedAccounts}
|
||||||
options={{title: title(msg`Blocked Accounts`), requireAuth: true}}
|
options={{title: title(msg`Blocked Accounts`), requireAuth: true}}
|
||||||
/>
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="ModerationInteractionSettings"
|
||||||
|
getComponent={() => ModerationInteractionSettings}
|
||||||
|
options={{
|
||||||
|
title: title(msg`Post Interaction Settings`),
|
||||||
|
requireAuth: true,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name="Settings"
|
name="Settings"
|
||||||
getComponent={() => SettingsScreen}
|
getComponent={() => SettingsScreen}
|
||||||
|
|||||||
+35
-2
@@ -50,6 +50,12 @@ export const atoms = {
|
|||||||
overflow_hidden: {
|
overflow_hidden: {
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* @platform web
|
||||||
|
*/
|
||||||
|
overflow_auto: web({
|
||||||
|
overflow: 'auto',
|
||||||
|
}),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Width
|
* Width
|
||||||
@@ -68,7 +74,6 @@ export const atoms = {
|
|||||||
* Used for the outermost components on screens, to ensure that they can fill
|
* Used for the outermost components on screens, to ensure that they can fill
|
||||||
* the screen and extend beyond.
|
* the screen and extend beyond.
|
||||||
*/
|
*/
|
||||||
// @ts-ignore - web only minHeight string
|
|
||||||
util_screen_outer: [
|
util_screen_outer: [
|
||||||
web({
|
web({
|
||||||
minHeight: '100vh',
|
minHeight: '100vh',
|
||||||
@@ -76,7 +81,7 @@ export const atoms = {
|
|||||||
native({
|
native({
|
||||||
height: '100%',
|
height: '100%',
|
||||||
}),
|
}),
|
||||||
] as ViewStyle,
|
] as StyleProp<ViewStyle>,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Theme-independent bg colors
|
* Theme-independent bg colors
|
||||||
@@ -965,6 +970,34 @@ export const atoms = {
|
|||||||
transitionDelay: '50ms',
|
transitionDelay: '50ms',
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Animaations
|
||||||
|
*/
|
||||||
|
fade_in: web({
|
||||||
|
animation: 'fadeIn ease-out 0.15s',
|
||||||
|
}),
|
||||||
|
fade_out: web({
|
||||||
|
animation: 'fadeOut ease-out 0.15s',
|
||||||
|
}),
|
||||||
|
zoom_in: web({
|
||||||
|
animation: 'zoomIn ease-out 0.1s',
|
||||||
|
}),
|
||||||
|
zoom_out: web({
|
||||||
|
animation: 'zoomOut ease-out 0.1s',
|
||||||
|
}),
|
||||||
|
slide_in_left: web({
|
||||||
|
// exponential easing function
|
||||||
|
animation: 'slideInLeft cubic-bezier(0.16, 1, 0.3, 1) 0.5s',
|
||||||
|
}),
|
||||||
|
slide_out_left: web({
|
||||||
|
animation: 'slideOutLeft ease-in 0.15s',
|
||||||
|
animationFillMode: 'forwards',
|
||||||
|
}),
|
||||||
|
// special composite animation for dialogs
|
||||||
|
zoom_fade_in: web({
|
||||||
|
animation: 'zoomIn ease-out 0.1s, fadeIn ease-out 0.1s',
|
||||||
|
}),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link Layout.SCROLLBAR_OFFSET}
|
* {@link Layout.SCROLLBAR_OFFSET}
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {FocusScope} from '@radix-ui/react-focus-scope'
|
|||||||
import {RemoveScrollBar} from 'react-remove-scroll-bar'
|
import {RemoveScrollBar} from 'react-remove-scroll-bar'
|
||||||
|
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
|
import {useA11y} from '#/state/a11y'
|
||||||
import {useDialogStateControlContext} from '#/state/dialogs'
|
import {useDialogStateControlContext} from '#/state/dialogs'
|
||||||
import {atoms as a, flatten, useBreakpoints, useTheme, web} from '#/alf'
|
import {atoms as a, flatten, useBreakpoints, useTheme, web} from '#/alf'
|
||||||
import {Button, ButtonIcon} from '#/components/Button'
|
import {Button, ButtonIcon} from '#/components/Button'
|
||||||
@@ -152,6 +153,7 @@ export function Inner({
|
|||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {close} = React.useContext(Context)
|
const {close} = React.useContext(Context)
|
||||||
const {gtMobile} = useBreakpoints()
|
const {gtMobile} = useBreakpoints()
|
||||||
|
const {reduceMotionEnabled} = useA11y()
|
||||||
useFocusGuards()
|
useFocusGuards()
|
||||||
return (
|
return (
|
||||||
<FocusScope loop asChild trapped>
|
<FocusScope loop asChild trapped>
|
||||||
@@ -161,7 +163,7 @@ export function Inner({
|
|||||||
aria-label={label}
|
aria-label={label}
|
||||||
aria-labelledby={accessibilityLabelledBy}
|
aria-labelledby={accessibilityLabelledBy}
|
||||||
aria-describedby={accessibilityDescribedBy}
|
aria-describedby={accessibilityDescribedBy}
|
||||||
// @ts-ignore web only -prf
|
// @ts-expect-error web only -prf
|
||||||
onClick={stopPropagation}
|
onClick={stopPropagation}
|
||||||
onStartShouldSetResponder={_ => true}
|
onStartShouldSetResponder={_ => true}
|
||||||
onTouchEnd={stopPropagation}
|
onTouchEnd={stopPropagation}
|
||||||
@@ -177,10 +179,9 @@ export function Inner({
|
|||||||
shadowColor: t.palette.black,
|
shadowColor: t.palette.black,
|
||||||
shadowOpacity: t.name === 'light' ? 0.1 : 0.4,
|
shadowOpacity: t.name === 'light' ? 0.1 : 0.4,
|
||||||
shadowRadius: 30,
|
shadowRadius: 30,
|
||||||
// @ts-ignore web only
|
|
||||||
animation: 'fadeIn ease-out 0.1s',
|
|
||||||
},
|
},
|
||||||
flatten(style),
|
!reduceMotionEnabled && a.zoom_fade_in,
|
||||||
|
style,
|
||||||
])}>
|
])}>
|
||||||
<DismissableLayer
|
<DismissableLayer
|
||||||
onInteractOutside={preventDefault}
|
onInteractOutside={preventDefault}
|
||||||
@@ -216,7 +217,7 @@ export const InnerFlatList = React.forwardRef<
|
|||||||
style={[
|
style={[
|
||||||
a.overflow_hidden,
|
a.overflow_hidden,
|
||||||
a.px_0,
|
a.px_0,
|
||||||
// @ts-ignore web only -sfn
|
// @ts-expect-error web only -sfn
|
||||||
{maxHeight: 'calc(-36px + 100vh)'},
|
{maxHeight: 'calc(-36px + 100vh)'},
|
||||||
webInnerStyle,
|
webInnerStyle,
|
||||||
]}
|
]}
|
||||||
@@ -262,20 +263,15 @@ export function Handle() {
|
|||||||
|
|
||||||
function Backdrop() {
|
function Backdrop() {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
|
const {reduceMotionEnabled} = useA11y()
|
||||||
return (
|
return (
|
||||||
<View
|
<View style={{opacity: 0.8}}>
|
||||||
style={{
|
|
||||||
opacity: 0.8,
|
|
||||||
}}>
|
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
a.fixed,
|
a.fixed,
|
||||||
a.inset_0,
|
a.inset_0,
|
||||||
{
|
{backgroundColor: t.palette.black},
|
||||||
backgroundColor: t.palette.black,
|
!reduceMotionEnabled && a.fade_in,
|
||||||
// @ts-ignore web only
|
|
||||||
animation: 'fadeIn ease-out 0.15s',
|
|
||||||
},
|
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import {createContext, useCallback, useContext} from 'react'
|
import {createContext, useCallback, useContext} from 'react'
|
||||||
import {GestureResponderEvent, View} from 'react-native'
|
import {GestureResponderEvent, Keyboard, View} from 'react-native'
|
||||||
import {msg} from '@lingui/macro'
|
import {msg} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {useNavigation} from '@react-navigation/native'
|
import {useNavigation} from '@react-navigation/native'
|
||||||
@@ -140,6 +140,7 @@ export function MenuButton() {
|
|||||||
const {gtMobile} = useBreakpoints()
|
const {gtMobile} = useBreakpoints()
|
||||||
|
|
||||||
const onPress = useCallback(() => {
|
const onPress = useCallback(() => {
|
||||||
|
Keyboard.dismiss()
|
||||||
setDrawerOpen(true)
|
setDrawerOpen(true)
|
||||||
}, [setDrawerOpen])
|
}, [setDrawerOpen])
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {msg} from '@lingui/macro'
|
|||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
|
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
|
||||||
|
|
||||||
|
import {useA11y} from '#/state/a11y'
|
||||||
import {atoms as a, flatten, useTheme, web} from '#/alf'
|
import {atoms as a, flatten, useTheme, web} from '#/alf'
|
||||||
import * as Dialog from '#/components/Dialog'
|
import * as Dialog from '#/components/Dialog'
|
||||||
import {useInteractionState} from '#/components/hooks/useInteractionState'
|
import {useInteractionState} from '#/components/hooks/useInteractionState'
|
||||||
@@ -177,10 +178,16 @@ export function Outer({
|
|||||||
style?: StyleProp<ViewStyle>
|
style?: StyleProp<ViewStyle>
|
||||||
}>) {
|
}>) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
|
const {reduceMotionEnabled} = useA11y()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu.Portal>
|
<DropdownMenu.Portal>
|
||||||
<DropdownMenu.Content sideOffset={5} loop aria-label="Test">
|
<DropdownMenu.Content
|
||||||
|
sideOffset={5}
|
||||||
|
collisionPadding={{left: 5, right: 5, bottom: 5}}
|
||||||
|
loop
|
||||||
|
aria-label="Test"
|
||||||
|
className="dropdown-menu-transform-origin">
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
a.rounded_sm,
|
a.rounded_sm,
|
||||||
@@ -189,6 +196,8 @@ export function Outer({
|
|||||||
t.name === 'light' ? t.atoms.bg : t.atoms.bg_contrast_25,
|
t.name === 'light' ? t.atoms.bg : t.atoms.bg_contrast_25,
|
||||||
t.atoms.shadow_md,
|
t.atoms.shadow_md,
|
||||||
t.atoms.border_contrast_low,
|
t.atoms.border_contrast_low,
|
||||||
|
a.overflow_auto,
|
||||||
|
!reduceMotionEnabled && a.zoom_fade_in,
|
||||||
style,
|
style,
|
||||||
]}>
|
]}>
|
||||||
{children}
|
{children}
|
||||||
@@ -373,9 +382,8 @@ export function Divider() {
|
|||||||
style={flatten([
|
style={flatten([
|
||||||
a.my_xs,
|
a.my_xs,
|
||||||
t.atoms.bg_contrast_100,
|
t.atoms.bg_contrast_100,
|
||||||
{
|
a.flex_shrink_0,
|
||||||
height: 1,
|
{height: 1},
|
||||||
},
|
|
||||||
])}
|
])}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -762,7 +762,7 @@ function SearchInput({
|
|||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
autoCapitalize="none"
|
autoCapitalize="none"
|
||||||
accessibilityLabel={_(msg`Search profiles`)}
|
accessibilityLabel={_(msg`Search profiles`)}
|
||||||
accessibilityHint={_(msg`Search profiles`)}
|
accessibilityHint={_(msg`Searches for profiles`)}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import {precacheResolvedUri} from '#/state/queries/resolve-uri'
|
|||||||
import {precacheStarterPack} from '#/state/queries/starter-packs'
|
import {precacheStarterPack} from '#/state/queries/starter-packs'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {StarterPack} from '#/components/icons/StarterPack'
|
import {StarterPack as StarterPackIcon} from '#/components/icons/StarterPack'
|
||||||
import {Link as BaseLink, LinkProps as BaseLinkProps} from '#/components/Link'
|
import {Link as BaseLink, LinkProps as BaseLinkProps} from '#/components/Link'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
import * as bsky from '#/types/bsky'
|
import * as bsky from '#/types/bsky'
|
||||||
@@ -70,7 +70,7 @@ export function Card({
|
|||||||
return (
|
return (
|
||||||
<View style={[a.w_full, a.gap_md]}>
|
<View style={[a.w_full, a.gap_md]}>
|
||||||
<View style={[a.flex_row, a.gap_sm, a.w_full]}>
|
<View style={[a.flex_row, a.gap_sm, a.w_full]}>
|
||||||
{!noIcon ? <StarterPack width={40} gradient="sky" /> : null}
|
{!noIcon ? <StarterPackIcon width={40} gradient="sky" /> : null}
|
||||||
<View style={[a.flex_1]}>
|
<View style={[a.flex_1]}>
|
||||||
<Text
|
<Text
|
||||||
emoji
|
emoji
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {PressableScale} from '#/lib/custom-animations/PressableScale'
|
|||||||
// import {UserAvatar} from '#/view/com/util/UserAvatar'
|
// import {UserAvatar} from '#/view/com/util/UserAvatar'
|
||||||
import type {TrendingTopic} from '#/state/queries/trending/useTrendingTopics'
|
import type {TrendingTopic} from '#/state/queries/trending/useTrendingTopics'
|
||||||
import {atoms as a, native, useTheme, ViewStyleProp} from '#/alf'
|
import {atoms as a, native, useTheme, ViewStyleProp} from '#/alf'
|
||||||
|
import {StarterPack as StarterPackIcon} from '#/components/icons/StarterPack'
|
||||||
import {Link as InternalLink, LinkProps} from '#/components/Link'
|
import {Link as InternalLink, LinkProps} from '#/components/Link'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
|
||||||
@@ -24,9 +25,8 @@ export function TrendingTopic({
|
|||||||
const topic = useTopic(raw)
|
const topic = useTopic(raw)
|
||||||
|
|
||||||
const isSmall = size === 'small'
|
const isSmall = size === 'small'
|
||||||
// const hasAvi = topic.type === 'feed' || topic.type === 'profile'
|
const hasIcon = topic.type === 'starter-pack' && !isSmall
|
||||||
// const aviSize = isSmall ? 16 : 20
|
const iconSize = 20
|
||||||
// const iconSize = isSmall ? 16 : 20
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
@@ -45,45 +45,47 @@ export function TrendingTopic({
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
: [a.py_sm, a.px_md],
|
: [a.py_sm, a.px_md],
|
||||||
|
hasIcon && {gap: 6},
|
||||||
style,
|
style,
|
||||||
/*
|
|
||||||
{
|
|
||||||
padding: 6,
|
|
||||||
gap: hasAvi ? 4 : 2,
|
|
||||||
},
|
|
||||||
a.pr_md,
|
|
||||||
*/
|
|
||||||
]}>
|
]}>
|
||||||
|
{hasIcon && topic.type === 'starter-pack' && (
|
||||||
|
<StarterPackIcon
|
||||||
|
gradient="sky"
|
||||||
|
width={iconSize}
|
||||||
|
style={{marginLeft: -3, marginVertical: -1}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{/*
|
{/*
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
a.align_center,
|
a.align_center,
|
||||||
a.justify_center,
|
a.justify_center,
|
||||||
a.rounded_full,
|
a.rounded_full,
|
||||||
a.overflow_hidden,
|
a.overflow_hidden,
|
||||||
{
|
{
|
||||||
width: aviSize,
|
width: iconSize,
|
||||||
height: aviSize,
|
height: iconSize,
|
||||||
},
|
},
|
||||||
]}>
|
]}>
|
||||||
{topic.type === 'tag' ? (
|
{topic.type === 'tag' ? (
|
||||||
<Hashtag width={iconSize} />
|
<Hashtag width={iconSize} />
|
||||||
) : topic.type === 'topic' ? (
|
) : topic.type === 'topic' ? (
|
||||||
<Quote width={iconSize - 2} />
|
<Quote width={iconSize - 2} />
|
||||||
) : topic.type === 'feed' ? (
|
) : topic.type === 'feed' ? (
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
type="user"
|
type="user"
|
||||||
size={aviSize}
|
size={aviSize}
|
||||||
avatar=""
|
avatar=""
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
type="user"
|
type="user"
|
||||||
size={aviSize}
|
size={aviSize}
|
||||||
avatar=""
|
avatar=""
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
*/}
|
*/}
|
||||||
|
|
||||||
<Text
|
<Text
|
||||||
@@ -151,7 +153,7 @@ export function TrendingTopicLink({
|
|||||||
|
|
||||||
type ParsedTrendingTopic =
|
type ParsedTrendingTopic =
|
||||||
| {
|
| {
|
||||||
type: 'topic' | 'tag' | 'unknown'
|
type: 'topic' | 'tag' | 'starter-pack' | 'unknown'
|
||||||
label: string
|
label: string
|
||||||
displayName: string
|
displayName: string
|
||||||
url: string
|
url: string
|
||||||
@@ -187,6 +189,14 @@ export function useTopic(raw: TrendingTopic): ParsedTrendingTopic {
|
|||||||
uri: undefined,
|
uri: undefined,
|
||||||
url: link,
|
url: link,
|
||||||
}
|
}
|
||||||
|
} else if (link.startsWith('/starter-pack')) {
|
||||||
|
return {
|
||||||
|
type: 'starter-pack',
|
||||||
|
label: _(msg`Browse starter pack ${displayName}`),
|
||||||
|
displayName,
|
||||||
|
uri: undefined,
|
||||||
|
url: link,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ export function VideoPostCard({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
accessibilityHint={_(msg`Tap to view video in immersive mode.`)}
|
accessibilityHint={_(msg`Views video in immersive mode`)}
|
||||||
label={_(msg`Video from ${author.handle}: ${text}`)}
|
label={_(msg`Video from ${author.handle}: ${text}`)}
|
||||||
to={{
|
to={{
|
||||||
screen: 'VideoFeed',
|
screen: 'VideoFeed',
|
||||||
|
|||||||
@@ -213,7 +213,12 @@ function Rules({
|
|||||||
a.flex_wrap,
|
a.flex_wrap,
|
||||||
t.atoms.text_contrast_medium,
|
t.atoms.text_contrast_medium,
|
||||||
]}>
|
]}>
|
||||||
{settings[0].type === 'everybody' ? (
|
{settings.length === 0 ? (
|
||||||
|
<Trans>
|
||||||
|
This post has an unknown type of threadgate on it. Your app may be
|
||||||
|
out of date.
|
||||||
|
</Trans>
|
||||||
|
) : settings[0].type === 'everybody' ? (
|
||||||
<Trans>Everybody can reply to this post.</Trans>
|
<Trans>Everybody can reply to this post.</Trans>
|
||||||
) : settings[0].type === 'nobody' ? (
|
) : settings[0].type === 'nobody' ? (
|
||||||
<Trans>Replies to this post are disabled.</Trans>
|
<Trans>Replies to this post are disabled.</Trans>
|
||||||
@@ -257,6 +262,19 @@ function Rule({
|
|||||||
if (rule.type === 'mention') {
|
if (rule.type === 'mention') {
|
||||||
return <Trans>mentioned users</Trans>
|
return <Trans>mentioned users</Trans>
|
||||||
}
|
}
|
||||||
|
if (rule.type === 'followers') {
|
||||||
|
return (
|
||||||
|
<Trans>
|
||||||
|
users following{' '}
|
||||||
|
<InlineLinkText
|
||||||
|
label={`@${post.author.handle}`}
|
||||||
|
to={makeProfileLink(post.author)}
|
||||||
|
style={[a.text_sm, a.leading_snug]}>
|
||||||
|
@{post.author.handle}
|
||||||
|
</InlineLinkText>
|
||||||
|
</Trans>
|
||||||
|
)
|
||||||
|
}
|
||||||
if (rule.type === 'following') {
|
if (rule.type === 'following') {
|
||||||
return (
|
return (
|
||||||
<Trans>
|
<Trans>
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import {Loader} from '#/components/Loader'
|
|||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
|
||||||
export type PostInteractionSettingsFormProps = {
|
export type PostInteractionSettingsFormProps = {
|
||||||
|
canSave?: boolean
|
||||||
onSave: () => void
|
onSave: () => void
|
||||||
isSaving?: boolean
|
isSaving?: boolean
|
||||||
|
|
||||||
@@ -58,20 +59,53 @@ export function PostInteractionSettingsControlledDialog({
|
|||||||
}: PostInteractionSettingsFormProps & {
|
}: PostInteractionSettingsFormProps & {
|
||||||
control: Dialog.DialogControlProps
|
control: Dialog.DialogControlProps
|
||||||
}) {
|
}) {
|
||||||
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog.Outer control={control}>
|
<Dialog.Outer control={control}>
|
||||||
<Dialog.Handle />
|
<Dialog.Handle />
|
||||||
<Dialog.ScrollableInner
|
<Dialog.ScrollableInner
|
||||||
label={_(msg`Edit post interaction settings`)}
|
label={_(msg`Edit post interaction settings`)}
|
||||||
style={[{maxWidth: 500}, a.w_full]}>
|
style={[{maxWidth: 500}, a.w_full]}>
|
||||||
<PostInteractionSettingsForm {...rest} />
|
<View style={[a.gap_md]}>
|
||||||
|
<Header />
|
||||||
|
<PostInteractionSettingsForm {...rest} />
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
a.pt_sm,
|
||||||
|
a.text_sm,
|
||||||
|
a.leading_snug,
|
||||||
|
t.atoms.text_contrast_medium,
|
||||||
|
]}>
|
||||||
|
<Trans>
|
||||||
|
You can set default interaction settings in{' '}
|
||||||
|
<Text style={[a.font_bold, t.atoms.text_contrast_medium]}>
|
||||||
|
Settings → Moderation → Interaction settings.
|
||||||
|
</Text>
|
||||||
|
</Trans>
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
<Dialog.Close />
|
<Dialog.Close />
|
||||||
</Dialog.ScrollableInner>
|
</Dialog.ScrollableInner>
|
||||||
</Dialog.Outer>
|
</Dialog.Outer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function Header() {
|
||||||
|
return (
|
||||||
|
<View style={[a.gap_md, a.pb_sm]}>
|
||||||
|
<Text style={[a.text_2xl, a.font_bold]}>
|
||||||
|
<Trans>Post interaction settings</Trans>
|
||||||
|
</Text>
|
||||||
|
<Text style={[a.text_md, a.pb_xs]}>
|
||||||
|
<Trans>Customize who can interact with this post.</Trans>
|
||||||
|
</Text>
|
||||||
|
<Divider />
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export type PostInteractionSettingsDialogProps = {
|
export type PostInteractionSettingsDialogProps = {
|
||||||
control: Dialog.DialogControlProps
|
control: Dialog.DialogControlProps
|
||||||
/**
|
/**
|
||||||
@@ -203,26 +237,31 @@ export function PostInteractionSettingsDialogControlledInner(
|
|||||||
<Dialog.ScrollableInner
|
<Dialog.ScrollableInner
|
||||||
label={_(msg`Edit post interaction settings`)}
|
label={_(msg`Edit post interaction settings`)}
|
||||||
style={[{maxWidth: 500}, a.w_full]}>
|
style={[{maxWidth: 500}, a.w_full]}>
|
||||||
{isLoading ? (
|
<View style={[a.gap_md]}>
|
||||||
<View style={[a.flex_1, a.py_4xl, a.align_center, a.justify_center]}>
|
<Header />
|
||||||
<Loader size="xl" />
|
|
||||||
</View>
|
{isLoading ? (
|
||||||
) : (
|
<View style={[a.flex_1, a.py_4xl, a.align_center, a.justify_center]}>
|
||||||
<PostInteractionSettingsForm
|
<Loader size="xl" />
|
||||||
replySettingsDisabled={!isThreadgateOwnedByViewer}
|
</View>
|
||||||
isSaving={isSaving}
|
) : (
|
||||||
onSave={onSave}
|
<PostInteractionSettingsForm
|
||||||
postgate={postgateValue}
|
replySettingsDisabled={!isThreadgateOwnedByViewer}
|
||||||
onChangePostgate={setEditedPostgate}
|
isSaving={isSaving}
|
||||||
threadgateAllowUISettings={allowUIValue}
|
onSave={onSave}
|
||||||
onChangeThreadgateAllowUISettings={setEditedAllowUISettings}
|
postgate={postgateValue}
|
||||||
/>
|
onChangePostgate={setEditedPostgate}
|
||||||
)}
|
threadgateAllowUISettings={allowUIValue}
|
||||||
|
onChangeThreadgateAllowUISettings={setEditedAllowUISettings}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
</Dialog.ScrollableInner>
|
</Dialog.ScrollableInner>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PostInteractionSettingsForm({
|
export function PostInteractionSettingsForm({
|
||||||
|
canSave = true,
|
||||||
onSave,
|
onSave,
|
||||||
isSaving,
|
isSaving,
|
||||||
postgate,
|
postgate,
|
||||||
@@ -283,17 +322,7 @@ export function PostInteractionSettingsForm({
|
|||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
<View style={[a.flex_1, a.gap_md]}>
|
<View style={[a.flex_1, a.gap_md]}>
|
||||||
<Text style={[a.text_2xl, a.font_bold]}>
|
|
||||||
<Trans>Post interaction settings</Trans>
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
<View style={[a.gap_lg]}>
|
<View style={[a.gap_lg]}>
|
||||||
<Text style={[a.text_md]}>
|
|
||||||
<Trans>Customize who can interact with this post.</Trans>
|
|
||||||
</Text>
|
|
||||||
|
|
||||||
<Divider />
|
|
||||||
|
|
||||||
<View style={[a.gap_sm]}>
|
<View style={[a.gap_sm]}>
|
||||||
<Text style={[a.font_bold, a.text_lg]}>
|
<Text style={[a.font_bold, a.text_lg]}>
|
||||||
<Trans>Quote settings</Trans>
|
<Trans>Quote settings</Trans>
|
||||||
@@ -400,7 +429,7 @@ export function PostInteractionSettingsForm({
|
|||||||
disabled={replySettingsDisabled}
|
disabled={replySettingsDisabled}
|
||||||
/>
|
/>
|
||||||
<Selectable
|
<Selectable
|
||||||
label={_(msg`Followed users`)}
|
label={_(msg`Users you follow`)}
|
||||||
isSelected={
|
isSelected={
|
||||||
!!threadgateAllowUISettings.find(
|
!!threadgateAllowUISettings.find(
|
||||||
v => v.type === 'following',
|
v => v.type === 'following',
|
||||||
@@ -409,6 +438,16 @@ export function PostInteractionSettingsForm({
|
|||||||
onPress={() => onPressAudience({type: 'following'})}
|
onPress={() => onPressAudience({type: 'following'})}
|
||||||
disabled={replySettingsDisabled}
|
disabled={replySettingsDisabled}
|
||||||
/>
|
/>
|
||||||
|
<Selectable
|
||||||
|
label={_(msg`Your followers`)}
|
||||||
|
isSelected={
|
||||||
|
!!threadgateAllowUISettings.find(
|
||||||
|
v => v.type === 'followers',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onPress={() => onPressAudience({type: 'followers'})}
|
||||||
|
disabled={replySettingsDisabled}
|
||||||
|
/>
|
||||||
{lists && lists.length > 0
|
{lists && lists.length > 0
|
||||||
? lists.map(list => (
|
? lists.map(list => (
|
||||||
<Selectable
|
<Selectable
|
||||||
@@ -435,6 +474,7 @@ export function PostInteractionSettingsForm({
|
|||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
disabled={!canSave || isSaving}
|
||||||
label={_(msg`Save`)}
|
label={_(msg`Save`)}
|
||||||
onPress={onSave}
|
onPress={onSave}
|
||||||
color="primary"
|
color="primary"
|
||||||
|
|||||||
@@ -506,7 +506,7 @@ function SearchInput({
|
|||||||
autoCapitalize="none"
|
autoCapitalize="none"
|
||||||
autoFocus
|
autoFocus
|
||||||
accessibilityLabel={_(msg`Search profiles`)}
|
accessibilityLabel={_(msg`Search profiles`)}
|
||||||
accessibilityHint={_(msg`Search profiles`)}
|
accessibilityHint={_(msg`Searches for profiles`)}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export function HostingProvider({
|
|||||||
</Text>
|
</Text>
|
||||||
<Button
|
<Button
|
||||||
label={toNiceDomain(serviceUrl)}
|
label={toNiceDomain(serviceUrl)}
|
||||||
accessibilityHint={_(msg`Press to change hosting provider`)}
|
accessibilityHint={_(msg`Changes hosting provider`)}
|
||||||
onPress={onPressSelectService}
|
onPress={onPressSelectService}
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
@@ -63,7 +63,7 @@ export function HostingProvider({
|
|||||||
<Button
|
<Button
|
||||||
testID="selectServiceButton"
|
testID="selectServiceButton"
|
||||||
label={toNiceDomain(serviceUrl)}
|
label={toNiceDomain(serviceUrl)}
|
||||||
accessibilityHint={_(msg`Press to change hosting provider`)}
|
accessibilityHint={_(msg`Changes hosting provider`)}
|
||||||
variant="solid"
|
variant="solid"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
style={[
|
style={[
|
||||||
|
|||||||
@@ -226,6 +226,7 @@ export function createInput(Component: typeof TextInput) {
|
|||||||
<>
|
<>
|
||||||
<Component
|
<Component
|
||||||
accessibilityHint={undefined}
|
accessibilityHint={undefined}
|
||||||
|
hitSlop={HITSLOP_20}
|
||||||
{...rest}
|
{...rest}
|
||||||
accessibilityLabel={label}
|
accessibilityLabel={label}
|
||||||
ref={refs}
|
ref={refs}
|
||||||
@@ -242,7 +243,6 @@ export function createInput(Component: typeof TextInput) {
|
|||||||
placeholder={placeholder || label}
|
placeholder={placeholder || label}
|
||||||
placeholderTextColor={t.palette.contrast_500}
|
placeholderTextColor={t.palette.contrast_500}
|
||||||
keyboardAppearance={t.name === 'light' ? 'light' : 'dark'}
|
keyboardAppearance={t.name === 'light' ? 'light' : 'dark'}
|
||||||
hitSlop={HITSLOP_20}
|
|
||||||
style={flattened}
|
style={flattened}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ const locales: Record<AppLanguage, Locale | undefined> = {
|
|||||||
gl,
|
gl,
|
||||||
hi,
|
hi,
|
||||||
hu,
|
hu,
|
||||||
|
ia: undefined,
|
||||||
id,
|
id,
|
||||||
it,
|
it,
|
||||||
ja,
|
ja,
|
||||||
|
|||||||
@@ -15,3 +15,7 @@ export const ChevronTop_Stroke2_Corner0_Rounded = createSinglePathSVG({
|
|||||||
export const ChevronBottom_Stroke2_Corner0_Rounded = createSinglePathSVG({
|
export const ChevronBottom_Stroke2_Corner0_Rounded = createSinglePathSVG({
|
||||||
path: 'M3.293 8.293a1 1 0 0 1 1.414 0L12 15.586l7.293-7.293a1 1 0 1 1 1.414 1.414l-8 8a1 1 0 0 1-1.414 0l-8-8a1 1 0 0 1 0-1.414Z',
|
path: 'M3.293 8.293a1 1 0 0 1 1.414 0L12 15.586l7.293-7.293a1 1 0 1 1 1.414 1.414l-8 8a1 1 0 0 1-1.414 0l-8-8a1 1 0 0 1 0-1.414Z',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const ChevronTopBottom_Stroke2_Corner0_Rounded = createSinglePathSVG({
|
||||||
|
path: 'M11.293 4.293a1 1 0 0 1 1.414 0l4 4a1 1 0 0 1-1.414 1.414L12 6.414 8.707 9.707a1 1 0 0 1-1.414-1.414l4-4Zm-4 10a1 1 0 0 1 1.414 0L12 17.586l3.293-3.293a1 1 0 0 1 1.414 1.414l-4 4a1 1 0 0 1-1.414 0l-4-4a1 1 0 0 1 0-1.414Z',
|
||||||
|
})
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
import {createSinglePathSVG} from './TEMPLATE'
|
|
||||||
|
|
||||||
export const Coffee_Stroke2_Corner0_Rounded = createSinglePathSVG({
|
|
||||||
path: 'M7 2a1 1 0 0 1 1 1v2a1 1 0 0 1-2 0V3a1 1 0 0 1 1-1Zm4 0a1 1 0 0 1 1 1v2a1 1 0 1 1-2 0V3a1 1 0 0 1 1-1Zm4 0a1 1 0 0 1 1 1v2a1 1 0 1 1-2 0V3a1 1 0 0 1 1-1ZM4 9a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2h.5a3.5 3.5 0 1 1 0 7H18v4a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V9Zm12 0H6v11h10V9Zm2 5h.5a1.5 1.5 0 0 0 0-3H18v3Z',
|
|
||||||
})
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
import {createSinglePathSVG} from './TEMPLATE'
|
|
||||||
|
|
||||||
export const PiggyBank_Stroke2_Corner0_Rounded = createSinglePathSVG({
|
|
||||||
path: 'M6.5 4.999Zm0 0a.054.054 0 0 1-.016.024.196.196 0 0 1-.152.043c.057.01.113.02.168.032V7.5a1 1 0 0 1-.33.742c-.543.49-.917 1.176-1.23 2.036a1 1 0 0 1-.94.657H3V14h1a1 1 0 0 1 .866.5c.436.754.879 1.195 1.637 1.636A1 1 0 0 1 7 17v2h2a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2h2v-2.537a1 1 0 0 1 .332-.744A4.978 4.978 0 0 0 19 11.999 5 5 0 0 0 14 7H9.474a1 1 0 0 1-.893-.55v-.001l-.001-.002-.005-.008L9.474 6l-.9.438h.001v.002l.002.001.001.003.002.003v.003a2.62 2.62 0 0 0-.443-.538c-.319-.298-.839-.648-1.637-.814V5Zm2.082 1.452ZM9.5 4.447c.211.196.379.387.508.553H14a7 7 0 0 1 6.72 8.96 1.003 1.003 0 0 0 1.146-1.46 1 1 0 1 1 1.731-1 3 3 0 0 1-3.714 4.286A7.074 7.074 0 0 1 19 16.888V19a2 2 0 0 1-2 2h-2a2 2 0 0 1-2-2h-2a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v-1.45A5.783 5.783 0 0 1 3.448 16H3a2 2 0 0 1-2-2v-3.065a2 2 0 0 1 2-2h.324c.286-.649.657-1.291 1.176-1.852V5c0-1.047.89-2.12 2.161-1.907 1.33.223 2.248.805 2.839 1.354ZM8.25 12a1.25 1.25 0 1 0 0-2.5 1.25 1.25 0 0 0 0 2.5Z',
|
|
||||||
})
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
import {createSinglePathSVG} from './TEMPLATE'
|
|
||||||
|
|
||||||
export const Poop_Stroke2_Corner0_Rounded = createSinglePathSVG({
|
|
||||||
path: 'M12 4c0-1.012.894-2.187 2.237-1.846a5.002 5.002 0 0 1 3.218 7.119 4.001 4.001 0 0 1 2.345 4.976A3.501 3.501 0 0 1 18.5 21h-13a3.5 3.5 0 0 1-1.3-6.75 4 4 0 0 1 2.052-4.848A4 4 0 0 1 10 4h2.001Zm-4.187 7.009A2 2 0 0 0 6 13c0 .366.098.706.271 1H12a1 1 0 1 1 0 2H5.5a1.5 1.5 0 0 0 0 3h13a1.5 1.5 0 1 0 0-3H17a1 1 0 1 1 0-2h.729c.173-.294.271-.634.271-1a2 2 0 0 0-2-2h-2a1 1 0 1 1 0-2h1.236a3.002 3.002 0 0 0-1.243-4.832A2 2 0 0 1 12 6h-2a2 2 0 0 0-1.728 3.009H9a1 1 0 0 1 0 2H7.813Z',
|
|
||||||
})
|
|
||||||
@@ -146,10 +146,10 @@ function ContentHiderActive({
|
|||||||
label={desc.name}
|
label={desc.name}
|
||||||
accessibilityHint={
|
accessibilityHint={
|
||||||
modui.noOverride
|
modui.noOverride
|
||||||
? _(msg`Learn more about the moderation applied to this content.`)
|
? _(msg`Learn more about the moderation applied to this content`)
|
||||||
: override
|
: override
|
||||||
? _(msg`Hide the content`)
|
? _(msg`Hides the content`)
|
||||||
: _(msg`Show the content`)
|
: _(msg`Shows the content`)
|
||||||
}>
|
}>
|
||||||
{state => (
|
{state => (
|
||||||
<View
|
<View
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ export function PostHider({
|
|||||||
}}
|
}}
|
||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
accessibilityHint={
|
accessibilityHint={
|
||||||
override ? _(msg`Hide the content`) : _(msg`Show the content`)
|
override ? _(msg`Hides the content`) : _(msg`Shows the content`)
|
||||||
}
|
}
|
||||||
accessibilityLabel=""
|
accessibilityLabel=""
|
||||||
style={[
|
style={[
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export type CommonNavigatorParams = {
|
|||||||
ModerationModlists: undefined
|
ModerationModlists: undefined
|
||||||
ModerationMutedAccounts: undefined
|
ModerationMutedAccounts: undefined
|
||||||
ModerationBlockedAccounts: undefined
|
ModerationBlockedAccounts: undefined
|
||||||
|
ModerationInteractionSettings: undefined
|
||||||
Settings: undefined
|
Settings: undefined
|
||||||
Profile: {name: string; hideBackButton?: boolean}
|
Profile: {name: string; hideBackButton?: boolean}
|
||||||
ProfileFollowers: {name: string}
|
ProfileFollowers: {name: string}
|
||||||
|
|||||||
@@ -25,3 +25,19 @@ export async function shareUrl(url: string) {
|
|||||||
Toast.show(t`Copied to clipboard`, 'clipboard-check')
|
Toast.show(t`Copied to clipboard`, 'clipboard-check')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function shares a text using the native Share API if available, or copies it to the clipboard
|
||||||
|
* and displays a toast message if not (mostly on web)
|
||||||
|
*
|
||||||
|
* @param {string} text - A string representing the text that needs to be shared or copied to the
|
||||||
|
* clipboard.
|
||||||
|
*/
|
||||||
|
export async function shareText(text: string) {
|
||||||
|
if (isAndroid || isIOS) {
|
||||||
|
await Share.share({message: text})
|
||||||
|
} else {
|
||||||
|
await setStringAsync(text)
|
||||||
|
Toast.show(t`Copied to clipboard`, 'clipboard-check')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,9 +2,8 @@ export type Gate =
|
|||||||
// Keep this alphabetic please.
|
// Keep this alphabetic please.
|
||||||
| 'debug_show_feedcontext'
|
| 'debug_show_feedcontext'
|
||||||
| 'debug_subscriptions'
|
| 'debug_subscriptions'
|
||||||
| 'new_postonboarding'
|
| 'old_postonboarding'
|
||||||
| 'onboarding_add_video_feed'
|
| 'onboarding_add_video_feed'
|
||||||
| 'remove_show_latest_button'
|
| 'remove_show_latest_button'
|
||||||
| 'test_gate_1'
|
| 'test_gate_1'
|
||||||
| 'test_gate_2'
|
| 'test_gate_2'
|
||||||
| 'trending_topics_beta'
|
|
||||||
|
|||||||
@@ -42,10 +42,9 @@ export interface IsValidHandle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// More checks from https://github.com/bluesky-social/atproto/blob/main/packages/pds/src/handle/index.ts#L72
|
// More checks from https://github.com/bluesky-social/atproto/blob/main/packages/pds/src/handle/index.ts#L72
|
||||||
export function validateHandle(
|
export function validateServiceHandle(
|
||||||
str: string,
|
str: string,
|
||||||
userDomain: string,
|
userDomain: string,
|
||||||
isServiceHandle?: boolean,
|
|
||||||
): IsValidHandle {
|
): IsValidHandle {
|
||||||
const fullHandle = createFullHandle(str, userDomain)
|
const fullHandle = createFullHandle(str, userDomain)
|
||||||
|
|
||||||
@@ -53,8 +52,8 @@ export function validateHandle(
|
|||||||
handleChars:
|
handleChars:
|
||||||
!str || (VALIDATE_REGEX.test(fullHandle) && !str.includes('.')),
|
!str || (VALIDATE_REGEX.test(fullHandle) && !str.includes('.')),
|
||||||
hyphenStartOrEnd: !str.startsWith('-') && !str.endsWith('-'),
|
hyphenStartOrEnd: !str.startsWith('-') && !str.endsWith('-'),
|
||||||
frontLength: str.length >= 3,
|
frontLength: str.length >= 3 && str.length <= 18,
|
||||||
totalLength: fullHandle.length <= (isServiceHandle ? 30 : 253),
|
totalLength: fullHandle.length <= 253,
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -185,6 +185,8 @@ export function sanitizeAppLanguageSetting(appLanguage: string): AppLanguage {
|
|||||||
return AppLanguage.hi
|
return AppLanguage.hi
|
||||||
case 'hu':
|
case 'hu':
|
||||||
return AppLanguage.hu
|
return AppLanguage.hu
|
||||||
|
case 'ia':
|
||||||
|
return AppLanguage.ia
|
||||||
case 'id':
|
case 'id':
|
||||||
return AppLanguage.id
|
return AppLanguage.id
|
||||||
case 'it':
|
case 'it':
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import {messages as messagesGa} from '#/locale/locales/ga/messages'
|
|||||||
import {messages as messagesGl} from '#/locale/locales/gl/messages'
|
import {messages as messagesGl} from '#/locale/locales/gl/messages'
|
||||||
import {messages as messagesHi} from '#/locale/locales/hi/messages'
|
import {messages as messagesHi} from '#/locale/locales/hi/messages'
|
||||||
import {messages as messagesHu} from '#/locale/locales/hu/messages'
|
import {messages as messagesHu} from '#/locale/locales/hu/messages'
|
||||||
|
import {messages as messagesIa} from '#/locale/locales/ia/messages'
|
||||||
import {messages as messagesId} from '#/locale/locales/id/messages'
|
import {messages as messagesId} from '#/locale/locales/id/messages'
|
||||||
import {messages as messagesIt} from '#/locale/locales/it/messages'
|
import {messages as messagesIt} from '#/locale/locales/it/messages'
|
||||||
import {messages as messagesJa} from '#/locale/locales/ja/messages'
|
import {messages as messagesJa} from '#/locale/locales/ja/messages'
|
||||||
@@ -173,6 +174,14 @@ export async function dynamicActivate(locale: AppLanguage) {
|
|||||||
])
|
])
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
case AppLanguage.id: {
|
||||||
|
i18n.loadAndActivate({locale, messages: messagesIa})
|
||||||
|
await Promise.all([
|
||||||
|
import('@formatjs/intl-pluralrules/locale-data/ia'),
|
||||||
|
import('@formatjs/intl-numberformat/locale-data/ia'),
|
||||||
|
])
|
||||||
|
break
|
||||||
|
}
|
||||||
case AppLanguage.id: {
|
case AppLanguage.id: {
|
||||||
i18n.loadAndActivate({locale, messages: messagesId})
|
i18n.loadAndActivate({locale, messages: messagesId})
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
|
|||||||
@@ -72,6 +72,10 @@ export async function dynamicActivate(locale: AppLanguage) {
|
|||||||
mod = await import(`./locales/hu/messages`)
|
mod = await import(`./locales/hu/messages`)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
case AppLanguage.ia: {
|
||||||
|
mod = await import(`./locales/ia/messages`)
|
||||||
|
break
|
||||||
|
}
|
||||||
case AppLanguage.id: {
|
case AppLanguage.id: {
|
||||||
mod = await import(`./locales/id/messages`)
|
mod = await import(`./locales/id/messages`)
|
||||||
break
|
break
|
||||||
|
|||||||
+13
-19
@@ -21,6 +21,7 @@ export enum AppLanguage {
|
|||||||
gl = 'gl',
|
gl = 'gl',
|
||||||
hi = 'hi',
|
hi = 'hi',
|
||||||
hu = 'hu',
|
hu = 'hu',
|
||||||
|
ia = 'ia',
|
||||||
id = 'id',
|
id = 'id',
|
||||||
it = 'it',
|
it = 'it',
|
||||||
ja = 'ja',
|
ja = 'ja',
|
||||||
@@ -64,6 +65,7 @@ export const APP_LANGUAGES: AppLanguageConfig[] = [
|
|||||||
{code2: AppLanguage.gl, name: 'Galego – Galician'},
|
{code2: AppLanguage.gl, name: 'Galego – Galician'},
|
||||||
{code2: AppLanguage.hi, name: 'हिंदी – Hindi'},
|
{code2: AppLanguage.hi, name: 'हिंदी – Hindi'},
|
||||||
{code2: AppLanguage.hu, name: 'magyar – Hungarian'},
|
{code2: AppLanguage.hu, name: 'magyar – Hungarian'},
|
||||||
|
{code2: AppLanguage.ia, name: 'Interlingua'},
|
||||||
{code2: AppLanguage.id, name: 'Bahasa Indonesia – Indonesian'},
|
{code2: AppLanguage.id, name: 'Bahasa Indonesia – Indonesian'},
|
||||||
{code2: AppLanguage.it, name: 'Italiano – Italian'},
|
{code2: AppLanguage.it, name: 'Italiano – Italian'},
|
||||||
{code2: AppLanguage.ja, name: '日本語 – Japanese'},
|
{code2: AppLanguage.ja, name: '日本語 – Japanese'},
|
||||||
@@ -177,11 +179,7 @@ export const LANGUAGES: Language[] = [
|
|||||||
{code3: 'cho', code2: '', name: 'Choctaw'},
|
{code3: 'cho', code2: '', name: 'Choctaw'},
|
||||||
{code3: 'chp', code2: '', name: 'Chipewyan; Dene Suline'},
|
{code3: 'chp', code2: '', name: 'Chipewyan; Dene Suline'},
|
||||||
{code3: 'chr', code2: '', name: 'Cherokee'},
|
{code3: 'chr', code2: '', name: 'Cherokee'},
|
||||||
{
|
{code3: 'chu', code2: 'cu', name: 'Church Slavic'},
|
||||||
code3: 'chu',
|
|
||||||
code2: 'cu',
|
|
||||||
name: 'Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic',
|
|
||||||
},
|
|
||||||
{code3: 'chv', code2: 'cv', name: 'Chuvash'},
|
{code3: 'chv', code2: 'cv', name: 'Chuvash'},
|
||||||
{code3: 'chy', code2: '', name: 'Cheyenne'},
|
{code3: 'chy', code2: '', name: 'Cheyenne'},
|
||||||
{code3: 'cmc', code2: '', name: 'Chamic languages'},
|
{code3: 'cmc', code2: '', name: 'Chamic languages'},
|
||||||
@@ -299,13 +297,9 @@ export const LANGUAGES: Language[] = [
|
|||||||
{code3: 'iii', code2: 'ii', name: 'Sichuan Yi; Nuosu'},
|
{code3: 'iii', code2: 'ii', name: 'Sichuan Yi; Nuosu'},
|
||||||
{code3: 'ijo', code2: '', name: 'Ijo languages'},
|
{code3: 'ijo', code2: '', name: 'Ijo languages'},
|
||||||
{code3: 'iku', code2: 'iu', name: 'Inuktitut'},
|
{code3: 'iku', code2: 'iu', name: 'Inuktitut'},
|
||||||
{code3: 'ile', code2: 'ie', name: 'Interlingue; Occidental'},
|
{code3: 'ile', code2: 'ie', name: 'Interlingue'},
|
||||||
{code3: 'ilo', code2: '', name: 'Iloko'},
|
{code3: 'ilo', code2: '', name: 'Iloko'},
|
||||||
{
|
{code3: 'ina', code2: 'ia', name: 'Interlingua'},
|
||||||
code3: 'ina',
|
|
||||||
code2: 'ia',
|
|
||||||
name: 'Interlingua (International Auxiliary Language Association)',
|
|
||||||
},
|
|
||||||
{code3: 'inc', code2: '', name: 'Indic languages'},
|
{code3: 'inc', code2: '', name: 'Indic languages'},
|
||||||
{code3: 'ind', code2: 'id', name: 'Indonesian'},
|
{code3: 'ind', code2: 'id', name: 'Indonesian'},
|
||||||
{code3: 'ine', code2: '', name: 'Indo-European languages'},
|
{code3: 'ine', code2: '', name: 'Indo-European languages'},
|
||||||
@@ -323,7 +317,7 @@ export const LANGUAGES: Language[] = [
|
|||||||
{code3: 'kaa', code2: '', name: 'Kara-Kalpak'},
|
{code3: 'kaa', code2: '', name: 'Kara-Kalpak'},
|
||||||
{code3: 'kab', code2: '', name: 'Kabyle'},
|
{code3: 'kab', code2: '', name: 'Kabyle'},
|
||||||
{code3: 'kac', code2: '', name: 'Kachin; Jingpho'},
|
{code3: 'kac', code2: '', name: 'Kachin; Jingpho'},
|
||||||
{code3: 'kal', code2: 'kl', name: 'Kalaallisut; Greenlandic'},
|
{code3: 'kal', code2: 'kl', name: 'Kalaallisut'},
|
||||||
{code3: 'kam', code2: '', name: 'Kamba'},
|
{code3: 'kam', code2: '', name: 'Kamba'},
|
||||||
{code3: 'kan', code2: 'kn', name: 'Kannada'},
|
{code3: 'kan', code2: 'kn', name: 'Kannada'},
|
||||||
{code3: 'kar', code2: '', name: 'Karen languages'},
|
{code3: 'kar', code2: '', name: 'Karen languages'},
|
||||||
@@ -362,7 +356,7 @@ export const LANGUAGES: Language[] = [
|
|||||||
{code3: 'lat', code2: 'la', name: 'Latin'},
|
{code3: 'lat', code2: 'la', name: 'Latin'},
|
||||||
{code3: 'lav', code2: 'lv', name: 'Latvian'},
|
{code3: 'lav', code2: 'lv', name: 'Latvian'},
|
||||||
{code3: 'lez', code2: '', name: 'Lezghian'},
|
{code3: 'lez', code2: '', name: 'Lezghian'},
|
||||||
{code3: 'lim', code2: 'li', name: 'Limburgan; Limburger; Limburgish'},
|
{code3: 'lim', code2: 'li', name: 'Limburgish'},
|
||||||
{code3: 'lin', code2: 'ln', name: 'Lingala'},
|
{code3: 'lin', code2: 'ln', name: 'Lingala'},
|
||||||
{code3: 'lit', code2: 'lt', name: 'Lithuanian'},
|
{code3: 'lit', code2: 'lt', name: 'Lithuanian'},
|
||||||
{code3: 'lol', code2: '', name: 'Mongo'},
|
{code3: 'lol', code2: '', name: 'Mongo'},
|
||||||
@@ -423,9 +417,9 @@ export const LANGUAGES: Language[] = [
|
|||||||
{code3: 'nai', code2: '', name: 'North American Indian languages'},
|
{code3: 'nai', code2: '', name: 'North American Indian languages'},
|
||||||
{code3: 'nap', code2: '', name: 'Neapolitan'},
|
{code3: 'nap', code2: '', name: 'Neapolitan'},
|
||||||
{code3: 'nau', code2: 'na', name: 'Nauru'},
|
{code3: 'nau', code2: 'na', name: 'Nauru'},
|
||||||
{code3: 'nav', code2: 'nv', name: 'Navajo; Navaho'},
|
{code3: 'nav', code2: 'nv', name: 'Navajo'},
|
||||||
{code3: 'nbl', code2: 'nr', name: 'Ndebele, South; South Ndebele'},
|
{code3: 'nbl', code2: 'nr', name: 'South Ndebele'},
|
||||||
{code3: 'nde', code2: 'nd', name: 'Ndebele, North; North Ndebele'},
|
{code3: 'nde', code2: 'nd', name: 'North Ndebele'},
|
||||||
{code3: 'ndo', code2: 'ng', name: 'Ndonga'},
|
{code3: 'ndo', code2: 'ng', name: 'Ndonga'},
|
||||||
{
|
{
|
||||||
code3: 'nds',
|
code3: 'nds',
|
||||||
@@ -438,8 +432,8 @@ export const LANGUAGES: Language[] = [
|
|||||||
{code3: 'nic', code2: '', name: 'Niger-Kordofanian languages'},
|
{code3: 'nic', code2: '', name: 'Niger-Kordofanian languages'},
|
||||||
{code3: 'niu', code2: '', name: 'Niuean'},
|
{code3: 'niu', code2: '', name: 'Niuean'},
|
||||||
{code3: 'nld', code2: 'nl', name: 'Dutch; Flemish'},
|
{code3: 'nld', code2: 'nl', name: 'Dutch; Flemish'},
|
||||||
{code3: 'nno', code2: 'nn', name: 'Norwegian Nynorsk; Nynorsk, Norwegian'},
|
{code3: 'nno', code2: 'nn', name: 'Norwegian Nynorsk'},
|
||||||
{code3: 'nob', code2: 'nb', name: 'Bokmål, Norwegian; Norwegian Bokmål'},
|
{code3: 'nob', code2: 'nb', name: 'Norwegian Bokmål'},
|
||||||
{code3: 'nog', code2: '', name: 'Nogai'},
|
{code3: 'nog', code2: '', name: 'Nogai'},
|
||||||
{code3: 'non', code2: '', name: 'Norse, Old'},
|
{code3: 'non', code2: '', name: 'Norse, Old'},
|
||||||
{code3: 'nor', code2: 'no', name: 'Norwegian'},
|
{code3: 'nor', code2: 'no', name: 'Norwegian'},
|
||||||
@@ -461,7 +455,7 @@ export const LANGUAGES: Language[] = [
|
|||||||
{code3: 'ori', code2: 'or', name: 'Oriya'},
|
{code3: 'ori', code2: 'or', name: 'Oriya'},
|
||||||
{code3: 'orm', code2: 'om', name: 'Oromo'},
|
{code3: 'orm', code2: 'om', name: 'Oromo'},
|
||||||
{code3: 'osa', code2: '', name: 'Osage'},
|
{code3: 'osa', code2: '', name: 'Osage'},
|
||||||
{code3: 'oss', code2: 'os', name: 'Ossetian; Ossetic'},
|
{code3: 'oss', code2: 'os', name: 'Ossetic'},
|
||||||
{code3: 'ota', code2: '', name: 'Turkish, Ottoman (1500-1928)'},
|
{code3: 'ota', code2: '', name: 'Turkish, Ottoman (1500-1928)'},
|
||||||
{code3: 'oto', code2: '', name: 'Otomian languages'},
|
{code3: 'oto', code2: '', name: 'Otomian languages'},
|
||||||
{code3: 'paa', code2: '', name: 'Papuan languages'},
|
{code3: 'paa', code2: '', name: 'Papuan languages'},
|
||||||
|
|||||||
+485
-289
File diff suppressed because it is too large
Load Diff
+1274
-1664
File diff suppressed because it is too large
Load Diff
+1288
-965
File diff suppressed because it is too large
Load Diff
@@ -15,7 +15,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: src/components/ProgressGuide/FollowDialog.tsx:567
|
#: src/components/ProgressGuide/FollowDialog.tsx:567
|
||||||
msgid "(active)"
|
msgid "(active)"
|
||||||
msgstr ""
|
msgstr "(सक्रिय)"
|
||||||
|
|
||||||
#: src/screens/Messages/components/ChatListItem.tsx:130
|
#: src/screens/Messages/components/ChatListItem.tsx:130
|
||||||
msgid "(contains embedded content)"
|
msgid "(contains embedded content)"
|
||||||
@@ -37,11 +37,11 @@ msgstr "{0, plural, other {# दिन}}"
|
|||||||
|
|
||||||
#: src/screens/Profile/ProfileFollowers.tsx:40
|
#: src/screens/Profile/ProfileFollowers.tsx:40
|
||||||
msgid "{0, plural, one {# follower} other {# followers}}"
|
msgid "{0, plural, one {# follower} other {# followers}}"
|
||||||
msgstr ""
|
msgstr "{0, plural, one {# फ़ॉलोअर} other {# फ़ॉलोअर}}"
|
||||||
|
|
||||||
#: src/screens/Profile/ProfileFollows.tsx:40
|
#: src/screens/Profile/ProfileFollows.tsx:40
|
||||||
msgid "{0, plural, one {# following} other {# following}}"
|
msgid "{0, plural, one {# following} other {# following}}"
|
||||||
msgstr ""
|
msgstr "{0, plural, one {# फ़ॉलोइंग} other {# फ़ॉलोइंग}}"
|
||||||
|
|
||||||
#: src/lib/hooks/useTimeAgo.ts:146
|
#: src/lib/hooks/useTimeAgo.ts:146
|
||||||
msgid "{0, plural, one {# hour} other {# hours}}"
|
msgid "{0, plural, one {# hour} other {# hours}}"
|
||||||
@@ -65,15 +65,15 @@ msgstr "{0, plural, one {# घंटा} other {# घंटे}}"
|
|||||||
|
|
||||||
#: src/components/moderation/LabelsOnMe.tsx:53
|
#: src/components/moderation/LabelsOnMe.tsx:53
|
||||||
msgid "{0, plural, one {# label has} other {# labels have}} been placed on this account"
|
msgid "{0, plural, one {# label has} other {# labels have}} been placed on this account"
|
||||||
msgstr ""
|
msgstr "इस खाते पर {0, plural, one {# लेबल लगाया गया है।} other {# लेबल लगाए गए हैं।}}"
|
||||||
|
|
||||||
#: src/components/moderation/LabelsOnMe.tsx:62
|
#: src/components/moderation/LabelsOnMe.tsx:62
|
||||||
msgid "{0, plural, one {# label has} other {# labels have}} been placed on this content"
|
msgid "{0, plural, one {# label has} other {# labels have}} been placed on this content"
|
||||||
msgstr ""
|
msgstr "इस सामाग्री पर {0, plural, one {# लेबल लगाया गया है।} other {# लेबल लगाए गए हैं।}}"
|
||||||
|
|
||||||
#: src/screens/Post/PostLikedBy.tsx:41
|
#: src/screens/Post/PostLikedBy.tsx:41
|
||||||
msgid "{0, plural, one {# like} other {# likes}}"
|
msgid "{0, plural, one {# like} other {# likes}}"
|
||||||
msgstr ""
|
msgstr "{0, plural, one {# पसंद} other {# पसंद}}"
|
||||||
|
|
||||||
#: src/lib/hooks/useTimeAgo.ts:136
|
#: src/lib/hooks/useTimeAgo.ts:136
|
||||||
msgid "{0, plural, one {# minute} other {# minutes}}"
|
msgid "{0, plural, one {# minute} other {# minutes}}"
|
||||||
@@ -85,7 +85,7 @@ msgstr "{0, plural, one {# महीना} other {# महीने}}"
|
|||||||
|
|
||||||
#: src/screens/Post/PostQuotes.tsx:41
|
#: src/screens/Post/PostQuotes.tsx:41
|
||||||
msgid "{0, plural, one {# quote} other {# quotes}}"
|
msgid "{0, plural, one {# quote} other {# quotes}}"
|
||||||
msgstr ""
|
msgstr "{0, plural, one {# क्वोट} other {# क्वोट}}"
|
||||||
|
|
||||||
#: src/screens/Post/PostRepostedBy.tsx:41
|
#: src/screens/Post/PostRepostedBy.tsx:41
|
||||||
msgid "{0, plural, one {# repost} other {# reposts}}"
|
msgid "{0, plural, one {# repost} other {# reposts}}"
|
||||||
@@ -335,7 +335,7 @@ msgstr "{handle} को संदेश भेजा नहीं जा सक
|
|||||||
|
|
||||||
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:260
|
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:260
|
||||||
msgid "{notificationCount} unread items"
|
msgid "{notificationCount} unread items"
|
||||||
msgstr ""
|
msgstr "{notificationCount} अपठित चीज़ें"
|
||||||
|
|
||||||
#: src/view/shell/Drawer.tsx:448
|
#: src/view/shell/Drawer.tsx:448
|
||||||
msgid "{numUnreadNotifications} unread"
|
msgid "{numUnreadNotifications} unread"
|
||||||
@@ -621,7 +621,7 @@ msgstr "नया पोस्ट जोड़ें"
|
|||||||
#: src/view/screens/ProfileList.tsx:903
|
#: src/view/screens/ProfileList.tsx:903
|
||||||
#: src/view/screens/ProfileList.tsx:921
|
#: src/view/screens/ProfileList.tsx:921
|
||||||
msgid "Add people"
|
msgid "Add people"
|
||||||
msgstr ""
|
msgstr "लोगों को जोड़ें"
|
||||||
|
|
||||||
#: src/screens/Home/NoFeedsPinned.tsx:99
|
#: src/screens/Home/NoFeedsPinned.tsx:99
|
||||||
msgid "Add recommended feeds"
|
msgid "Add recommended feeds"
|
||||||
@@ -703,7 +703,7 @@ msgstr "विकसित"
|
|||||||
|
|
||||||
#: src/view/screens/Notifications.tsx:86
|
#: src/view/screens/Notifications.tsx:86
|
||||||
msgid "All"
|
msgid "All"
|
||||||
msgstr ""
|
msgstr "सभी"
|
||||||
|
|
||||||
#: src/screens/StarterPack/StarterPackScreen.tsx:381
|
#: src/screens/StarterPack/StarterPackScreen.tsx:381
|
||||||
msgid "All accounts have been followed!"
|
msgid "All accounts have been followed!"
|
||||||
@@ -725,7 +725,7 @@ msgstr "इनसे नए संदेश आने की अनुमति
|
|||||||
|
|
||||||
#: src/components/dialogs/PostInteractionSettingsDialog.tsx:314
|
#: src/components/dialogs/PostInteractionSettingsDialog.tsx:314
|
||||||
msgid "Allow quote posts"
|
msgid "Allow quote posts"
|
||||||
msgstr ""
|
msgstr "क्वोट पोस्ट की अनुमति दें"
|
||||||
|
|
||||||
#: src/components/dialogs/PostInteractionSettingsDialog.tsx:359
|
#: src/components/dialogs/PostInteractionSettingsDialog.tsx:359
|
||||||
msgid "Allow replies from:"
|
msgid "Allow replies from:"
|
||||||
@@ -888,7 +888,7 @@ msgstr "कोई भी संपर्क कर सकता है"
|
|||||||
#: src/screens/Settings/AppIconSettings/SettingsListItem.tsx:18
|
#: src/screens/Settings/AppIconSettings/SettingsListItem.tsx:18
|
||||||
#: src/screens/Settings/AppIconSettings/SettingsListItem.tsx:23
|
#: src/screens/Settings/AppIconSettings/SettingsListItem.tsx:23
|
||||||
msgid "App Icon"
|
msgid "App Icon"
|
||||||
msgstr ""
|
msgstr "ऐप आइकॉन"
|
||||||
|
|
||||||
#: src/screens/Settings/LanguageSettings.tsx:80
|
#: src/screens/Settings/LanguageSettings.tsx:80
|
||||||
msgid "App Language"
|
msgid "App Language"
|
||||||
@@ -1113,7 +1113,7 @@ msgstr "अन्य उपयोगकर्ताओं को संदेश
|
|||||||
|
|
||||||
#: src/screens/Search/components/ExploreTrendingTopics.tsx:74
|
#: src/screens/Search/components/ExploreTrendingTopics.tsx:74
|
||||||
msgid "BETA"
|
msgid "BETA"
|
||||||
msgstr ""
|
msgstr "बीटा"
|
||||||
|
|
||||||
#: src/components/dialogs/BirthDateSettings.tsx:106
|
#: src/components/dialogs/BirthDateSettings.tsx:106
|
||||||
#: src/screens/Settings/AccountSettings.tsx:109
|
#: src/screens/Settings/AccountSettings.tsx:109
|
||||||
@@ -1252,11 +1252,11 @@ msgstr "Bluesky लॉग आउट उपयोगकर्ताओं को
|
|||||||
|
|
||||||
#: src/screens/Settings/AppIconSettings/index.tsx:99
|
#: src/screens/Settings/AppIconSettings/index.tsx:99
|
||||||
msgid "Bluesky+"
|
msgid "Bluesky+"
|
||||||
msgstr ""
|
msgstr "Bluesky+"
|
||||||
|
|
||||||
#: src/screens/Settings/AppIconSettings/index.tsx:102
|
#: src/screens/Settings/AppIconSettings/index.tsx:102
|
||||||
msgid "Bluesky+ icons"
|
msgid "Bluesky+ icons"
|
||||||
msgstr ""
|
msgstr "Bluesky+ आइकॉन"
|
||||||
|
|
||||||
#: src/lib/moderation/useLabelBehaviorDescription.ts:53
|
#: src/lib/moderation/useLabelBehaviorDescription.ts:53
|
||||||
msgid "Blur images"
|
msgid "Blur images"
|
||||||
@@ -1298,15 +1298,15 @@ msgstr "अन्य फ़ीड देखें"
|
|||||||
|
|
||||||
#: src/components/TrendingTopics.tsx:176
|
#: src/components/TrendingTopics.tsx:176
|
||||||
msgid "Browse posts about {displayName}"
|
msgid "Browse posts about {displayName}"
|
||||||
msgstr ""
|
msgstr "{displayName} के बारे में पोस्ट देखें"
|
||||||
|
|
||||||
#: src/components/TrendingTopics.tsx:184
|
#: src/components/TrendingTopics.tsx:184
|
||||||
msgid "Browse posts tagged with {displayName}"
|
msgid "Browse posts tagged with {displayName}"
|
||||||
msgstr ""
|
msgstr "{displayName} से टैग किए गए पोस्ट देखें"
|
||||||
|
|
||||||
#: src/components/TrendingTopics.tsx:222
|
#: src/components/TrendingTopics.tsx:222
|
||||||
msgid "Browse topic {displayName}"
|
msgid "Browse topic {displayName}"
|
||||||
msgstr ""
|
msgstr "{displayName} विषय देखें"
|
||||||
|
|
||||||
#: src/view/screens/Settings/index.tsx:893
|
#: src/view/screens/Settings/index.tsx:893
|
||||||
#~ msgid "Build version {0} {1}"
|
#~ msgid "Build version {0} {1}"
|
||||||
@@ -1330,7 +1330,7 @@ msgstr "{0} के द्वारा"
|
|||||||
|
|
||||||
#: src/screens/Profile/components/ProfileFeedHeader.tsx:447
|
#: src/screens/Profile/components/ProfileFeedHeader.tsx:447
|
||||||
msgid "By <0>{0}</0>"
|
msgid "By <0>{0}</0>"
|
||||||
msgstr ""
|
msgstr "<0>{0}</0> के द्वार"
|
||||||
|
|
||||||
#: src/screens/Signup/StepInfo/Policies.tsx:80
|
#: src/screens/Signup/StepInfo/Policies.tsx:80
|
||||||
#~ msgid "By creating an account you agree to the {els}."
|
#~ msgid "By creating an account you agree to the {els}."
|
||||||
@@ -1463,12 +1463,12 @@ msgstr "बदलें"
|
|||||||
|
|
||||||
#: src/screens/Settings/AppIconSettings/index.tsx:39
|
#: src/screens/Settings/AppIconSettings/index.tsx:39
|
||||||
msgid "Change app icon"
|
msgid "Change app icon"
|
||||||
msgstr ""
|
msgstr "ऐप आइकॉन बदलें"
|
||||||
|
|
||||||
#: src/screens/Settings/AppIconSettings/index.tsx:38
|
#: src/screens/Settings/AppIconSettings/index.tsx:38
|
||||||
#: src/screens/Settings/AppIconSettings/index.tsx:221
|
#: src/screens/Settings/AppIconSettings/index.tsx:221
|
||||||
msgid "Change app icon to \"{0}\""
|
msgid "Change app icon to \"{0}\""
|
||||||
msgstr ""
|
msgstr "ऐप आइकॉन को \"{0}\" में बदलें"
|
||||||
|
|
||||||
#: src/screens/Settings/AccountSettings.tsx:97
|
#: src/screens/Settings/AccountSettings.tsx:97
|
||||||
#: src/screens/Settings/AccountSettings.tsx:101
|
#: src/screens/Settings/AccountSettings.tsx:101
|
||||||
@@ -1600,7 +1600,7 @@ msgstr "इस रंग को अपना अवतार के रूप
|
|||||||
#: src/view/screens/Feeds.tsx:728
|
#: src/view/screens/Feeds.tsx:728
|
||||||
#: src/view/screens/Search/Explore.tsx:411
|
#: src/view/screens/Search/Explore.tsx:411
|
||||||
msgid "Choose your own timeline! Feeds built by the community help you find content you love."
|
msgid "Choose your own timeline! Feeds built by the community help you find content you love."
|
||||||
msgstr ""
|
msgstr "आपका अपना टाइमलाइन चुनें! समुदाय द्वारा बनाए गए फ़ीड आपको पसंदीदा सामग्री ढूँढने में सहायता करते हैं।"
|
||||||
|
|
||||||
#: src/screens/Signup/StepInfo/index.tsx:201
|
#: src/screens/Signup/StepInfo/index.tsx:201
|
||||||
msgid "Choose your password"
|
msgid "Choose your password"
|
||||||
@@ -1696,7 +1696,7 @@ msgstr "डायलॉग बंद करें"
|
|||||||
#: src/view/com/composer/text-input/web/EmojiPicker.web.tsx:137
|
#: src/view/com/composer/text-input/web/EmojiPicker.web.tsx:137
|
||||||
#: src/view/com/composer/text-input/web/EmojiPicker.web.tsx:173
|
#: src/view/com/composer/text-input/web/EmojiPicker.web.tsx:173
|
||||||
msgid "Close emoji picker"
|
msgid "Close emoji picker"
|
||||||
msgstr ""
|
msgstr "इमोजी चयन बंद करें"
|
||||||
|
|
||||||
#: src/components/dialogs/GifSelect.tsx:169
|
#: src/components/dialogs/GifSelect.tsx:169
|
||||||
msgid "Close GIF dialog"
|
msgid "Close GIF dialog"
|
||||||
@@ -1859,7 +1859,7 @@ msgstr "सहायता से संपर्क करें"
|
|||||||
|
|
||||||
#: src/screens/Settings/ContentAndMediaSettings.tsx:49
|
#: src/screens/Settings/ContentAndMediaSettings.tsx:49
|
||||||
msgid "Content & Media"
|
msgid "Content & Media"
|
||||||
msgstr ""
|
msgstr "सामाग्री और मीडिया"
|
||||||
|
|
||||||
#: src/screens/Settings/AccessibilitySettings.tsx:109
|
#: src/screens/Settings/AccessibilitySettings.tsx:109
|
||||||
#: src/screens/Settings/Settings.tsx:175
|
#: src/screens/Settings/Settings.tsx:175
|
||||||
@@ -2149,7 +2149,7 @@ msgstr "{0} बनाया गया"
|
|||||||
|
|
||||||
#: src/screens/List/ListHiddenScreen.tsx:127
|
#: src/screens/List/ListHiddenScreen.tsx:127
|
||||||
msgid "Creator has been blocked"
|
msgid "Creator has been blocked"
|
||||||
msgstr ""
|
msgstr "रचयिता को अवरुद्ध किया गया"
|
||||||
|
|
||||||
#: src/screens/Onboarding/index.tsx:26
|
#: src/screens/Onboarding/index.tsx:26
|
||||||
#: src/screens/Onboarding/state.ts:99
|
#: src/screens/Onboarding/state.ts:99
|
||||||
@@ -2227,7 +2227,7 @@ msgstr "डिफ़ॉल्ट"
|
|||||||
|
|
||||||
#: src/screens/Settings/AppIconSettings/index.tsx:75
|
#: src/screens/Settings/AppIconSettings/index.tsx:75
|
||||||
msgid "Default icons"
|
msgid "Default icons"
|
||||||
msgstr ""
|
msgstr "डिफ़ॉल्ट आइकॉन"
|
||||||
|
|
||||||
#: src/components/dms/MessageMenu.tsx:151
|
#: src/components/dms/MessageMenu.tsx:151
|
||||||
#: src/screens/Settings/AppPasswords.tsx:212
|
#: src/screens/Settings/AppPasswords.tsx:212
|
||||||
@@ -2713,7 +2713,7 @@ msgstr "शिक्षा"
|
|||||||
|
|
||||||
#: src/screens/List/ListHiddenScreen.tsx:141
|
#: src/screens/List/ListHiddenScreen.tsx:141
|
||||||
msgid "Either the creator of this list has blocked you or you have blocked the creator."
|
msgid "Either the creator of this list has blocked you or you have blocked the creator."
|
||||||
msgstr ""
|
msgstr "इस सूची के रचयिता ने आपको अवरुद्ध किया है या आपने रचयिता को अवरुद्ध किया है।"
|
||||||
|
|
||||||
#: src/screens/Settings/AccountSettings.tsx:60
|
#: src/screens/Settings/AccountSettings.tsx:60
|
||||||
#: src/screens/Signup/StepInfo/index.tsx:170
|
#: src/screens/Signup/StepInfo/index.tsx:170
|
||||||
@@ -2774,7 +2774,7 @@ msgstr "इस पोस्ट को अपने वेबसाइट मे
|
|||||||
|
|
||||||
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerWeb.tsx:57
|
#: src/view/com/util/post-embeds/VideoEmbedInner/VideoEmbedInnerWeb.tsx:57
|
||||||
msgid "Embedded video player"
|
msgid "Embedded video player"
|
||||||
msgstr ""
|
msgstr "एम्बेडेड वीडियो प्लेयर"
|
||||||
|
|
||||||
#: src/screens/Settings/components/Email2FAToggle.tsx:56
|
#: src/screens/Settings/components/Email2FAToggle.tsx:56
|
||||||
#: src/screens/Settings/components/Email2FAToggle.tsx:60
|
#: src/screens/Settings/components/Email2FAToggle.tsx:60
|
||||||
@@ -2822,7 +2822,7 @@ msgstr "केवल इस सूत्र को सक्षम करें"
|
|||||||
#: src/screens/Settings/ContentAndMediaSettings.tsx:122
|
#: src/screens/Settings/ContentAndMediaSettings.tsx:122
|
||||||
#: src/screens/Settings/ContentAndMediaSettings.tsx:136
|
#: src/screens/Settings/ContentAndMediaSettings.tsx:136
|
||||||
msgid "Enable trending topics"
|
msgid "Enable trending topics"
|
||||||
msgstr ""
|
msgstr "रुझान सक्षम करें"
|
||||||
|
|
||||||
#: src/screens/Messages/Settings.tsx:130
|
#: src/screens/Messages/Settings.tsx:130
|
||||||
#: src/screens/Messages/Settings.tsx:133
|
#: src/screens/Messages/Settings.tsx:133
|
||||||
@@ -2861,7 +2861,7 @@ msgstr "पुष्टिकरण कोड दर्ज करें"
|
|||||||
|
|
||||||
#: src/view/com/util/post-embeds/VideoEmbedInner/web-controls/VideoControls.tsx:405
|
#: src/view/com/util/post-embeds/VideoEmbedInner/web-controls/VideoControls.tsx:405
|
||||||
msgid "Enter fullscreen"
|
msgid "Enter fullscreen"
|
||||||
msgstr ""
|
msgstr "फ़ुलस्क्रीन में जाएँ"
|
||||||
|
|
||||||
#: src/view/com/modals/ChangePassword.tsx:154
|
#: src/view/com/modals/ChangePassword.tsx:154
|
||||||
msgid "Enter the code you received to change your password."
|
msgid "Enter the code you received to change your password."
|
||||||
@@ -3166,7 +3166,7 @@ msgstr "{0} द्वारा फ़ीड"
|
|||||||
|
|
||||||
#: src/screens/Profile/components/ProfileFeedHeader.tsx:353
|
#: src/screens/Profile/components/ProfileFeedHeader.tsx:353
|
||||||
msgid "Feed menu"
|
msgid "Feed menu"
|
||||||
msgstr ""
|
msgstr "फ़ीड मेनू"
|
||||||
|
|
||||||
#: src/view/screens/Feeds.tsx:709
|
#: src/view/screens/Feeds.tsx:709
|
||||||
#~ msgid "Feed offline"
|
#~ msgid "Feed offline"
|
||||||
@@ -3217,7 +3217,7 @@ msgstr "फ़ीड अपडेट की गई!"
|
|||||||
|
|
||||||
#: src/screens/Search/components/ExploreRecommendations.tsx:54
|
#: src/screens/Search/components/ExploreRecommendations.tsx:54
|
||||||
msgid "Feeds we think you might like."
|
msgid "Feeds we think you might like."
|
||||||
msgstr ""
|
msgstr "फ़ीड जो हमें लगता है आपको पसंद आए।"
|
||||||
|
|
||||||
#: src/view/com/modals/ChangeHandle.tsx:468
|
#: src/view/com/modals/ChangeHandle.tsx:468
|
||||||
#~ msgid "File Contents"
|
#~ msgid "File Contents"
|
||||||
@@ -3245,7 +3245,7 @@ msgstr "फ़ॉलो करने के लिए खाते खोजे
|
|||||||
#: src/components/ProgressGuide/FollowDialog.tsx:88
|
#: src/components/ProgressGuide/FollowDialog.tsx:88
|
||||||
#: src/components/ProgressGuide/FollowDialog.tsx:417
|
#: src/components/ProgressGuide/FollowDialog.tsx:417
|
||||||
msgid "Find people to follow"
|
msgid "Find people to follow"
|
||||||
msgstr ""
|
msgstr "फ़ॉलो करने के लिए लोग खोजें"
|
||||||
|
|
||||||
#: src/view/screens/Search/Search.tsx:595
|
#: src/view/screens/Search/Search.tsx:595
|
||||||
msgid "Find posts and users on Bluesky"
|
msgid "Find posts and users on Bluesky"
|
||||||
@@ -3305,7 +3305,7 @@ msgstr "{name} को फ़ॉलो करें"
|
|||||||
#: src/components/ProgressGuide/List.tsx:52
|
#: src/components/ProgressGuide/List.tsx:52
|
||||||
#: src/state/shell/progress-guide.tsx:229
|
#: src/state/shell/progress-guide.tsx:229
|
||||||
msgid "Follow 10 accounts"
|
msgid "Follow 10 accounts"
|
||||||
msgstr ""
|
msgstr "10 खाते फ़ॉलो करें"
|
||||||
|
|
||||||
#: src/components/ProgressGuide/List.tsx:69
|
#: src/components/ProgressGuide/List.tsx:69
|
||||||
msgid "Follow 7 accounts"
|
msgid "Follow 7 accounts"
|
||||||
@@ -3732,13 +3732,13 @@ msgstr "यह पोस्ट छिपाएँ?"
|
|||||||
#: src/screens/Search/components/ExploreTrendingTopics.tsx:83
|
#: src/screens/Search/components/ExploreTrendingTopics.tsx:83
|
||||||
#: src/view/shell/desktop/SidebarTrendingTopics.tsx:62
|
#: src/view/shell/desktop/SidebarTrendingTopics.tsx:62
|
||||||
msgid "Hide trending topics"
|
msgid "Hide trending topics"
|
||||||
msgstr ""
|
msgstr "रुझान छिपाएँ"
|
||||||
|
|
||||||
#: src/components/interstitials/Trending.tsx:99
|
#: src/components/interstitials/Trending.tsx:99
|
||||||
#: src/screens/Search/components/ExploreTrendingTopics.tsx:135
|
#: src/screens/Search/components/ExploreTrendingTopics.tsx:135
|
||||||
#: src/view/shell/desktop/SidebarTrendingTopics.tsx:108
|
#: src/view/shell/desktop/SidebarTrendingTopics.tsx:108
|
||||||
msgid "Hide trending topics?"
|
msgid "Hide trending topics?"
|
||||||
msgstr ""
|
msgstr "रुझान छिपाएँ?"
|
||||||
|
|
||||||
#: src/view/com/notifications/NotificationFeedItem.tsx:592
|
#: src/view/com/notifications/NotificationFeedItem.tsx:592
|
||||||
msgid "Hide user list"
|
msgid "Hide user list"
|
||||||
@@ -3806,7 +3806,7 @@ msgstr "होस्टिंग प्रदाता"
|
|||||||
#: src/view/com/post-thread/PostThread.tsx:652
|
#: src/view/com/post-thread/PostThread.tsx:652
|
||||||
#: src/view/com/post-thread/PostThread.tsx:657
|
#: src/view/com/post-thread/PostThread.tsx:657
|
||||||
msgid "Hot replies first"
|
msgid "Hot replies first"
|
||||||
msgstr ""
|
msgstr "गर्मागर्म जवाब पहले"
|
||||||
|
|
||||||
#: src/view/com/modals/InAppBrowserConsent.tsx:41
|
#: src/view/com/modals/InAppBrowserConsent.tsx:41
|
||||||
msgid "How should we open this link?"
|
msgid "How should we open this link?"
|
||||||
@@ -3859,7 +3859,7 @@ msgstr "यदि आप इस सूची को मिटते हैं,
|
|||||||
|
|
||||||
#: src/screens/Settings/components/ChangeHandleDialog.tsx:250
|
#: src/screens/Settings/components/ChangeHandleDialog.tsx:250
|
||||||
msgid "If you have your own domain, you can use that as your handle. This lets you self-verify your identity. <0>Learn more here.</0>"
|
msgid "If you have your own domain, you can use that as your handle. This lets you self-verify your identity. <0>Learn more here.</0>"
|
||||||
msgstr ""
|
msgstr "यदि आपका अपना डोमेन है, आप उसे अपने हैंडल के तौर पर उपयोग कर सकते हैं। इसे आप ख़ुद अपने पहचान की पुष्टि कर सकते हैं। <0>यहाँ अधिक जानें।</0>"
|
||||||
|
|
||||||
#: src/view/com/util/forms/PostDropdownBtnMenuItems.tsx:658
|
#: src/view/com/util/forms/PostDropdownBtnMenuItems.tsx:658
|
||||||
msgid "If you remove this post, you won't be able to recover it."
|
msgid "If you remove this post, you won't be able to recover it."
|
||||||
@@ -4216,11 +4216,11 @@ msgstr "रोशन"
|
|||||||
|
|
||||||
#: src/screens/Profile/components/ProfileFeedHeader.tsx:514
|
#: src/screens/Profile/components/ProfileFeedHeader.tsx:514
|
||||||
msgid "Like"
|
msgid "Like"
|
||||||
msgstr ""
|
msgstr "पसंद"
|
||||||
|
|
||||||
#: src/view/com/util/post-ctrls/PostCtrls.tsx:311
|
#: src/view/com/util/post-ctrls/PostCtrls.tsx:311
|
||||||
msgid "Like ({0, plural, one {# like} other {# likes}})"
|
msgid "Like ({0, plural, one {# like} other {# likes}})"
|
||||||
msgstr ""
|
msgstr "पसंद करें ({0, plural, one {# पसंद} other {# पसंद}})"
|
||||||
|
|
||||||
#: src/components/ProgressGuide/List.tsx:63
|
#: src/components/ProgressGuide/List.tsx:63
|
||||||
msgid "Like 10 posts"
|
msgid "Like 10 posts"
|
||||||
@@ -4233,7 +4233,7 @@ msgstr "डिस्कवर फ़ीड को प्रशिक्षित
|
|||||||
|
|
||||||
#: src/screens/Profile/components/ProfileFeedHeader.tsx:501
|
#: src/screens/Profile/components/ProfileFeedHeader.tsx:501
|
||||||
msgid "Like feed"
|
msgid "Like feed"
|
||||||
msgstr ""
|
msgstr "फ़ीड पसंद करें"
|
||||||
|
|
||||||
#: src/screens/Profile/Header/ProfileHeaderLabeler.tsx:275
|
#: src/screens/Profile/Header/ProfileHeaderLabeler.tsx:275
|
||||||
msgid "Like this feed"
|
msgid "Like this feed"
|
||||||
@@ -4254,14 +4254,14 @@ msgstr "इन्होनें पसंद किया"
|
|||||||
#: src/components/FeedCard.tsx:213
|
#: src/components/FeedCard.tsx:213
|
||||||
#: src/view/com/feeds/FeedSourceCard.tsx:303
|
#: src/view/com/feeds/FeedSourceCard.tsx:303
|
||||||
msgid "Liked by {0, plural, one {# user} other {# users}}"
|
msgid "Liked by {0, plural, one {# user} other {# users}}"
|
||||||
msgstr ""
|
msgstr "{0, plural, one {# उपयोगकर्ता} other {# उपयोगकर्ताओं}} ने पसंद किया"
|
||||||
|
|
||||||
#: src/components/LabelingServiceCard/index.tsx:96
|
#: src/components/LabelingServiceCard/index.tsx:96
|
||||||
#: src/screens/Profile/components/ProfileFeedHeader.tsx:489
|
#: src/screens/Profile/components/ProfileFeedHeader.tsx:489
|
||||||
#: src/screens/Profile/Header/ProfileHeaderLabeler.tsx:295
|
#: src/screens/Profile/Header/ProfileHeaderLabeler.tsx:295
|
||||||
#: src/screens/Profile/Header/ProfileHeaderLabeler.tsx:309
|
#: src/screens/Profile/Header/ProfileHeaderLabeler.tsx:309
|
||||||
msgid "Liked by {likeCount, plural, one {# user} other {# users}}"
|
msgid "Liked by {likeCount, plural, one {# user} other {# users}}"
|
||||||
msgstr ""
|
msgstr "{likeCount, plural, one {# उपयोगकर्ता} other {# उपयोगकर्ताओं}} ने पसंद किया"
|
||||||
|
|
||||||
#: src/view/com/notifications/FeedItem.tsx:211
|
#: src/view/com/notifications/FeedItem.tsx:211
|
||||||
#~ msgid "liked your custom feed"
|
#~ msgid "liked your custom feed"
|
||||||
@@ -4282,7 +4282,7 @@ msgstr "इस पोस्ट पर पसंद"
|
|||||||
#: src/view/com/post-thread/PostThread.tsx:626
|
#: src/view/com/post-thread/PostThread.tsx:626
|
||||||
#: src/view/com/post-thread/PostThread.tsx:631
|
#: src/view/com/post-thread/PostThread.tsx:631
|
||||||
msgid "Linear"
|
msgid "Linear"
|
||||||
msgstr ""
|
msgstr "रेखीय"
|
||||||
|
|
||||||
#: src/Navigation.tsx:198
|
#: src/Navigation.tsx:198
|
||||||
msgid "List"
|
msgid "List"
|
||||||
@@ -4303,11 +4303,11 @@ msgstr "{0} द्वारा सूची"
|
|||||||
|
|
||||||
#: src/view/com/profile/ProfileSubpageHeader.tsx:156
|
#: src/view/com/profile/ProfileSubpageHeader.tsx:156
|
||||||
msgid "List by <0/>"
|
msgid "List by <0/>"
|
||||||
msgstr ""
|
msgstr "<0/> द्वारा सूची"
|
||||||
|
|
||||||
#: src/view/com/profile/ProfileSubpageHeader.tsx:154
|
#: src/view/com/profile/ProfileSubpageHeader.tsx:154
|
||||||
msgid "List by you"
|
msgid "List by you"
|
||||||
msgstr ""
|
msgstr "आपके द्वारा सूची"
|
||||||
|
|
||||||
#: src/view/screens/ProfileList.tsx:455
|
#: src/view/screens/ProfileList.tsx:455
|
||||||
msgid "List deleted"
|
msgid "List deleted"
|
||||||
@@ -4412,7 +4412,7 @@ msgstr "उस खाते में लॉग इन करें जो स
|
|||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:121
|
#: src/view/shell/desktop/RightNav.tsx:121
|
||||||
msgid "Logo by @sawaratsuki.bsky.social"
|
msgid "Logo by @sawaratsuki.bsky.social"
|
||||||
msgstr ""
|
msgstr "@sawaratsuki.bsky.social द्वारा लोगो"
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:103
|
#: src/view/shell/desktop/RightNav.tsx:103
|
||||||
#~ msgid "Logo by <0/>"
|
#~ msgid "Logo by <0/>"
|
||||||
@@ -4483,7 +4483,7 @@ msgstr "उल्लेखित उपयोगकर्ता"
|
|||||||
|
|
||||||
#: src/view/screens/Notifications.tsx:99
|
#: src/view/screens/Notifications.tsx:99
|
||||||
msgid "Mentions"
|
msgid "Mentions"
|
||||||
msgstr ""
|
msgstr "उल्लेख"
|
||||||
|
|
||||||
#: src/components/Menu/index.tsx:96
|
#: src/components/Menu/index.tsx:96
|
||||||
#: src/view/screens/Search/Search.tsx:863
|
#: src/view/screens/Search/Search.tsx:863
|
||||||
@@ -4837,7 +4837,7 @@ msgstr "नया हैंडल"
|
|||||||
#: src/view/screens/Lists.tsx:66
|
#: src/view/screens/Lists.tsx:66
|
||||||
#: src/view/screens/ModerationModlists.tsx:66
|
#: src/view/screens/ModerationModlists.tsx:66
|
||||||
msgid "New list"
|
msgid "New list"
|
||||||
msgstr ""
|
msgstr "नई सूची"
|
||||||
|
|
||||||
#: src/components/dms/NewMessagesPill.tsx:92
|
#: src/components/dms/NewMessagesPill.tsx:92
|
||||||
msgid "New messages"
|
msgid "New messages"
|
||||||
@@ -5241,7 +5241,7 @@ msgstr "बातचीत विकल्प खोलें"
|
|||||||
|
|
||||||
#: src/components/Layout/Header/index.tsx:145
|
#: src/components/Layout/Header/index.tsx:145
|
||||||
msgid "Open drawer menu"
|
msgid "Open drawer menu"
|
||||||
msgstr ""
|
msgstr "ड्रॉअर मेनू खोलें"
|
||||||
|
|
||||||
#: src/screens/Messages/components/MessageInput.web.tsx:181
|
#: src/screens/Messages/components/MessageInput.web.tsx:181
|
||||||
#: src/view/com/composer/Composer.tsx:1228
|
#: src/view/com/composer/Composer.tsx:1228
|
||||||
@@ -5251,7 +5251,7 @@ msgstr "इमोजी चयन खोलें"
|
|||||||
|
|
||||||
#: src/screens/Profile/components/ProfileFeedHeader.tsx:190
|
#: src/screens/Profile/components/ProfileFeedHeader.tsx:190
|
||||||
msgid "Open feed info screen"
|
msgid "Open feed info screen"
|
||||||
msgstr ""
|
msgstr "फ़ीड जानकारी स्क्रीन खोलें"
|
||||||
|
|
||||||
#: src/screens/Profile/components/ProfileFeedHeader.tsx:290
|
#: src/screens/Profile/components/ProfileFeedHeader.tsx:290
|
||||||
#: src/screens/Profile/components/ProfileFeedHeader.tsx:295
|
#: src/screens/Profile/components/ProfileFeedHeader.tsx:295
|
||||||
@@ -5582,7 +5582,7 @@ msgstr "वयस्कों के लिए छवि।"
|
|||||||
#: src/screens/Profile/components/ProfileFeedHeader.tsx:519
|
#: src/screens/Profile/components/ProfileFeedHeader.tsx:519
|
||||||
#: src/screens/Profile/components/ProfileFeedHeader.tsx:526
|
#: src/screens/Profile/components/ProfileFeedHeader.tsx:526
|
||||||
msgid "Pin feed"
|
msgid "Pin feed"
|
||||||
msgstr ""
|
msgstr "फ़ीड पिन करें"
|
||||||
|
|
||||||
#: src/view/screens/ProfileList.tsx:685
|
#: src/view/screens/ProfileList.tsx:685
|
||||||
msgid "Pin to home"
|
msgid "Pin to home"
|
||||||
@@ -5604,7 +5604,7 @@ msgstr "पिन किया गया"
|
|||||||
#: src/screens/Profile/components/ProfileFeedHeader.tsx:162
|
#: src/screens/Profile/components/ProfileFeedHeader.tsx:162
|
||||||
#: src/screens/Profile/components/ProfileFeedHeader.tsx:174
|
#: src/screens/Profile/components/ProfileFeedHeader.tsx:174
|
||||||
msgid "Pinned {0} to Home"
|
msgid "Pinned {0} to Home"
|
||||||
msgstr ""
|
msgstr "होम में {0} पिन किया गया"
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:123
|
#: src/view/screens/SavedFeeds.tsx:123
|
||||||
msgid "Pinned Feeds"
|
msgid "Pinned Feeds"
|
||||||
@@ -5912,11 +5912,11 @@ msgstr "सार्वजनिक"
|
|||||||
|
|
||||||
#: src/view/com/lists/MyLists.tsx:77
|
#: src/view/com/lists/MyLists.tsx:77
|
||||||
msgid "Public, sharable lists of users to mute or block in bulk."
|
msgid "Public, sharable lists of users to mute or block in bulk."
|
||||||
msgstr ""
|
msgstr "उपयोगकर्ताओं की सार्वजनिक, साझा योग्य सूचियाँ जिन्हें एक साथ म्यूट या अवरुद्ध किया जा सकता है।"
|
||||||
|
|
||||||
#: src/view/com/lists/MyLists.tsx:72
|
#: src/view/com/lists/MyLists.tsx:72
|
||||||
msgid "Public, sharable lists which can be used to drive feeds."
|
msgid "Public, sharable lists which can be used to drive feeds."
|
||||||
msgstr ""
|
msgstr "सार्वजनिक, साझा योग्य सूचियाँ जो फ़ीड चला सकती हैं।"
|
||||||
|
|
||||||
#: src/view/screens/ModerationModlists.tsx:75
|
#: src/view/screens/ModerationModlists.tsx:75
|
||||||
#~ msgid "Public, shareable lists of users to mute or block in bulk."
|
#~ msgid "Public, shareable lists of users to mute or block in bulk."
|
||||||
@@ -6024,7 +6024,7 @@ msgstr "हाल के खोज"
|
|||||||
|
|
||||||
#: src/screens/Search/components/ExploreRecommendations.tsx:50
|
#: src/screens/Search/components/ExploreRecommendations.tsx:50
|
||||||
msgid "Recommended"
|
msgid "Recommended"
|
||||||
msgstr ""
|
msgstr "अनुशंसित"
|
||||||
|
|
||||||
#: src/view/com/auth/onboarding/RecommendedFeeds.tsx:117
|
#: src/view/com/auth/onboarding/RecommendedFeeds.tsx:117
|
||||||
#~ msgid "Recommended Feeds"
|
#~ msgid "Recommended Feeds"
|
||||||
@@ -6216,7 +6216,7 @@ msgstr "जवाब दें"
|
|||||||
|
|
||||||
#: src/view/com/util/post-ctrls/PostCtrls.tsx:263
|
#: src/view/com/util/post-ctrls/PostCtrls.tsx:263
|
||||||
msgid "Reply ({0, plural, one {# reply} other {# replies}})"
|
msgid "Reply ({0, plural, one {# reply} other {# replies}})"
|
||||||
msgstr ""
|
msgstr "जवाब दें ({0, plural, one {# जवाब} other {# जवाब}})"
|
||||||
|
|
||||||
#: src/view/screens/PreferencesFollowingFeed.tsx:142
|
#: src/view/screens/PreferencesFollowingFeed.tsx:142
|
||||||
#~ msgid "Reply Filters"
|
#~ msgid "Reply Filters"
|
||||||
@@ -6242,7 +6242,7 @@ msgstr "जवाब सेटिंग थ्रेड का लेखक च
|
|||||||
|
|
||||||
#: src/view/com/post-thread/PostThread.tsx:648
|
#: src/view/com/post-thread/PostThread.tsx:648
|
||||||
msgid "Reply sorting"
|
msgid "Reply sorting"
|
||||||
msgstr ""
|
msgstr "जवाब क्रम"
|
||||||
|
|
||||||
#: src/view/com/post/Post.tsx:204
|
#: src/view/com/post/Post.tsx:204
|
||||||
#: src/view/com/posts/PostFeedItem.tsx:553
|
#: src/view/com/posts/PostFeedItem.tsx:553
|
||||||
@@ -6365,7 +6365,7 @@ msgstr "रीपोस्ट"
|
|||||||
|
|
||||||
#: src/view/com/util/post-ctrls/RepostButton.tsx:74
|
#: src/view/com/util/post-ctrls/RepostButton.tsx:74
|
||||||
msgid "Repost ({0, plural, one {# repost} other {# reposts}})"
|
msgid "Repost ({0, plural, one {# repost} other {# reposts}})"
|
||||||
msgstr ""
|
msgstr "रीपोस्ट करें ({0, plural, one {# रीपोस्ट} other {# रीपोस्ट}})"
|
||||||
|
|
||||||
#: src/screens/StarterPack/StarterPackScreen.tsx:548
|
#: src/screens/StarterPack/StarterPackScreen.tsx:548
|
||||||
#: src/view/com/util/post-ctrls/RepostButton.tsx:148
|
#: src/view/com/util/post-ctrls/RepostButton.tsx:148
|
||||||
@@ -6637,15 +6637,15 @@ msgstr "खोजें"
|
|||||||
|
|
||||||
#: src/components/ProgressGuide/FollowDialog.tsx:745
|
#: src/components/ProgressGuide/FollowDialog.tsx:745
|
||||||
msgid "Search by name or interest"
|
msgid "Search by name or interest"
|
||||||
msgstr ""
|
msgstr "नाम या दिलचस्पी से खोजें"
|
||||||
|
|
||||||
#: src/view/screens/Feeds.tsx:441
|
#: src/view/screens/Feeds.tsx:441
|
||||||
msgid "Search feeds"
|
msgid "Search feeds"
|
||||||
msgstr ""
|
msgstr "फ़ीड खोजें"
|
||||||
|
|
||||||
#: src/components/ProgressGuide/FollowDialog.tsx:575
|
#: src/components/ProgressGuide/FollowDialog.tsx:575
|
||||||
msgid "Search for \"{interestsDisplayName}\"{activeText}"
|
msgid "Search for \"{interestsDisplayName}\"{activeText}"
|
||||||
msgstr ""
|
msgstr "\"{interestsDisplayName}\"{activeText} खोजें"
|
||||||
|
|
||||||
#: src/view/shell/desktop/Search.tsx:201
|
#: src/view/shell/desktop/Search.tsx:201
|
||||||
msgid "Search for \"{query}\""
|
msgid "Search for \"{query}\""
|
||||||
@@ -6716,7 +6716,7 @@ msgstr "यह गाइड देखें"
|
|||||||
|
|
||||||
#: src/view/com/util/post-embeds/VideoEmbedInner/web-controls/Scrubber.tsx:194
|
#: src/view/com/util/post-embeds/VideoEmbedInner/web-controls/Scrubber.tsx:194
|
||||||
msgid "Seek slider. Use the arrow keys to seek forwards and backwards, and space to play/pause"
|
msgid "Seek slider. Use the arrow keys to seek forwards and backwards, and space to play/pause"
|
||||||
msgstr ""
|
msgstr "सीक स्लाइडर। एरो की से आगे और पीछे सीक करें, और स्पेस से चालू/बंद करें"
|
||||||
|
|
||||||
#: src/view/com/util/Selector.tsx:107
|
#: src/view/com/util/Selector.tsx:107
|
||||||
#~ msgid "Select {item}"
|
#~ msgid "Select {item}"
|
||||||
@@ -6909,7 +6909,7 @@ msgstr "सर्वर पता"
|
|||||||
|
|
||||||
#: src/screens/Settings/AppIconSettings/index.tsx:178
|
#: src/screens/Settings/AppIconSettings/index.tsx:178
|
||||||
msgid "Set app icon to {0}"
|
msgid "Set app icon to {0}"
|
||||||
msgstr ""
|
msgstr "ऐप आइकॉन को {0} करें"
|
||||||
|
|
||||||
#: src/screens/Moderation/index.tsx:290
|
#: src/screens/Moderation/index.tsx:290
|
||||||
msgid "Set birthdate"
|
msgid "Set birthdate"
|
||||||
@@ -7030,7 +7030,7 @@ msgstr "QR कोड साझा करें"
|
|||||||
|
|
||||||
#: src/screens/Profile/components/ProfileFeedHeader.tsx:470
|
#: src/screens/Profile/components/ProfileFeedHeader.tsx:470
|
||||||
msgid "Share this feed"
|
msgid "Share this feed"
|
||||||
msgstr ""
|
msgstr "इस फ़ीड को साझा करें"
|
||||||
|
|
||||||
#: src/screens/StarterPack/StarterPackScreen.tsx:416
|
#: src/screens/StarterPack/StarterPackScreen.tsx:416
|
||||||
msgid "Share this starter pack"
|
msgid "Share this starter pack"
|
||||||
@@ -7129,11 +7129,11 @@ msgstr "जवाब दिखाएँ"
|
|||||||
|
|
||||||
#: src/view/com/post-thread/PostThread.tsx:622
|
#: src/view/com/post-thread/PostThread.tsx:622
|
||||||
msgid "Show replies as"
|
msgid "Show replies as"
|
||||||
msgstr ""
|
msgstr "जवाबों को ऐसे दिखाएँ"
|
||||||
|
|
||||||
#: src/screens/Settings/ThreadPreferences.tsx:151
|
#: src/screens/Settings/ThreadPreferences.tsx:151
|
||||||
msgid "Show replies as threaded"
|
msgid "Show replies as threaded"
|
||||||
msgstr ""
|
msgstr "जवाबों को थ्रेड में दिखाएँ"
|
||||||
|
|
||||||
#: src/screens/Settings/ThreadPreferences.tsx:126
|
#: src/screens/Settings/ThreadPreferences.tsx:126
|
||||||
msgid "Show replies by people you follow before all other replies"
|
msgid "Show replies by people you follow before all other replies"
|
||||||
@@ -7334,7 +7334,7 @@ msgstr "कोई गड़बड़ हुई!"
|
|||||||
|
|
||||||
#: src/screens/Profile/components/ProfileFeedHeader.tsx:538
|
#: src/screens/Profile/components/ProfileFeedHeader.tsx:538
|
||||||
msgid "Something wrong? Let us know."
|
msgid "Something wrong? Let us know."
|
||||||
msgstr ""
|
msgstr "कुछ गड़बड़ है? हमें बताएँ।"
|
||||||
|
|
||||||
#: src/App.native.tsx:122
|
#: src/App.native.tsx:122
|
||||||
#: src/App.web.tsx:97
|
#: src/App.web.tsx:97
|
||||||
@@ -7390,12 +7390,12 @@ msgstr "नया बातचीत शुरू करें"
|
|||||||
#: src/view/screens/ProfileList.tsx:817
|
#: src/view/screens/ProfileList.tsx:817
|
||||||
#: src/view/screens/ProfileList.tsx:938
|
#: src/view/screens/ProfileList.tsx:938
|
||||||
msgid "Start adding people"
|
msgid "Start adding people"
|
||||||
msgstr ""
|
msgstr "लोगों को जोड़ना शुरू करें"
|
||||||
|
|
||||||
#: src/view/screens/ProfileList.tsx:824
|
#: src/view/screens/ProfileList.tsx:824
|
||||||
#: src/view/screens/ProfileList.tsx:945
|
#: src/view/screens/ProfileList.tsx:945
|
||||||
msgid "Start adding people!"
|
msgid "Start adding people!"
|
||||||
msgstr ""
|
msgstr "लोगों को जोड़ना शुरू करें!"
|
||||||
|
|
||||||
#: src/components/dms/dialogs/SearchablePeopleList.tsx:353
|
#: src/components/dms/dialogs/SearchablePeopleList.tsx:353
|
||||||
msgid "Start chat with {displayName}"
|
msgid "Start chat with {displayName}"
|
||||||
@@ -7413,7 +7413,7 @@ msgstr "{0} द्वारा स्टार्टर पैक"
|
|||||||
|
|
||||||
#: src/view/com/profile/ProfileSubpageHeader.tsx:182
|
#: src/view/com/profile/ProfileSubpageHeader.tsx:182
|
||||||
msgid "Starter pack by <0/>"
|
msgid "Starter pack by <0/>"
|
||||||
msgstr ""
|
msgstr "<0/> द्वारा स्टार्टर पैक"
|
||||||
|
|
||||||
#: src/components/StarterPack/StarterPackCard.tsx:80
|
#: src/components/StarterPack/StarterPackCard.tsx:80
|
||||||
#: src/view/com/profile/ProfileSubpageHeader.tsx:180
|
#: src/view/com/profile/ProfileSubpageHeader.tsx:180
|
||||||
@@ -7560,12 +7560,12 @@ msgstr "केवल टैग"
|
|||||||
|
|
||||||
#: src/screens/Settings/AppIconSettings/index.tsx:216
|
#: src/screens/Settings/AppIconSettings/index.tsx:216
|
||||||
msgid "Tap to change app icon"
|
msgid "Tap to change app icon"
|
||||||
msgstr ""
|
msgstr "ऐप आइकॉन बदलने के लिए टैप करें"
|
||||||
|
|
||||||
#: src/view/com/composer/text-input/web/EmojiPicker.web.tsx:138
|
#: src/view/com/composer/text-input/web/EmojiPicker.web.tsx:138
|
||||||
#: src/view/com/composer/text-input/web/EmojiPicker.web.tsx:174
|
#: src/view/com/composer/text-input/web/EmojiPicker.web.tsx:174
|
||||||
msgid "Tap to close the emoji picker"
|
msgid "Tap to close the emoji picker"
|
||||||
msgstr ""
|
msgstr "इमोजी चयन बंद करने के लिए टैप करें"
|
||||||
|
|
||||||
#: src/components/ProgressGuide/Toast.tsx:156
|
#: src/components/ProgressGuide/Toast.tsx:156
|
||||||
msgid "Tap to dismiss"
|
msgid "Tap to dismiss"
|
||||||
@@ -7590,7 +7590,7 @@ msgstr "पूरी छवि देखने के लिए दबाएँ"
|
|||||||
|
|
||||||
#: src/state/shell/progress-guide.tsx:233
|
#: src/state/shell/progress-guide.tsx:233
|
||||||
msgid "Task complete - 10 follows!"
|
msgid "Task complete - 10 follows!"
|
||||||
msgstr ""
|
msgstr "कार्य समाप्त - 10 फ़ॉलो!"
|
||||||
|
|
||||||
#: src/state/shell/progress-guide.tsx:223
|
#: src/state/shell/progress-guide.tsx:223
|
||||||
msgid "Task complete - 10 likes!"
|
msgid "Task complete - 10 likes!"
|
||||||
@@ -7693,7 +7693,7 @@ msgstr "अनअवरुद्ध करने के बाद खाता
|
|||||||
#: src/screens/Settings/AppIconSettings/index.tsx:41
|
#: src/screens/Settings/AppIconSettings/index.tsx:41
|
||||||
#: src/screens/Settings/AppIconSettings/index.tsx:222
|
#: src/screens/Settings/AppIconSettings/index.tsx:222
|
||||||
msgid "The app will be restarted"
|
msgid "The app will be restarted"
|
||||||
msgstr ""
|
msgstr "ऐप को फिर से शुरू किया जाएगा"
|
||||||
|
|
||||||
#: src/components/moderation/ModerationDetailsDialog.tsx:127
|
#: src/components/moderation/ModerationDetailsDialog.tsx:127
|
||||||
#~ msgid "the author"
|
#~ msgid "the author"
|
||||||
@@ -8006,7 +8006,7 @@ msgstr "<0>{0}</0> द्वारा बनाई गई इस सूची
|
|||||||
|
|
||||||
#: src/view/screens/ProfileList.tsx:933
|
#: src/view/screens/ProfileList.tsx:933
|
||||||
msgid "This list is empty."
|
msgid "This list is empty."
|
||||||
msgstr ""
|
msgstr "यह सूची खाली है।"
|
||||||
|
|
||||||
#: src/screens/Profile/ErrorState.tsx:40
|
#: src/screens/Profile/ErrorState.tsx:40
|
||||||
msgid "This moderation service is unavailable. See below for more details. If this issue persists, contact us."
|
msgid "This moderation service is unavailable. See below for more details. If this issue persists, contact us."
|
||||||
@@ -8105,7 +8105,7 @@ msgstr "यह आपके पोस्ट को इस क्वोट पो
|
|||||||
#: src/view/com/post-thread/PostThread.tsx:606
|
#: src/view/com/post-thread/PostThread.tsx:606
|
||||||
#: src/view/com/post-thread/PostThread.tsx:609
|
#: src/view/com/post-thread/PostThread.tsx:609
|
||||||
msgid "Thread options"
|
msgid "Thread options"
|
||||||
msgstr ""
|
msgstr "थ्रेड विकल्प"
|
||||||
|
|
||||||
#: src/screens/Settings/ContentAndMediaSettings.tsx:66
|
#: src/screens/Settings/ContentAndMediaSettings.tsx:66
|
||||||
#: src/screens/Settings/ContentAndMediaSettings.tsx:69
|
#: src/screens/Settings/ContentAndMediaSettings.tsx:69
|
||||||
@@ -8119,7 +8119,7 @@ msgstr "थ्रेड प्राथमिकताएँ"
|
|||||||
#: src/view/com/post-thread/PostThread.tsx:636
|
#: src/view/com/post-thread/PostThread.tsx:636
|
||||||
#: src/view/com/post-thread/PostThread.tsx:641
|
#: src/view/com/post-thread/PostThread.tsx:641
|
||||||
msgid "Threaded"
|
msgid "Threaded"
|
||||||
msgstr ""
|
msgstr "थ्रेड"
|
||||||
|
|
||||||
#: src/screens/Settings/ThreadPreferences.tsx:142
|
#: src/screens/Settings/ThreadPreferences.tsx:142
|
||||||
msgid "Threaded mode"
|
msgid "Threaded mode"
|
||||||
@@ -8135,7 +8135,7 @@ msgstr "थ्रेड प्राथमिकताएँ"
|
|||||||
|
|
||||||
#: src/view/com/util/post-embeds/VideoEmbedInner/TimeIndicator.tsx:33
|
#: src/view/com/util/post-embeds/VideoEmbedInner/TimeIndicator.tsx:33
|
||||||
msgid "Time remaining: {time} seconds"
|
msgid "Time remaining: {time} seconds"
|
||||||
msgstr ""
|
msgstr "समय बाक़ी: {time} सेकंड"
|
||||||
|
|
||||||
#: src/screens/Settings/components/DisableEmail2FADialog.tsx:99
|
#: src/screens/Settings/components/DisableEmail2FADialog.tsx:99
|
||||||
msgid "To disable the email 2FA method, please verify your access to the email address."
|
msgid "To disable the email 2FA method, please verify your access to the email address."
|
||||||
@@ -8173,7 +8173,7 @@ msgstr "बहतरीन"
|
|||||||
|
|
||||||
#: src/Navigation.tsx:383
|
#: src/Navigation.tsx:383
|
||||||
msgid "Topic"
|
msgid "Topic"
|
||||||
msgstr ""
|
msgstr "विषय"
|
||||||
|
|
||||||
#: src/view/com/modals/EditImage.tsx:272
|
#: src/view/com/modals/EditImage.tsx:272
|
||||||
#~ msgid "Transformations"
|
#~ msgid "Transformations"
|
||||||
@@ -8191,7 +8191,7 @@ msgstr "अनुवाद करें"
|
|||||||
#: src/screens/Search/components/ExploreTrendingTopics.tsx:69
|
#: src/screens/Search/components/ExploreTrendingTopics.tsx:69
|
||||||
#: src/view/shell/desktop/SidebarTrendingTopics.tsx:59
|
#: src/view/shell/desktop/SidebarTrendingTopics.tsx:59
|
||||||
msgid "Trending"
|
msgid "Trending"
|
||||||
msgstr ""
|
msgstr "रुझान"
|
||||||
|
|
||||||
#: src/view/com/util/error/ErrorScreen.tsx:103
|
#: src/view/com/util/error/ErrorScreen.tsx:103
|
||||||
msgctxt "action"
|
msgctxt "action"
|
||||||
@@ -8285,7 +8285,7 @@ msgstr "रीपोस्ट पूर्ववत करें"
|
|||||||
|
|
||||||
#: src/view/com/util/post-ctrls/RepostButton.tsx:68
|
#: src/view/com/util/post-ctrls/RepostButton.tsx:68
|
||||||
msgid "Undo repost ({0, plural, one {# repost} other {# reposts}})"
|
msgid "Undo repost ({0, plural, one {# repost} other {# reposts}})"
|
||||||
msgstr ""
|
msgstr "रीपोस्ट पूर्ववत करें ({0, plural, one {# रीपोस्ट} other {# रीपोस्ट}})"
|
||||||
|
|
||||||
#: src/view/com/profile/FollowButton.tsx:60
|
#: src/view/com/profile/FollowButton.tsx:60
|
||||||
msgctxt "action"
|
msgctxt "action"
|
||||||
@@ -8307,11 +8307,11 @@ msgstr "खाता अनफ़ॉलो करें"
|
|||||||
|
|
||||||
#: src/screens/Profile/components/ProfileFeedHeader.tsx:514
|
#: src/screens/Profile/components/ProfileFeedHeader.tsx:514
|
||||||
msgid "Unlike"
|
msgid "Unlike"
|
||||||
msgstr ""
|
msgstr "नापसंद करें"
|
||||||
|
|
||||||
#: src/view/com/util/post-ctrls/PostCtrls.tsx:305
|
#: src/view/com/util/post-ctrls/PostCtrls.tsx:305
|
||||||
msgid "Unlike ({0, plural, one {# like} other {# likes}})"
|
msgid "Unlike ({0, plural, one {# like} other {# likes}})"
|
||||||
msgstr ""
|
msgstr "नापसंद करें ({0, plural, one {# पसंद} other {# पसंद}})"
|
||||||
|
|
||||||
#: src/view/screens/ProfileFeed.tsx:576
|
#: src/view/screens/ProfileFeed.tsx:576
|
||||||
#~ msgid "Unlike this feed"
|
#~ msgid "Unlike this feed"
|
||||||
@@ -8361,7 +8361,7 @@ msgstr "पिन से हटाएँ"
|
|||||||
#: src/screens/Profile/components/ProfileFeedHeader.tsx:519
|
#: src/screens/Profile/components/ProfileFeedHeader.tsx:519
|
||||||
#: src/screens/Profile/components/ProfileFeedHeader.tsx:526
|
#: src/screens/Profile/components/ProfileFeedHeader.tsx:526
|
||||||
msgid "Unpin feed"
|
msgid "Unpin feed"
|
||||||
msgstr ""
|
msgstr "फ़ीड को पिन से हटाएँ"
|
||||||
|
|
||||||
#: src/screens/Profile/components/ProfileFeedHeader.tsx:309
|
#: src/screens/Profile/components/ProfileFeedHeader.tsx:309
|
||||||
#: src/screens/Profile/components/ProfileFeedHeader.tsx:311
|
#: src/screens/Profile/components/ProfileFeedHeader.tsx:311
|
||||||
@@ -8379,7 +8379,7 @@ msgstr "मॉडरेशन सूची को पिन से हटाए
|
|||||||
|
|
||||||
#: src/screens/Profile/components/ProfileFeedHeader.tsx:164
|
#: src/screens/Profile/components/ProfileFeedHeader.tsx:164
|
||||||
msgid "Unpinned {0} from Home"
|
msgid "Unpinned {0} from Home"
|
||||||
msgstr ""
|
msgstr "{0} को होम पिन से हटाया गया"
|
||||||
|
|
||||||
#: src/view/screens/ProfileList.tsx:352
|
#: src/view/screens/ProfileList.tsx:352
|
||||||
msgid "Unpinned from your feeds"
|
msgid "Unpinned from your feeds"
|
||||||
@@ -8404,11 +8404,11 @@ msgstr "सूची की सदस्यता छोड़ी गई"
|
|||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:766
|
#: src/view/com/composer/Composer.tsx:766
|
||||||
msgid "Unsupported video type"
|
msgid "Unsupported video type"
|
||||||
msgstr ""
|
msgstr "असमर्थित वीडियो प्रकार"
|
||||||
|
|
||||||
#: src/view/com/composer/videos/SelectVideoBtn.tsx:66
|
#: src/view/com/composer/videos/SelectVideoBtn.tsx:66
|
||||||
msgid "Unsupported video type: {0}"
|
msgid "Unsupported video type: {0}"
|
||||||
msgstr ""
|
msgstr "असमर्थित वीडियो प्रकार: {0}"
|
||||||
|
|
||||||
#: src/view/com/composer/videos/SelectVideoBtn.tsx:72
|
#: src/view/com/composer/videos/SelectVideoBtn.tsx:72
|
||||||
#~ msgid "Unsupported video type: {mimeType}"
|
#~ msgid "Unsupported video type: {mimeType}"
|
||||||
@@ -8815,7 +8815,7 @@ msgstr "साइट पर जाएँ"
|
|||||||
|
|
||||||
#: src/view/com/util/post-embeds/VideoEmbedInner/web-controls/VolumeControl.tsx:80
|
#: src/view/com/util/post-embeds/VideoEmbedInner/web-controls/VolumeControl.tsx:80
|
||||||
msgid "Volume"
|
msgid "Volume"
|
||||||
msgstr ""
|
msgstr "वॉल्यूम"
|
||||||
|
|
||||||
#: src/components/moderation/LabelPreference.tsx:136
|
#: src/components/moderation/LabelPreference.tsx:136
|
||||||
#: src/lib/moderation/useLabelBehaviorDescription.ts:17
|
#: src/lib/moderation/useLabelBehaviorDescription.ts:17
|
||||||
@@ -8837,7 +8837,7 @@ msgstr "हमें इस हैशटैग के लिए कोई पर
|
|||||||
|
|
||||||
#: src/screens/Topic.tsx:178
|
#: src/screens/Topic.tsx:178
|
||||||
msgid "We couldn't find any results for that topic."
|
msgid "We couldn't find any results for that topic."
|
||||||
msgstr ""
|
msgstr "उस विषय से जुड़े हमें कोई परिणाम नहीं मिले।"
|
||||||
|
|
||||||
#: src/screens/Messages/Conversation.tsx:103
|
#: src/screens/Messages/Conversation.tsx:103
|
||||||
msgid "We couldn't load this conversation"
|
msgid "We couldn't load this conversation"
|
||||||
@@ -8951,7 +8951,7 @@ msgstr "आप अपने स्टार्टर पैक को क्य
|
|||||||
|
|
||||||
#: src/screens/Search/components/ExploreTrendingTopics.tsx:79
|
#: src/screens/Search/components/ExploreTrendingTopics.tsx:79
|
||||||
msgid "What people are posting about."
|
msgid "What people are posting about."
|
||||||
msgstr ""
|
msgstr "किसके बारे में लोग पोस्ट कर रहे हैं।"
|
||||||
|
|
||||||
#: src/view/com/auth/SplashScreen.tsx:38
|
#: src/view/com/auth/SplashScreen.tsx:38
|
||||||
#: src/view/com/auth/SplashScreen.web.tsx:99
|
#: src/view/com/auth/SplashScreen.web.tsx:99
|
||||||
@@ -9114,7 +9114,7 @@ msgstr "आप लॉग इन जारी रखने के लिए अ
|
|||||||
#: src/screens/Search/components/ExploreTrendingTopics.tsx:136
|
#: src/screens/Search/components/ExploreTrendingTopics.tsx:136
|
||||||
#: src/view/shell/desktop/SidebarTrendingTopics.tsx:109
|
#: src/view/shell/desktop/SidebarTrendingTopics.tsx:109
|
||||||
msgid "You can update this later from your settings."
|
msgid "You can update this later from your settings."
|
||||||
msgstr ""
|
msgstr "आप इसे बाद में अपने सेटिंग में बदल सकते हैं।"
|
||||||
|
|
||||||
#: src/view/com/profile/ProfileFollowers.tsx:94
|
#: src/view/com/profile/ProfileFollowers.tsx:94
|
||||||
msgid "You do not have any followers."
|
msgid "You do not have any followers."
|
||||||
@@ -9348,7 +9348,7 @@ msgstr "आपने इस पोस्ट में से एक शब्द
|
|||||||
|
|
||||||
#: src/state/shell/progress-guide.tsx:234
|
#: src/state/shell/progress-guide.tsx:234
|
||||||
msgid "You've found some people to follow"
|
msgid "You've found some people to follow"
|
||||||
msgstr ""
|
msgstr "आपने फ़ॉलो करने के लिए कुछ लोगों को ढूँढा है"
|
||||||
|
|
||||||
#: src/view/com/posts/FollowingEndOfFeed.tsx:44
|
#: src/view/com/posts/FollowingEndOfFeed.tsx:44
|
||||||
msgid "You've reached the end of your feed! Find some more accounts to follow."
|
msgid "You've reached the end of your feed! Find some more accounts to follow."
|
||||||
@@ -9396,7 +9396,7 @@ msgstr "आपका चयन सहेजा जाएगा, पर सेट
|
|||||||
|
|
||||||
#: src/screens/Settings/components/ChangeHandleDialog.tsx:496
|
#: src/screens/Settings/components/ChangeHandleDialog.tsx:496
|
||||||
msgid "Your current handle <0>{0}</0> will automatically remain reserved for you. You can switch back to it at any time from this account."
|
msgid "Your current handle <0>{0}</0> will automatically remain reserved for you. You can switch back to it at any time from this account."
|
||||||
msgstr ""
|
msgstr "आपका वर्तमान हैंडल <0>{0}</0> आपके लिए आरक्षित रहेगा। आप इस खाते से कभी भी उस हैंडल पर वापस जा सकते हैं।"
|
||||||
|
|
||||||
#: src/screens/Login/ForgotPasswordForm.tsx:51
|
#: src/screens/Login/ForgotPasswordForm.tsx:51
|
||||||
#: src/screens/Signup/state.ts:203
|
#: src/screens/Signup/state.ts:203
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+152
-152
@@ -8,8 +8,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Italian localization\n"
|
"Project-Id-Version: Italian localization\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-01-24 00:43+0000\n"
|
"POT-Creation-Date: 2025-02-04 00:43+0000\n"
|
||||||
"PO-Revision-Date: 2025-01-24 17:53+0000\n"
|
"PO-Revision-Date: 2025-02-04 07:28+0000\n"
|
||||||
"Last-Translator: Michele Locati <michele@locati.it>, 2025\n"
|
"Last-Translator: Michele Locati <michele@locati.it>, 2025\n"
|
||||||
"Language-Team: Italian (https://app.transifex.com/mlocati/teams/201833/it/)\n"
|
"Language-Team: Italian (https://app.transifex.com/mlocati/teams/201833/it/)\n"
|
||||||
"Language: it\n"
|
"Language: it\n"
|
||||||
@@ -23,7 +23,7 @@ msgstr ""
|
|||||||
msgid "(active)"
|
msgid "(active)"
|
||||||
msgstr "(attivo)"
|
msgstr "(attivo)"
|
||||||
|
|
||||||
#: src/screens/Messages/components/ChatListItem.tsx:139
|
#: src/screens/Messages/components/ChatListItem.tsx:145
|
||||||
msgid "(contains embedded content)"
|
msgid "(contains embedded content)"
|
||||||
msgstr "(contiene allegati)"
|
msgstr "(contiene allegati)"
|
||||||
|
|
||||||
@@ -374,9 +374,9 @@ msgstr "7 giorni"
|
|||||||
#: src/screens/Settings/Settings.tsx:215
|
#: src/screens/Settings/Settings.tsx:215
|
||||||
#: src/screens/Settings/Settings.tsx:218
|
#: src/screens/Settings/Settings.tsx:218
|
||||||
msgid "About"
|
msgid "About"
|
||||||
msgstr "Informazioni su"
|
msgstr "Risorse aggiuntive"
|
||||||
|
|
||||||
#: src/view/screens/Search/Search.tsx:858
|
#: src/view/screens/Search/Search.tsx:864
|
||||||
msgid "Access navigation links and settings"
|
msgid "Access navigation links and settings"
|
||||||
msgstr "Accedi alle impostazioni di navigazione"
|
msgstr "Accedi alle impostazioni di navigazione"
|
||||||
|
|
||||||
@@ -728,10 +728,10 @@ msgstr "Si è verificato un problema nell'aprire la chat"
|
|||||||
|
|
||||||
#: src/components/hooks/useFollowMethods.ts:35
|
#: src/components/hooks/useFollowMethods.ts:35
|
||||||
#: src/components/hooks/useFollowMethods.ts:50
|
#: src/components/hooks/useFollowMethods.ts:50
|
||||||
#: src/components/ProfileCard.tsx:330
|
#: src/components/ProfileCard.tsx:333
|
||||||
#: src/components/ProfileCard.tsx:351
|
#: src/components/ProfileCard.tsx:354
|
||||||
#: src/view/com/profile/FollowButton.tsx:35
|
#: src/view/com/profile/FollowButton.tsx:38
|
||||||
#: src/view/com/profile/FollowButton.tsx:45
|
#: src/view/com/profile/FollowButton.tsx:48
|
||||||
msgid "An issue occurred, please try again."
|
msgid "An issue occurred, please try again."
|
||||||
msgstr "Si è verificato un problema, riprova."
|
msgstr "Si è verificato un problema, riprova."
|
||||||
|
|
||||||
@@ -928,7 +928,7 @@ msgstr "Le opzioni di riproduzione automatica sono state spostate nelle <0>impos
|
|||||||
msgid "Autoplay videos and GIFs"
|
msgid "Autoplay videos and GIFs"
|
||||||
msgstr "Riproduci automaticamente video e GIF"
|
msgstr "Riproduci automaticamente video e GIF"
|
||||||
|
|
||||||
#: src/components/dms/MessagesListHeader.tsx:74
|
#: src/components/dms/MessagesListHeader.tsx:81
|
||||||
#: src/components/moderation/LabelsOnMeDialog.tsx:290
|
#: src/components/moderation/LabelsOnMeDialog.tsx:290
|
||||||
#: src/components/moderation/LabelsOnMeDialog.tsx:291
|
#: src/components/moderation/LabelsOnMeDialog.tsx:291
|
||||||
#: src/screens/Login/ChooseAccountForm.tsx:90
|
#: src/screens/Login/ChooseAccountForm.tsx:90
|
||||||
@@ -962,7 +962,7 @@ msgstr "Prima di creare uno starter pack, devi verificare la tua email."
|
|||||||
|
|
||||||
#: src/components/dms/dialogs/NewChatDialog.tsx:79
|
#: src/components/dms/dialogs/NewChatDialog.tsx:79
|
||||||
#: src/components/dms/MessageProfileButton.tsx:89
|
#: src/components/dms/MessageProfileButton.tsx:89
|
||||||
#: src/screens/Messages/Conversation.tsx:209
|
#: src/screens/Messages/Conversation.tsx:204
|
||||||
msgid "Before you may message another user, you must first verify your email."
|
msgid "Before you may message another user, you must first verify your email."
|
||||||
msgstr "Prima di poter inviare un messaggio a un altro utente, devi verificare la tua email."
|
msgstr "Prima di poter inviare un messaggio a un altro utente, devi verificare la tua email."
|
||||||
|
|
||||||
@@ -971,7 +971,7 @@ msgstr "Prima di poter inviare un messaggio a un altro utente, devi verificare l
|
|||||||
msgid "BETA"
|
msgid "BETA"
|
||||||
msgstr "BETA"
|
msgstr "BETA"
|
||||||
|
|
||||||
#: src/components/dialogs/BirthDateSettings.tsx:106
|
#: src/components/dialogs/BirthDateSettings.tsx:102
|
||||||
#: src/screens/Settings/AccountSettings.tsx:109
|
#: src/screens/Settings/AccountSettings.tsx:109
|
||||||
msgid "Birthday"
|
msgid "Birthday"
|
||||||
msgstr "Compleanno"
|
msgstr "Compleanno"
|
||||||
@@ -982,8 +982,8 @@ msgstr "Compleanno"
|
|||||||
msgid "Block"
|
msgid "Block"
|
||||||
msgstr "Blocca"
|
msgstr "Blocca"
|
||||||
|
|
||||||
#: src/components/dms/ConvoMenu.tsx:191
|
#: src/components/dms/ConvoMenu.tsx:250
|
||||||
#: src/components/dms/ConvoMenu.tsx:195
|
#: src/components/dms/ConvoMenu.tsx:253
|
||||||
#: src/view/com/util/forms/PostDropdownBtnMenuItems.tsx:603
|
#: src/view/com/util/forms/PostDropdownBtnMenuItems.tsx:603
|
||||||
#: src/view/com/util/forms/PostDropdownBtnMenuItems.tsx:605
|
#: src/view/com/util/forms/PostDropdownBtnMenuItems.tsx:605
|
||||||
msgid "Block account"
|
msgid "Block account"
|
||||||
@@ -1070,8 +1070,8 @@ msgstr "Il blocco non impedirà l'applicazione delle etichette al tuo account, m
|
|||||||
msgid "Blog"
|
msgid "Blog"
|
||||||
msgstr "Blog"
|
msgstr "Blog"
|
||||||
|
|
||||||
#: src/view/com/auth/server-input/index.tsx:92
|
#: src/view/com/auth/server-input/index.tsx:132
|
||||||
#: src/view/com/auth/server-input/index.tsx:94
|
#: src/view/com/auth/server-input/index.tsx:133
|
||||||
msgid "Bluesky"
|
msgid "Bluesky"
|
||||||
msgstr "Bluesky"
|
msgstr "Bluesky"
|
||||||
|
|
||||||
@@ -1079,13 +1079,13 @@ msgstr "Bluesky"
|
|||||||
msgid "Bluesky cannot confirm the authenticity of the claimed date."
|
msgid "Bluesky cannot confirm the authenticity of the claimed date."
|
||||||
msgstr "Bluesky non può confermare l'autenticità della data dichiarata."
|
msgstr "Bluesky non può confermare l'autenticità della data dichiarata."
|
||||||
|
|
||||||
#: src/view/com/auth/server-input/index.tsx:172
|
#: src/view/com/auth/server-input/index.tsx:208
|
||||||
msgid "Bluesky is an open network where you can choose your hosting provider. If you're a developer, you can host your own server."
|
msgid "Bluesky is an open network where you can choose your hosting provider. If you're a developer, you can host your own server."
|
||||||
msgstr "Bluesky è una rete aperta dove puoi scegliere il fornitore che ospita i tuoi dati. Se sei uno sviluppatore, puoi utilizzare il tuo server."
|
msgstr "Bluesky è una rete aperta dove puoi scegliere il fornitore che ospita i tuoi dati. Se sei uno sviluppatore, puoi utilizzare il tuo server."
|
||||||
|
|
||||||
#: src/view/com/auth/server-input/index.tsx:109
|
#: src/view/com/auth/server-input/index.tsx:145
|
||||||
msgid "Bluesky is an open network where you can choose your own provider. If you're new here, we recommend sticking with the default Bluesky Social option."
|
msgid "Bluesky is an open network where you can choose your own provider. If you're new here, we recommend sticking with the default Bluesky Social option."
|
||||||
msgstr "Bluesky è una rete aperta che ti permette di scegliere il fornitore dei tuoi dati. Se sei un nuovo utente, ti consigliamo di iniziare con l'opzione predefinita Bluesky Social."
|
msgstr "Bluesky è una rete aperta che ti permette di scegliere chi ospita i tuoi dati. Se sei un nuovo utente, ti consigliamo di iniziare con l'opzione predefinita Bluesky Social."
|
||||||
|
|
||||||
#: src/components/ProgressGuide/List.tsx:53
|
#: src/components/ProgressGuide/List.tsx:53
|
||||||
#: src/components/ProgressGuide/List.tsx:70
|
#: src/components/ProgressGuide/List.tsx:70
|
||||||
@@ -1094,7 +1094,7 @@ msgstr "Bluesky è meglio con gli amici!"
|
|||||||
|
|
||||||
#: src/screens/Takendown.tsx:217
|
#: src/screens/Takendown.tsx:217
|
||||||
msgid "Bluesky Social Terms of Service"
|
msgid "Bluesky Social Terms of Service"
|
||||||
msgstr "Termini di servizio di Bluesky Social"
|
msgstr "Termini di servizio di Bluesky"
|
||||||
|
|
||||||
#: src/components/StarterPack/ProfileStarterPacks.tsx:299
|
#: src/components/StarterPack/ProfileStarterPacks.tsx:299
|
||||||
msgid "Bluesky will choose a set of recommended accounts from people in your network."
|
msgid "Bluesky will choose a set of recommended accounts from people in your network."
|
||||||
@@ -1125,23 +1125,23 @@ msgstr "Sfoca le immagini e filtra dai feed"
|
|||||||
msgid "Books"
|
msgid "Books"
|
||||||
msgstr "Libri"
|
msgstr "Libri"
|
||||||
|
|
||||||
#: src/components/FeedInterstitials.tsx:349
|
#: src/components/FeedInterstitials.tsx:370
|
||||||
msgid "Browse more accounts on the Explore page"
|
msgid "Browse more accounts on the Explore page"
|
||||||
msgstr "Scopri altri account dalla Ricerca"
|
msgstr "Scopri altri account dalla Ricerca"
|
||||||
|
|
||||||
#: src/components/FeedInterstitials.tsx:486
|
#: src/components/FeedInterstitials.tsx:507
|
||||||
msgid "Browse more feeds on the Explore page"
|
msgid "Browse more feeds on the Explore page"
|
||||||
msgstr "Scopri nuovi feed dalla Ricerca"
|
msgstr "Scopri nuovi feed dalla Ricerca"
|
||||||
|
|
||||||
#: src/components/FeedInterstitials.tsx:330
|
#: src/components/FeedInterstitials.tsx:351
|
||||||
#: src/components/FeedInterstitials.tsx:333
|
#: src/components/FeedInterstitials.tsx:354
|
||||||
#: src/components/FeedInterstitials.tsx:467
|
#: src/components/FeedInterstitials.tsx:488
|
||||||
#: src/components/FeedInterstitials.tsx:470
|
#: src/components/FeedInterstitials.tsx:491
|
||||||
msgid "Browse more suggestions"
|
msgid "Browse more suggestions"
|
||||||
msgstr "Scopri nuovi suggerimenti"
|
msgstr "Scopri nuovi suggerimenti"
|
||||||
|
|
||||||
#: src/components/FeedInterstitials.tsx:357
|
#: src/components/FeedInterstitials.tsx:378
|
||||||
#: src/components/FeedInterstitials.tsx:495
|
#: src/components/FeedInterstitials.tsx:516
|
||||||
msgid "Browse more suggestions on the Explore page"
|
msgid "Browse more suggestions on the Explore page"
|
||||||
msgstr "Scopri nuovi suggerimenti dalla Ricerca"
|
msgstr "Scopri nuovi suggerimenti dalla Ricerca"
|
||||||
|
|
||||||
@@ -1218,7 +1218,7 @@ msgstr "Fotocamera"
|
|||||||
#: src/view/com/modals/VerifyEmail.tsx:255
|
#: src/view/com/modals/VerifyEmail.tsx:255
|
||||||
#: src/view/com/modals/VerifyEmail.tsx:261
|
#: src/view/com/modals/VerifyEmail.tsx:261
|
||||||
#: src/view/com/util/post-ctrls/RepostButton.tsx:213
|
#: src/view/com/util/post-ctrls/RepostButton.tsx:213
|
||||||
#: src/view/screens/Search/Search.tsx:887
|
#: src/view/screens/Search/Search.tsx:893
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:209
|
#: src/view/shell/desktop/LeftNav.tsx:209
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr "Annulla"
|
msgstr "Annulla"
|
||||||
@@ -1252,7 +1252,7 @@ msgid "Cancel reactivation and log out"
|
|||||||
msgstr "Annulla la riattivazione e disconnettiti"
|
msgstr "Annulla la riattivazione e disconnettiti"
|
||||||
|
|
||||||
#: src/view/com/modals/ListAddRemoveUsers.tsx:88
|
#: src/view/com/modals/ListAddRemoveUsers.tsx:88
|
||||||
#: src/view/screens/Search/Search.tsx:879
|
#: src/view/screens/Search/Search.tsx:885
|
||||||
msgid "Cancel search"
|
msgid "Cancel search"
|
||||||
msgstr "Annulla la ricerca"
|
msgstr "Annulla la ricerca"
|
||||||
|
|
||||||
@@ -1331,14 +1331,14 @@ msgstr "Modifica il tuo indirizzo email"
|
|||||||
msgid "Chat"
|
msgid "Chat"
|
||||||
msgstr "Messaggi"
|
msgstr "Messaggi"
|
||||||
|
|
||||||
#: src/components/dms/ConvoMenu.tsx:85
|
#: src/components/dms/ConvoMenu.tsx:179
|
||||||
msgid "Chat muted"
|
msgid "Chat muted"
|
||||||
msgstr "Conversazione silenziata"
|
msgstr "Conversazione silenziata"
|
||||||
|
|
||||||
#: src/components/dms/ConvoMenu.tsx:115
|
#: src/components/dms/ConvoMenu.tsx:78
|
||||||
#: src/components/dms/MessageMenu.tsx:81
|
#: src/components/dms/MessageMenu.tsx:81
|
||||||
#: src/Navigation.tsx:394
|
#: src/Navigation.tsx:394
|
||||||
#: src/screens/Messages/ChatList.tsx:254
|
#: src/screens/Messages/ChatList.tsx:253
|
||||||
msgid "Chat settings"
|
msgid "Chat settings"
|
||||||
msgstr "Impostazioni chat"
|
msgstr "Impostazioni chat"
|
||||||
|
|
||||||
@@ -1346,7 +1346,7 @@ msgstr "Impostazioni chat"
|
|||||||
msgid "Chat Settings"
|
msgid "Chat Settings"
|
||||||
msgstr "Impostazioni chat"
|
msgstr "Impostazioni chat"
|
||||||
|
|
||||||
#: src/components/dms/ConvoMenu.tsx:87
|
#: src/components/dms/ConvoMenu.tsx:181
|
||||||
msgid "Chat unmuted"
|
msgid "Chat unmuted"
|
||||||
msgstr "Conversazione riattivata"
|
msgstr "Conversazione riattivata"
|
||||||
|
|
||||||
@@ -1391,12 +1391,12 @@ msgstr "Scegli gli algoritmi che compilano i tuoi feed personalizzati."
|
|||||||
msgid "Choose this color as your avatar"
|
msgid "Choose this color as your avatar"
|
||||||
msgstr "Scegli questo colore per il tuo avatar"
|
msgstr "Scegli questo colore per il tuo avatar"
|
||||||
|
|
||||||
#: src/view/com/auth/server-input/index.tsx:86
|
#: src/view/com/auth/server-input/index.tsx:126
|
||||||
msgid "Choose your account provider"
|
msgid "Choose your account provider"
|
||||||
msgstr "Seleziona il fornitore del tuo account"
|
msgstr "Scegli il fornitore del tuo account"
|
||||||
|
|
||||||
#: src/view/screens/Feeds.tsx:728
|
#: src/view/screens/Feeds.tsx:728
|
||||||
#: src/view/screens/Search/Explore.tsx:424
|
#: src/view/screens/Search/Explore.tsx:427
|
||||||
msgid "Choose your own timeline! Feeds built by the community help you find content you love."
|
msgid "Choose your own timeline! Feeds built by the community help you find content you love."
|
||||||
msgstr "Personalizza la tua cronologia! I feed creati dalla collettività ti permettono di scoprire i contenuti di tuo interesse."
|
msgstr "Personalizza la tua cronologia! I feed creati dalla collettività ti permettono di scoprire i contenuti di tuo interesse."
|
||||||
|
|
||||||
@@ -1547,7 +1547,7 @@ msgstr "Linee guida della community"
|
|||||||
|
|
||||||
#: src/screens/Onboarding/StepFinished.tsx:300
|
#: src/screens/Onboarding/StepFinished.tsx:300
|
||||||
msgid "Complete onboarding and start using your account"
|
msgid "Complete onboarding and start using your account"
|
||||||
msgstr "Completa l'incorporazione e inizia a usare il tuo account"
|
msgstr "Completa la registrazione e inizia a usare il tuo account"
|
||||||
|
|
||||||
#: src/screens/Signup/index.tsx:144
|
#: src/screens/Signup/index.tsx:144
|
||||||
msgid "Complete the challenge"
|
msgid "Complete the challenge"
|
||||||
@@ -1700,7 +1700,7 @@ msgstr "Continua thread..."
|
|||||||
msgid "Continue to next step"
|
msgid "Continue to next step"
|
||||||
msgstr "Vai al passaggio successivo"
|
msgstr "Vai al passaggio successivo"
|
||||||
|
|
||||||
#: src/screens/Messages/components/ChatListItem.tsx:173
|
#: src/screens/Messages/components/ChatListItem.tsx:179
|
||||||
msgid "Conversation deleted"
|
msgid "Conversation deleted"
|
||||||
msgstr "Conversazione eliminata"
|
msgstr "Conversazione eliminata"
|
||||||
|
|
||||||
@@ -1807,7 +1807,7 @@ msgstr "Non è stato possibile caricare il feed"
|
|||||||
msgid "Could not load list"
|
msgid "Could not load list"
|
||||||
msgstr "Non è stato possibile caricare la lista"
|
msgstr "Non è stato possibile caricare la lista"
|
||||||
|
|
||||||
#: src/components/dms/ConvoMenu.tsx:91
|
#: src/components/dms/ConvoMenu.tsx:185
|
||||||
msgid "Could not mute chat"
|
msgid "Could not mute chat"
|
||||||
msgstr "Errore nel silenziare la conversazione"
|
msgstr "Errore nel silenziare la conversazione"
|
||||||
|
|
||||||
@@ -1842,7 +1842,7 @@ msgstr "Crea uno starter pack per me"
|
|||||||
#: src/view/shell/NavSignupCard.tsx:47
|
#: src/view/shell/NavSignupCard.tsx:47
|
||||||
#: src/view/shell/NavSignupCard.tsx:52
|
#: src/view/shell/NavSignupCard.tsx:52
|
||||||
msgid "Create account"
|
msgid "Create account"
|
||||||
msgstr "Crea un account"
|
msgstr "Crea account"
|
||||||
|
|
||||||
#: src/screens/Signup/index.tsx:93
|
#: src/screens/Signup/index.tsx:93
|
||||||
msgid "Create Account"
|
msgid "Create Account"
|
||||||
@@ -1883,8 +1883,8 @@ msgstr "L'autore è stato bloccato"
|
|||||||
msgid "Culture"
|
msgid "Culture"
|
||||||
msgstr "Cultura"
|
msgstr "Cultura"
|
||||||
|
|
||||||
#: src/view/com/auth/server-input/index.tsx:100
|
#: src/view/com/auth/server-input/index.tsx:138
|
||||||
#: src/view/com/auth/server-input/index.tsx:102
|
#: src/view/com/auth/server-input/index.tsx:139
|
||||||
msgid "Custom"
|
msgid "Custom"
|
||||||
msgstr "Personalizzato"
|
msgstr "Personalizzato"
|
||||||
|
|
||||||
@@ -1897,7 +1897,7 @@ msgstr "Personalizza chi può interagire con questo post."
|
|||||||
msgid "Dark"
|
msgid "Dark"
|
||||||
msgstr "Scuro"
|
msgstr "Scuro"
|
||||||
|
|
||||||
#: src/view/screens/Debug.tsx:70
|
#: src/view/screens/Debug.tsx:69
|
||||||
msgid "Dark mode"
|
msgid "Dark mode"
|
||||||
msgstr "Aspetto scuro"
|
msgstr "Aspetto scuro"
|
||||||
|
|
||||||
@@ -1919,7 +1919,7 @@ msgstr "Disattiva account"
|
|||||||
msgid "Debug Moderation"
|
msgid "Debug Moderation"
|
||||||
msgstr "Eliminare errori nella Moderazione"
|
msgstr "Eliminare errori nella Moderazione"
|
||||||
|
|
||||||
#: src/view/screens/Debug.tsx:90
|
#: src/view/screens/Debug.tsx:89
|
||||||
msgid "Debug panel"
|
msgid "Debug panel"
|
||||||
msgstr "Pannello per il debug"
|
msgstr "Pannello per il debug"
|
||||||
|
|
||||||
@@ -2018,8 +2018,8 @@ msgstr "Eliminare questo post?"
|
|||||||
msgid "Deleted"
|
msgid "Deleted"
|
||||||
msgstr "Eliminato"
|
msgstr "Eliminato"
|
||||||
|
|
||||||
#: src/components/dms/MessagesListHeader.tsx:148
|
#: src/components/dms/MessagesListHeader.tsx:154
|
||||||
#: src/screens/Messages/components/ChatListItem.tsx:107
|
#: src/screens/Messages/components/ChatListItem.tsx:113
|
||||||
msgid "Deleted Account"
|
msgid "Deleted Account"
|
||||||
msgstr "Account eliminato"
|
msgstr "Account eliminato"
|
||||||
|
|
||||||
@@ -2120,7 +2120,7 @@ msgstr "Scoraggia le app dal mostrare il mio account agli utenti disconnessi"
|
|||||||
msgid "Discover new custom feeds"
|
msgid "Discover new custom feeds"
|
||||||
msgstr "Scopri nuovi feed personalizzati"
|
msgstr "Scopri nuovi feed personalizzati"
|
||||||
|
|
||||||
#: src/view/screens/Search/Explore.tsx:422
|
#: src/view/screens/Search/Explore.tsx:425
|
||||||
msgid "Discover new feeds"
|
msgid "Discover new feeds"
|
||||||
msgstr "Scopri nuovi feed"
|
msgstr "Scopri nuovi feed"
|
||||||
|
|
||||||
@@ -2189,17 +2189,17 @@ msgstr "Non inizia o termina con un trattino"
|
|||||||
msgid "Domain verified!"
|
msgid "Domain verified!"
|
||||||
msgstr "Dominio verificato!"
|
msgstr "Dominio verificato!"
|
||||||
|
|
||||||
#: src/components/dialogs/BirthDateSettings.tsx:118
|
#: src/components/dialogs/BirthDateSettings.tsx:114
|
||||||
#: src/components/dialogs/BirthDateSettings.tsx:124
|
#: src/components/dialogs/BirthDateSettings.tsx:120
|
||||||
#: src/components/dms/ReportDialog.tsx:323
|
#: src/components/dms/ReportDialog.tsx:323
|
||||||
#: src/components/forms/DateField/index.tsx:77
|
#: src/components/forms/DateField/index.tsx:87
|
||||||
#: src/components/forms/DateField/index.tsx:83
|
#: src/components/forms/DateField/index.tsx:93
|
||||||
#: src/screens/Onboarding/StepProfile/index.tsx:330
|
#: src/screens/Onboarding/StepProfile/index.tsx:330
|
||||||
#: src/screens/Onboarding/StepProfile/index.tsx:333
|
#: src/screens/Onboarding/StepProfile/index.tsx:333
|
||||||
#: src/screens/Settings/components/AddAppPasswordDialog.tsx:215
|
#: src/screens/Settings/components/AddAppPasswordDialog.tsx:215
|
||||||
#: src/screens/Settings/components/AddAppPasswordDialog.tsx:222
|
#: src/screens/Settings/components/AddAppPasswordDialog.tsx:222
|
||||||
#: src/view/com/auth/server-input/index.tsx:192
|
#: src/view/com/auth/server-input/index.tsx:228
|
||||||
#: src/view/com/auth/server-input/index.tsx:193
|
#: src/view/com/auth/server-input/index.tsx:229
|
||||||
#: src/view/com/composer/labels/LabelsBtn.tsx:224
|
#: src/view/com/composer/labels/LabelsBtn.tsx:224
|
||||||
#: src/view/com/composer/labels/LabelsBtn.tsx:231
|
#: src/view/com/composer/labels/LabelsBtn.tsx:231
|
||||||
#: src/view/com/composer/videos/SubtitleDialog.tsx:169
|
#: src/view/com/composer/videos/SubtitleDialog.tsx:169
|
||||||
@@ -2226,7 +2226,7 @@ msgstr "Fatto{extraText}"
|
|||||||
msgid "Double tap to close the dialog"
|
msgid "Double tap to close the dialog"
|
||||||
msgstr "Tocca due volte per chiudere la finestra"
|
msgstr "Tocca due volte per chiudere la finestra"
|
||||||
|
|
||||||
#: src/screens/VideoFeed/index.tsx:1037
|
#: src/screens/VideoFeed/index.tsx:1039
|
||||||
msgid "Double tap to like"
|
msgid "Double tap to like"
|
||||||
msgstr "Tocca due volte per mettere mi piace"
|
msgstr "Tocca due volte per mettere mi piace"
|
||||||
|
|
||||||
@@ -2550,7 +2550,7 @@ msgstr "Inserisci il dominio che vuoi usare"
|
|||||||
msgid "Enter the email you used to create your account. We'll send you a \"reset code\" so you can set a new password."
|
msgid "Enter the email you used to create your account. We'll send you a \"reset code\" so you can set a new password."
|
||||||
msgstr "Inserisci l'email che hai usato per creare il tuo account. Ti invieremo un codice in modo che tu possa scegliere una nuova password."
|
msgstr "Inserisci l'email che hai usato per creare il tuo account. Ti invieremo un codice in modo che tu possa scegliere una nuova password."
|
||||||
|
|
||||||
#: src/components/dialogs/BirthDateSettings.tsx:107
|
#: src/components/dialogs/BirthDateSettings.tsx:103
|
||||||
msgid "Enter your birth date"
|
msgid "Enter your birth date"
|
||||||
msgstr "Inserisci la tua data di nascita"
|
msgstr "Inserisci la tua data di nascita"
|
||||||
|
|
||||||
@@ -2738,8 +2738,8 @@ msgstr "Non è stato possibile eliminare il post, riprovare"
|
|||||||
msgid "Failed to delete starter pack"
|
msgid "Failed to delete starter pack"
|
||||||
msgstr "Impossibile eliminare lo starter pack"
|
msgstr "Impossibile eliminare lo starter pack"
|
||||||
|
|
||||||
#: src/view/screens/Search/Explore.tsx:460
|
#: src/view/screens/Search/Explore.tsx:463
|
||||||
#: src/view/screens/Search/Explore.tsx:488
|
#: src/view/screens/Search/Explore.tsx:491
|
||||||
msgid "Failed to load feeds preferences"
|
msgid "Failed to load feeds preferences"
|
||||||
msgstr "Impossibile caricare preferenze feed"
|
msgstr "Impossibile caricare preferenze feed"
|
||||||
|
|
||||||
@@ -2751,12 +2751,12 @@ msgstr "Impossibile caricare GIF"
|
|||||||
msgid "Failed to load past messages"
|
msgid "Failed to load past messages"
|
||||||
msgstr "Impossibile caricare messaggi vecchi"
|
msgstr "Impossibile caricare messaggi vecchi"
|
||||||
|
|
||||||
#: src/view/screens/Search/Explore.tsx:453
|
#: src/view/screens/Search/Explore.tsx:456
|
||||||
#: src/view/screens/Search/Explore.tsx:481
|
#: src/view/screens/Search/Explore.tsx:484
|
||||||
msgid "Failed to load suggested feeds"
|
msgid "Failed to load suggested feeds"
|
||||||
msgstr "Impossibile caricare feed consigliati"
|
msgstr "Impossibile caricare feed consigliati"
|
||||||
|
|
||||||
#: src/view/screens/Search/Explore.tsx:411
|
#: src/view/screens/Search/Explore.tsx:414
|
||||||
msgid "Failed to load suggested follows"
|
msgid "Failed to load suggested follows"
|
||||||
msgstr "Impossibile caricare follow consigliati"
|
msgstr "Impossibile caricare follow consigliati"
|
||||||
|
|
||||||
@@ -2897,16 +2897,16 @@ msgid "Flexible"
|
|||||||
msgstr "Flessibile"
|
msgstr "Flessibile"
|
||||||
|
|
||||||
#. User is not following this account, click to follow
|
#. User is not following this account, click to follow
|
||||||
#: src/components/ProfileCard.tsx:363
|
#: src/components/ProfileCard.tsx:366
|
||||||
#: src/components/ProfileHoverCard/index.web.tsx:449
|
#: src/components/ProfileHoverCard/index.web.tsx:449
|
||||||
#: src/components/ProfileHoverCard/index.web.tsx:460
|
#: src/components/ProfileHoverCard/index.web.tsx:460
|
||||||
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:234
|
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:234
|
||||||
#: src/screens/VideoFeed/index.tsx:819
|
#: src/screens/VideoFeed/index.tsx:821
|
||||||
#: src/view/com/post-thread/PostThreadFollowBtn.tsx:132
|
#: src/view/com/post-thread/PostThreadFollowBtn.tsx:132
|
||||||
msgid "Follow"
|
msgid "Follow"
|
||||||
msgstr "Segui"
|
msgstr "Segui"
|
||||||
|
|
||||||
#: src/view/com/profile/FollowButton.tsx:69
|
#: src/view/com/profile/FollowButton.tsx:72
|
||||||
msgctxt "action"
|
msgctxt "action"
|
||||||
msgid "Follow"
|
msgid "Follow"
|
||||||
msgstr "Segui"
|
msgstr "Segui"
|
||||||
@@ -2916,7 +2916,7 @@ msgstr "Segui"
|
|||||||
msgid "Follow {0}"
|
msgid "Follow {0}"
|
||||||
msgstr "Segui {0}"
|
msgstr "Segui {0}"
|
||||||
|
|
||||||
#: src/screens/VideoFeed/index.tsx:798
|
#: src/screens/VideoFeed/index.tsx:800
|
||||||
msgid "Follow {handle}"
|
msgid "Follow {handle}"
|
||||||
msgstr "Segui {handle}"
|
msgstr "Segui {handle}"
|
||||||
|
|
||||||
@@ -2948,14 +2948,14 @@ msgstr "Segui tutti"
|
|||||||
msgid "Follow Back"
|
msgid "Follow Back"
|
||||||
msgstr "Ricambia follow"
|
msgstr "Ricambia follow"
|
||||||
|
|
||||||
#: src/view/com/profile/FollowButton.tsx:78
|
#: src/view/com/profile/FollowButton.tsx:81
|
||||||
msgctxt "action"
|
msgctxt "action"
|
||||||
msgid "Follow Back"
|
msgid "Follow Back"
|
||||||
msgstr "Segui anche tu"
|
msgstr "Segui anche tu"
|
||||||
|
|
||||||
#: src/view/screens/Search/Explore.tsx:368
|
#: src/view/screens/Search/Explore.tsx:370
|
||||||
msgid "Follow more accounts to get connected to your interests and build your network."
|
msgid "Follow more accounts to get connected to your interests and build your network."
|
||||||
msgstr "Segui altri account per connetterti ai tuoi interessi e crea il tuo network personale."
|
msgstr "Segui altri account per connetterti ai tuoi interessi e creare la tua rete personale."
|
||||||
|
|
||||||
#: src/components/KnownFollowers.tsx:232
|
#: src/components/KnownFollowers.tsx:232
|
||||||
msgid "Followed by <0>{0}</0>"
|
msgid "Followed by <0>{0}</0>"
|
||||||
@@ -2987,23 +2987,23 @@ msgid "Followers you know"
|
|||||||
msgstr "Follower che conosci"
|
msgstr "Follower che conosci"
|
||||||
|
|
||||||
#. User is following this account, click to unfollow
|
#. User is following this account, click to unfollow
|
||||||
#: src/components/ProfileCard.tsx:357
|
#: src/components/ProfileCard.tsx:360
|
||||||
#: src/components/ProfileHoverCard/index.web.tsx:448
|
#: src/components/ProfileHoverCard/index.web.tsx:448
|
||||||
#: src/components/ProfileHoverCard/index.web.tsx:459
|
#: src/components/ProfileHoverCard/index.web.tsx:459
|
||||||
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:230
|
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:230
|
||||||
#: src/screens/VideoFeed/index.tsx:817
|
#: src/screens/VideoFeed/index.tsx:819
|
||||||
#: src/view/com/post-thread/PostThreadFollowBtn.tsx:135
|
#: src/view/com/post-thread/PostThreadFollowBtn.tsx:135
|
||||||
#: src/view/screens/Feeds.tsx:599
|
#: src/view/screens/Feeds.tsx:599
|
||||||
#: src/view/screens/SavedFeeds.tsx:422
|
#: src/view/screens/SavedFeeds.tsx:422
|
||||||
msgid "Following"
|
msgid "Following"
|
||||||
msgstr "Following"
|
msgstr "Following"
|
||||||
|
|
||||||
#: src/components/ProfileCard.tsx:321
|
#: src/components/ProfileCard.tsx:323
|
||||||
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:98
|
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:98
|
||||||
msgid "Following {0}"
|
msgid "Following {0}"
|
||||||
msgstr "Stai seguendo {0}"
|
msgstr "Stai seguendo {0}"
|
||||||
|
|
||||||
#: src/screens/VideoFeed/index.tsx:797
|
#: src/screens/VideoFeed/index.tsx:799
|
||||||
msgid "Following {handle}"
|
msgid "Following {handle}"
|
||||||
msgstr "Stai seguendo {handle}"
|
msgstr "Stai seguendo {handle}"
|
||||||
|
|
||||||
@@ -3122,8 +3122,8 @@ msgstr "Evidenti violazioni della legge o dei termini di servizio"
|
|||||||
#: src/components/moderation/ScreenHider.tsx:163
|
#: src/components/moderation/ScreenHider.tsx:163
|
||||||
#: src/screens/Profile/ProfileFeed/index.tsx:89
|
#: src/screens/Profile/ProfileFeed/index.tsx:89
|
||||||
#: src/screens/VideoFeed/components/Header.tsx:163
|
#: src/screens/VideoFeed/components/Header.tsx:163
|
||||||
#: src/screens/VideoFeed/index.tsx:1098
|
#: src/screens/VideoFeed/index.tsx:1100
|
||||||
#: src/screens/VideoFeed/index.tsx:1102
|
#: src/screens/VideoFeed/index.tsx:1104
|
||||||
#: src/view/com/auth/LoggedOut.tsx:72
|
#: src/view/com/auth/LoggedOut.tsx:72
|
||||||
#: src/view/screens/NotFound.tsx:57
|
#: src/view/screens/NotFound.tsx:57
|
||||||
#: src/view/screens/ProfileList.tsx:1009
|
#: src/view/screens/ProfileList.tsx:1009
|
||||||
@@ -3166,7 +3166,7 @@ msgstr "Vai alla home"
|
|||||||
msgid "Go Home"
|
msgid "Go Home"
|
||||||
msgstr "Vai alla home"
|
msgstr "Vai alla home"
|
||||||
|
|
||||||
#: src/screens/Messages/components/ChatListItem.tsx:274
|
#: src/screens/Messages/components/ChatListItem.tsx:282
|
||||||
msgid "Go to conversation with {0}"
|
msgid "Go to conversation with {0}"
|
||||||
msgstr "Vai alla conversazione con {0}"
|
msgstr "Vai alla conversazione con {0}"
|
||||||
|
|
||||||
@@ -3175,11 +3175,11 @@ msgstr "Vai alla conversazione con {0}"
|
|||||||
msgid "Go to next"
|
msgid "Go to next"
|
||||||
msgstr "Prosegui"
|
msgstr "Prosegui"
|
||||||
|
|
||||||
#: src/components/dms/ConvoMenu.tsx:170
|
#: src/components/dms/ConvoMenu.tsx:230
|
||||||
msgid "Go to profile"
|
msgid "Go to profile"
|
||||||
msgstr "Vai al profilo"
|
msgstr "Vai al profilo"
|
||||||
|
|
||||||
#: src/components/dms/ConvoMenu.tsx:167
|
#: src/components/dms/ConvoMenu.tsx:227
|
||||||
msgid "Go to user's profile"
|
msgid "Go to user's profile"
|
||||||
msgstr "Vai al profilo dell'utente"
|
msgstr "Vai al profilo dell'utente"
|
||||||
|
|
||||||
@@ -3439,7 +3439,7 @@ msgstr "Se rimuovi questo post, non potrai recuperarlo."
|
|||||||
msgid "If you want to change your password, we will send you a code to verify that this is your account."
|
msgid "If you want to change your password, we will send you a code to verify that this is your account."
|
||||||
msgstr "Se vuoi modificare la password, ti invieremo un codice per verificare che questo è il tuo account."
|
msgstr "Se vuoi modificare la password, ti invieremo un codice per verificare che questo è il tuo account."
|
||||||
|
|
||||||
#: src/view/com/auth/server-input/index.tsx:168
|
#: src/view/com/auth/server-input/index.tsx:204
|
||||||
msgid "If you're a developer, you can host your own server."
|
msgid "If you're a developer, you can host your own server."
|
||||||
msgstr "Se sei uno sviluppatore, puoi utilizzare il tuo server."
|
msgstr "Se sei uno sviluppatore, puoi utilizzare il tuo server."
|
||||||
|
|
||||||
@@ -3560,7 +3560,7 @@ msgstr "Inviti, ma personali"
|
|||||||
msgid "It looks like you may have entered your email address incorrectly. Are you sure it's right?"
|
msgid "It looks like you may have entered your email address incorrectly. Are you sure it's right?"
|
||||||
msgstr "Sembra che tu abbia inserito il tuo indirizzo email in modo errato. Sei sicuro che sia corretto?"
|
msgstr "Sembra che tu abbia inserito il tuo indirizzo email in modo errato. Sei sicuro che sia corretto?"
|
||||||
|
|
||||||
#: src/screens/Signup/StepInfo/index.tsx:235
|
#: src/screens/Signup/StepInfo/index.tsx:236
|
||||||
msgid "It's correct"
|
msgid "It's correct"
|
||||||
msgstr "È corretto"
|
msgstr "È corretto"
|
||||||
|
|
||||||
@@ -3574,7 +3574,7 @@ msgstr "ID processo: {0}"
|
|||||||
|
|
||||||
#: src/view/com/auth/SplashScreen.web.tsx:178
|
#: src/view/com/auth/SplashScreen.web.tsx:178
|
||||||
msgid "Jobs"
|
msgid "Jobs"
|
||||||
msgstr "Lavora con noi"
|
msgstr "Opportunità di lavoro"
|
||||||
|
|
||||||
#: src/screens/StarterPack/StarterPackLandingScreen.tsx:201
|
#: src/screens/StarterPack/StarterPackLandingScreen.tsx:201
|
||||||
#: src/screens/StarterPack/StarterPackLandingScreen.tsx:207
|
#: src/screens/StarterPack/StarterPackLandingScreen.tsx:207
|
||||||
@@ -3658,7 +3658,7 @@ msgstr "Ulteriori Informazioni"
|
|||||||
msgid "Learn more about Bluesky"
|
msgid "Learn more about Bluesky"
|
||||||
msgstr "Scopri di più su Bluesky"
|
msgstr "Scopri di più su Bluesky"
|
||||||
|
|
||||||
#: src/view/com/auth/server-input/index.tsx:178
|
#: src/view/com/auth/server-input/index.tsx:214
|
||||||
msgid "Learn more about self hosting your PDS."
|
msgid "Learn more about self hosting your PDS."
|
||||||
msgstr "Maggiori informazioni su come ospitare il tuo server."
|
msgstr "Maggiori informazioni su come ospitare il tuo server."
|
||||||
|
|
||||||
@@ -3678,7 +3678,7 @@ msgid "Learn more about what is public on Bluesky."
|
|||||||
msgstr "Scopri cosa è pubblico su Bluesky."
|
msgstr "Scopri cosa è pubblico su Bluesky."
|
||||||
|
|
||||||
#: src/components/moderation/ContentHider.tsx:239
|
#: src/components/moderation/ContentHider.tsx:239
|
||||||
#: src/view/com/auth/server-input/index.tsx:180
|
#: src/view/com/auth/server-input/index.tsx:216
|
||||||
msgid "Learn more."
|
msgid "Learn more."
|
||||||
msgstr "Saperne di più."
|
msgstr "Saperne di più."
|
||||||
|
|
||||||
@@ -3686,15 +3686,15 @@ msgstr "Saperne di più."
|
|||||||
msgid "Leave"
|
msgid "Leave"
|
||||||
msgstr "Abbandona"
|
msgstr "Abbandona"
|
||||||
|
|
||||||
#: src/components/dms/MessagesListBlockedFooter.tsx:66
|
|
||||||
#: src/components/dms/MessagesListBlockedFooter.tsx:73
|
#: src/components/dms/MessagesListBlockedFooter.tsx:73
|
||||||
|
#: src/components/dms/MessagesListBlockedFooter.tsx:80
|
||||||
msgid "Leave chat"
|
msgid "Leave chat"
|
||||||
msgstr "Abbandona la chat"
|
msgstr "Abbandona la chat"
|
||||||
|
|
||||||
#: src/components/dms/ConvoMenu.tsx:141
|
#: src/components/dms/ConvoMenu.tsx:206
|
||||||
#: src/components/dms/ConvoMenu.tsx:144
|
#: src/components/dms/ConvoMenu.tsx:209
|
||||||
#: src/components/dms/ConvoMenu.tsx:211
|
#: src/components/dms/ConvoMenu.tsx:269
|
||||||
#: src/components/dms/ConvoMenu.tsx:214
|
#: src/components/dms/ConvoMenu.tsx:272
|
||||||
#: src/components/dms/LeaveConvoPrompt.tsx:40
|
#: src/components/dms/LeaveConvoPrompt.tsx:40
|
||||||
msgid "Leave conversation"
|
msgid "Leave conversation"
|
||||||
msgstr "Abbandona conversazione"
|
msgstr "Abbandona conversazione"
|
||||||
@@ -3856,15 +3856,15 @@ msgstr "Liste"
|
|||||||
msgid "Lists blocking this user:"
|
msgid "Lists blocking this user:"
|
||||||
msgstr "Liste che bloccano questo utente:"
|
msgstr "Liste che bloccano questo utente:"
|
||||||
|
|
||||||
#: src/view/screens/Search/Explore.tsx:134
|
#: src/view/screens/Search/Explore.tsx:135
|
||||||
msgid "Load more"
|
msgid "Load more"
|
||||||
msgstr "Carica di più"
|
msgstr "Carica di più"
|
||||||
|
|
||||||
#: src/view/screens/Search/Explore.tsx:223
|
#: src/view/screens/Search/Explore.tsx:224
|
||||||
msgid "Load more suggested feeds"
|
msgid "Load more suggested feeds"
|
||||||
msgstr "Carica più feed consigliati"
|
msgstr "Carica più feed consigliati"
|
||||||
|
|
||||||
#: src/view/screens/Search/Explore.tsx:221
|
#: src/view/screens/Search/Explore.tsx:222
|
||||||
msgid "Load more suggested follows"
|
msgid "Load more suggested follows"
|
||||||
msgstr "Carica più utenti suggeriti"
|
msgstr "Carica più utenti suggeriti"
|
||||||
|
|
||||||
@@ -3956,8 +3956,8 @@ msgstr "Gestisci i feed salvati"
|
|||||||
msgid "Manage your muted words and tags"
|
msgid "Manage your muted words and tags"
|
||||||
msgstr "Gestisci parole e tag silenziati"
|
msgstr "Gestisci parole e tag silenziati"
|
||||||
|
|
||||||
#: src/components/dms/ConvoMenu.tsx:154
|
#: src/components/dms/ConvoMenu.tsx:218
|
||||||
#: src/components/dms/ConvoMenu.tsx:161
|
#: src/components/dms/ConvoMenu.tsx:221
|
||||||
msgid "Mark as read"
|
msgid "Mark as read"
|
||||||
msgstr "Segna come letto"
|
msgstr "Segna come letto"
|
||||||
|
|
||||||
@@ -3982,7 +3982,7 @@ msgid "Mentions"
|
|||||||
msgstr "Menzioni"
|
msgstr "Menzioni"
|
||||||
|
|
||||||
#: src/components/Menu/index.tsx:103
|
#: src/components/Menu/index.tsx:103
|
||||||
#: src/view/screens/Search/Search.tsx:856
|
#: src/view/screens/Search/Search.tsx:862
|
||||||
msgid "Menu"
|
msgid "Menu"
|
||||||
msgstr "Menu"
|
msgstr "Menu"
|
||||||
|
|
||||||
@@ -3991,7 +3991,7 @@ msgid "Message {0}"
|
|||||||
msgstr "Messaggio {0}"
|
msgstr "Messaggio {0}"
|
||||||
|
|
||||||
#: src/components/dms/MessageMenu.tsx:72
|
#: src/components/dms/MessageMenu.tsx:72
|
||||||
#: src/screens/Messages/components/ChatListItem.tsx:174
|
#: src/screens/Messages/components/ChatListItem.tsx:180
|
||||||
msgid "Message deleted"
|
msgid "Message deleted"
|
||||||
msgstr "Messaggio eliminato"
|
msgstr "Messaggio eliminato"
|
||||||
|
|
||||||
@@ -4009,8 +4009,8 @@ msgid "Message is too long"
|
|||||||
msgstr "Il messaggio è troppo lungo"
|
msgstr "Il messaggio è troppo lungo"
|
||||||
|
|
||||||
#: src/Navigation.tsx:618
|
#: src/Navigation.tsx:618
|
||||||
#: src/screens/Messages/ChatList.tsx:270
|
#: src/screens/Messages/ChatList.tsx:269
|
||||||
#: src/screens/Messages/ChatList.tsx:294
|
#: src/screens/Messages/ChatList.tsx:293
|
||||||
msgid "Messages"
|
msgid "Messages"
|
||||||
msgstr "Messaggi"
|
msgstr "Messaggi"
|
||||||
|
|
||||||
@@ -4133,8 +4133,8 @@ msgstr "Silenzia account"
|
|||||||
msgid "Mute accounts"
|
msgid "Mute accounts"
|
||||||
msgstr "Silenzia account"
|
msgstr "Silenzia account"
|
||||||
|
|
||||||
#: src/components/dms/ConvoMenu.tsx:175
|
#: src/components/dms/ConvoMenu.tsx:235
|
||||||
#: src/components/dms/ConvoMenu.tsx:181
|
#: src/components/dms/ConvoMenu.tsx:241
|
||||||
msgid "Mute conversation"
|
msgid "Mute conversation"
|
||||||
msgstr "Silenzia conversazione"
|
msgstr "Silenzia conversazione"
|
||||||
|
|
||||||
@@ -4275,8 +4275,8 @@ msgid "New"
|
|||||||
msgstr "Nuova"
|
msgstr "Nuova"
|
||||||
|
|
||||||
#: src/components/dms/dialogs/NewChatDialog.tsx:65
|
#: src/components/dms/dialogs/NewChatDialog.tsx:65
|
||||||
#: src/screens/Messages/ChatList.tsx:277
|
#: src/screens/Messages/ChatList.tsx:276
|
||||||
#: src/screens/Messages/ChatList.tsx:284
|
#: src/screens/Messages/ChatList.tsx:283
|
||||||
msgid "New chat"
|
msgid "New chat"
|
||||||
msgstr "Nuova chat"
|
msgstr "Nuova chat"
|
||||||
|
|
||||||
@@ -4390,7 +4390,7 @@ msgstr "Nessun feed trovato. Prova a cercarne altri."
|
|||||||
msgid "No likes yet"
|
msgid "No likes yet"
|
||||||
msgstr "Ancora nessun mi piace"
|
msgstr "Ancora nessun mi piace"
|
||||||
|
|
||||||
#: src/components/ProfileCard.tsx:342
|
#: src/components/ProfileCard.tsx:345
|
||||||
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:119
|
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:119
|
||||||
msgid "No longer following {0}"
|
msgid "No longer following {0}"
|
||||||
msgstr "Non segui più {0}"
|
msgstr "Non segui più {0}"
|
||||||
@@ -4399,7 +4399,7 @@ msgstr "Non segui più {0}"
|
|||||||
msgid "No longer than {0} characters"
|
msgid "No longer than {0} characters"
|
||||||
msgstr "Non più di {0} caratteri"
|
msgstr "Non più di {0} caratteri"
|
||||||
|
|
||||||
#: src/screens/Messages/components/ChatListItem.tsx:118
|
#: src/screens/Messages/components/ChatListItem.tsx:124
|
||||||
msgid "No messages yet"
|
msgid "No messages yet"
|
||||||
msgstr "Ancora nessun messaggio"
|
msgstr "Ancora nessun messaggio"
|
||||||
|
|
||||||
@@ -4599,7 +4599,7 @@ msgstr "su<0><1/><2><3/></2></0>"
|
|||||||
|
|
||||||
#: src/screens/Settings/Settings.tsx:304
|
#: src/screens/Settings/Settings.tsx:304
|
||||||
msgid "Onboarding reset"
|
msgid "Onboarding reset"
|
||||||
msgstr "Reimpostazione dell'onboarding"
|
msgstr "Reimposta account"
|
||||||
|
|
||||||
#: src/view/com/composer/Composer.tsx:338
|
#: src/view/com/composer/Composer.tsx:338
|
||||||
msgid "One or more GIFs is missing alt text."
|
msgid "One or more GIFs is missing alt text."
|
||||||
@@ -4663,8 +4663,8 @@ msgstr "Apri il creatore di avatar"
|
|||||||
msgid "Open change handle dialog"
|
msgid "Open change handle dialog"
|
||||||
msgstr "Apri la finestra di dialogo per la modifica del nome utente"
|
msgstr "Apri la finestra di dialogo per la modifica del nome utente"
|
||||||
|
|
||||||
#: src/screens/Messages/components/ChatListItem.tsx:282
|
#: src/screens/Messages/components/ChatListItem.tsx:290
|
||||||
#: src/screens/Messages/components/ChatListItem.tsx:283
|
#: src/screens/Messages/components/ChatListItem.tsx:291
|
||||||
msgid "Open conversation options"
|
msgid "Open conversation options"
|
||||||
msgstr "Apri opzioni conversazione"
|
msgstr "Apri opzioni conversazione"
|
||||||
|
|
||||||
@@ -4827,7 +4827,7 @@ msgstr "Altro..."
|
|||||||
|
|
||||||
#: src/components/dms/ReportDialog.tsx:339
|
#: src/components/dms/ReportDialog.tsx:339
|
||||||
msgid "Our moderation team has received your report."
|
msgid "Our moderation team has received your report."
|
||||||
msgstr "Il nostro team di moderazione ha ricevuto la segnalazione."
|
msgstr "Il team di moderazione ha ricevuto la tua segnalazione."
|
||||||
|
|
||||||
#: src/screens/Messages/components/ChatDisabled.tsx:28
|
#: src/screens/Messages/components/ChatDisabled.tsx:28
|
||||||
msgid "Our moderators have reviewed reports and decided to disable your access to chats on Bluesky."
|
msgid "Our moderators have reviewed reports and decided to disable your access to chats on Bluesky."
|
||||||
@@ -5326,11 +5326,11 @@ msgstr "Riattacca citazione"
|
|||||||
msgid "Reactivate your account"
|
msgid "Reactivate your account"
|
||||||
msgstr "Riattiva account"
|
msgstr "Riattiva account"
|
||||||
|
|
||||||
#: src/screens/VideoFeed/index.tsx:932
|
#: src/screens/VideoFeed/index.tsx:934
|
||||||
msgid "Read less"
|
msgid "Read less"
|
||||||
msgstr "Leggi di meno"
|
msgstr "Leggi di meno"
|
||||||
|
|
||||||
#: src/screens/VideoFeed/index.tsx:932
|
#: src/screens/VideoFeed/index.tsx:934
|
||||||
msgid "Read more"
|
msgid "Read more"
|
||||||
msgstr "Leggi di più"
|
msgstr "Leggi di più"
|
||||||
|
|
||||||
@@ -5351,13 +5351,13 @@ msgstr "Leggi i termini di servizio di Bluesky"
|
|||||||
#: src/screens/Takendown.tsx:162
|
#: src/screens/Takendown.tsx:162
|
||||||
#: src/screens/Takendown.tsx:170
|
#: src/screens/Takendown.tsx:170
|
||||||
msgid "Reason for appeal"
|
msgid "Reason for appeal"
|
||||||
msgstr "Motivo della richiesta di revisione della sospensione"
|
msgstr "Motivo del ricorso"
|
||||||
|
|
||||||
#: src/components/dms/ReportDialog.tsx:210
|
#: src/components/dms/ReportDialog.tsx:210
|
||||||
msgid "Reason:"
|
msgid "Reason:"
|
||||||
msgstr "Motivo:"
|
msgstr "Motivo:"
|
||||||
|
|
||||||
#: src/view/screens/Search/Search.tsx:1034
|
#: src/view/screens/Search/Search.tsx:1040
|
||||||
msgid "Recent Searches"
|
msgid "Recent Searches"
|
||||||
msgstr "Ricerche recenti"
|
msgstr "Ricerche recenti"
|
||||||
|
|
||||||
@@ -5450,11 +5450,11 @@ msgstr "Rimuovi l'immagine"
|
|||||||
msgid "Remove mute word from your list"
|
msgid "Remove mute word from your list"
|
||||||
msgstr "Rimuovi parola silenziata dalla tua lista"
|
msgstr "Rimuovi parola silenziata dalla tua lista"
|
||||||
|
|
||||||
#: src/view/screens/Search/Search.tsx:1082
|
#: src/view/screens/Search/Search.tsx:1088
|
||||||
msgid "Remove profile"
|
msgid "Remove profile"
|
||||||
msgstr "Rimuovi profilo"
|
msgstr "Rimuovi profilo"
|
||||||
|
|
||||||
#: src/view/screens/Search/Search.tsx:1084
|
#: src/view/screens/Search/Search.tsx:1090
|
||||||
msgid "Remove profile from search history"
|
msgid "Remove profile from search history"
|
||||||
msgstr "Rimuovi profilo dalla cronologia di ricerca"
|
msgstr "Rimuovi profilo dalla cronologia di ricerca"
|
||||||
|
|
||||||
@@ -5465,7 +5465,7 @@ msgstr "Rimuovi citazione"
|
|||||||
#: src/view/com/util/post-ctrls/RepostButton.tsx:155
|
#: src/view/com/util/post-ctrls/RepostButton.tsx:155
|
||||||
#: src/view/com/util/post-ctrls/RepostButton.tsx:165
|
#: src/view/com/util/post-ctrls/RepostButton.tsx:165
|
||||||
msgid "Remove repost"
|
msgid "Remove repost"
|
||||||
msgstr "Rimuovi ripubblicazione"
|
msgstr "Rimuovi repost"
|
||||||
|
|
||||||
#: src/view/com/composer/videos/SubtitleDialog.tsx:260
|
#: src/view/com/composer/videos/SubtitleDialog.tsx:260
|
||||||
msgid "Remove subtitle file"
|
msgid "Remove subtitle file"
|
||||||
@@ -5586,8 +5586,8 @@ msgid "Reply was successfully hidden"
|
|||||||
msgstr "Risposta nascosta con successo"
|
msgstr "Risposta nascosta con successo"
|
||||||
|
|
||||||
#: src/components/dms/MessageMenu.tsx:132
|
#: src/components/dms/MessageMenu.tsx:132
|
||||||
#: src/components/dms/MessagesListBlockedFooter.tsx:77
|
|
||||||
#: src/components/dms/MessagesListBlockedFooter.tsx:84
|
#: src/components/dms/MessagesListBlockedFooter.tsx:84
|
||||||
|
#: src/components/dms/MessagesListBlockedFooter.tsx:91
|
||||||
msgid "Report"
|
msgid "Report"
|
||||||
msgstr "Segnala"
|
msgstr "Segnala"
|
||||||
|
|
||||||
@@ -5596,8 +5596,8 @@ msgstr "Segnala"
|
|||||||
msgid "Report Account"
|
msgid "Report Account"
|
||||||
msgstr "Segnala account"
|
msgstr "Segnala account"
|
||||||
|
|
||||||
#: src/components/dms/ConvoMenu.tsx:200
|
#: src/components/dms/ConvoMenu.tsx:258
|
||||||
#: src/components/dms/ConvoMenu.tsx:203
|
#: src/components/dms/ConvoMenu.tsx:261
|
||||||
#: src/components/dms/ReportConversationPrompt.tsx:17
|
#: src/components/dms/ReportConversationPrompt.tsx:17
|
||||||
msgid "Report conversation"
|
msgid "Report conversation"
|
||||||
msgstr "Segnala conversazione"
|
msgstr "Segnala conversazione"
|
||||||
@@ -5759,7 +5759,7 @@ msgstr "Reimposta il codice"
|
|||||||
#: src/screens/Settings/Settings.tsx:344
|
#: src/screens/Settings/Settings.tsx:344
|
||||||
#: src/screens/Settings/Settings.tsx:346
|
#: src/screens/Settings/Settings.tsx:346
|
||||||
msgid "Reset onboarding state"
|
msgid "Reset onboarding state"
|
||||||
msgstr "Reimposta lo stato dell'incorporazione"
|
msgstr "Ripristina lo stato di registrazione"
|
||||||
|
|
||||||
#: src/screens/Login/ForgotPasswordForm.tsx:80
|
#: src/screens/Login/ForgotPasswordForm.tsx:80
|
||||||
msgid "Reset password"
|
msgid "Reset password"
|
||||||
@@ -5804,12 +5804,12 @@ msgid "Returns to home page"
|
|||||||
msgstr "Ritorna alla home"
|
msgstr "Ritorna alla home"
|
||||||
|
|
||||||
#: src/screens/Profile/ProfileFeed/index.tsx:90
|
#: src/screens/Profile/ProfileFeed/index.tsx:90
|
||||||
#: src/screens/VideoFeed/index.tsx:1099
|
#: src/screens/VideoFeed/index.tsx:1101
|
||||||
#: src/view/screens/NotFound.tsx:60
|
#: src/view/screens/NotFound.tsx:60
|
||||||
msgid "Returns to previous page"
|
msgid "Returns to previous page"
|
||||||
msgstr "Ritorna alla pagina precedente"
|
msgstr "Ritorna alla pagina precedente"
|
||||||
|
|
||||||
#: src/components/dialogs/BirthDateSettings.tsx:124
|
#: src/components/dialogs/BirthDateSettings.tsx:120
|
||||||
#: src/components/dialogs/PostInteractionSettingsDialog.tsx:438
|
#: src/components/dialogs/PostInteractionSettingsDialog.tsx:438
|
||||||
#: src/components/dialogs/PostInteractionSettingsDialog.tsx:444
|
#: src/components/dialogs/PostInteractionSettingsDialog.tsx:444
|
||||||
#: src/components/StarterPack/QrCodeDialog.tsx:185
|
#: src/components/StarterPack/QrCodeDialog.tsx:185
|
||||||
@@ -5834,7 +5834,7 @@ msgctxt "action"
|
|||||||
msgid "Save"
|
msgid "Save"
|
||||||
msgstr "Salva"
|
msgstr "Salva"
|
||||||
|
|
||||||
#: src/components/dialogs/BirthDateSettings.tsx:118
|
#: src/components/dialogs/BirthDateSettings.tsx:114
|
||||||
msgid "Save birthday"
|
msgid "Save birthday"
|
||||||
msgstr "Salva il compleanno"
|
msgstr "Salva il compleanno"
|
||||||
|
|
||||||
@@ -5934,7 +5934,7 @@ msgstr "Cerca \"{interestsDisplayName}\"{activeText}"
|
|||||||
msgid "Search for \"{query}\""
|
msgid "Search for \"{query}\""
|
||||||
msgstr "Cerca \"{query}\""
|
msgstr "Cerca \"{query}\""
|
||||||
|
|
||||||
#: src/view/screens/Search/Search.tsx:980
|
#: src/view/screens/Search/Search.tsx:986
|
||||||
msgid "Search for \"{searchText}\""
|
msgid "Search for \"{searchText}\""
|
||||||
msgstr "Cerca \"{searchText}\""
|
msgstr "Cerca \"{searchText}\""
|
||||||
|
|
||||||
@@ -6145,7 +6145,7 @@ msgstr "Invia tramite messaggi"
|
|||||||
msgid "Sends email with confirmation code for account deletion"
|
msgid "Sends email with confirmation code for account deletion"
|
||||||
msgstr "Invia un'email con il codice di conferma per l'eliminazione dell'account"
|
msgstr "Invia un'email con il codice di conferma per l'eliminazione dell'account"
|
||||||
|
|
||||||
#: src/view/com/auth/server-input/index.tsx:127
|
#: src/view/com/auth/server-input/index.tsx:163
|
||||||
msgid "Server address"
|
msgid "Server address"
|
||||||
msgstr "Indirizzo del server"
|
msgstr "Indirizzo del server"
|
||||||
|
|
||||||
@@ -6420,7 +6420,7 @@ msgstr "Esci"
|
|||||||
#: src/screens/Settings/Settings.tsx:256
|
#: src/screens/Settings/Settings.tsx:256
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:205
|
#: src/view/shell/desktop/LeftNav.tsx:205
|
||||||
msgid "Sign out?"
|
msgid "Sign out?"
|
||||||
msgstr "Uscire?"
|
msgstr "Vuoi uscire?"
|
||||||
|
|
||||||
#: src/components/moderation/ScreenHider.tsx:91
|
#: src/components/moderation/ScreenHider.tsx:91
|
||||||
#: src/lib/moderation/useGlobalLabelStrings.ts:28
|
#: src/lib/moderation/useGlobalLabelStrings.ts:28
|
||||||
@@ -6437,7 +6437,7 @@ msgstr "Accesso effettuato come @{0}"
|
|||||||
msgid "Signup without a starter pack"
|
msgid "Signup without a starter pack"
|
||||||
msgstr "Iscriviti senza uno starter pack"
|
msgstr "Iscriviti senza uno starter pack"
|
||||||
|
|
||||||
#: src/components/FeedInterstitials.tsx:314
|
#: src/components/FeedInterstitials.tsx:335
|
||||||
msgid "Similar accounts"
|
msgid "Similar accounts"
|
||||||
msgstr "Account simili"
|
msgstr "Account simili"
|
||||||
|
|
||||||
@@ -6459,7 +6459,7 @@ msgstr "Più piccolo"
|
|||||||
msgid "Software Dev"
|
msgid "Software Dev"
|
||||||
msgstr "Sviluppo software"
|
msgstr "Sviluppo software"
|
||||||
|
|
||||||
#: src/components/FeedInterstitials.tsx:449
|
#: src/components/FeedInterstitials.tsx:470
|
||||||
msgid "Some other feeds you might like"
|
msgid "Some other feeds you might like"
|
||||||
msgstr "Altri feed che potrebbero piacerti"
|
msgstr "Altri feed che potrebbero piacerti"
|
||||||
|
|
||||||
@@ -6467,7 +6467,7 @@ msgstr "Altri feed che potrebbero piacerti"
|
|||||||
msgid "Some people can reply"
|
msgid "Some people can reply"
|
||||||
msgstr "Risposte limitate"
|
msgstr "Risposte limitate"
|
||||||
|
|
||||||
#: src/screens/Messages/Conversation.tsx:102
|
#: src/screens/Messages/Conversation.tsx:112
|
||||||
msgid "Something went wrong"
|
msgid "Something went wrong"
|
||||||
msgstr "Qualcosa è andato storto"
|
msgstr "Qualcosa è andato storto"
|
||||||
|
|
||||||
@@ -6632,11 +6632,11 @@ msgstr "Iscriviti alla lista"
|
|||||||
msgid "Success!"
|
msgid "Success!"
|
||||||
msgstr "Successo!"
|
msgstr "Successo!"
|
||||||
|
|
||||||
#: src/view/screens/Search/Explore.tsx:366
|
#: src/view/screens/Search/Explore.tsx:368
|
||||||
msgid "Suggested accounts"
|
msgid "Suggested accounts"
|
||||||
msgstr "Account suggeriti"
|
msgstr "Account suggeriti"
|
||||||
|
|
||||||
#: src/components/FeedInterstitials.tsx:316
|
#: src/components/FeedInterstitials.tsx:337
|
||||||
msgid "Suggested for you"
|
msgid "Suggested for you"
|
||||||
msgstr "Suggerito per te"
|
msgstr "Suggerito per te"
|
||||||
|
|
||||||
@@ -6703,7 +6703,7 @@ msgstr "Tocca per ignorare"
|
|||||||
msgid "Tap to enter full screen"
|
msgid "Tap to enter full screen"
|
||||||
msgstr "Tocca per entrare in modalità a schermo intero"
|
msgstr "Tocca per entrare in modalità a schermo intero"
|
||||||
|
|
||||||
#: src/screens/VideoFeed/index.tsx:931
|
#: src/screens/VideoFeed/index.tsx:933
|
||||||
msgid "Tap to expand or collapse post text."
|
msgid "Tap to expand or collapse post text."
|
||||||
msgstr "Tocca per espandere o comprimere il testo del post."
|
msgstr "Tocca per espandere o comprimere il testo del post."
|
||||||
|
|
||||||
@@ -6820,7 +6820,7 @@ msgstr "Impossibile trovare starter pack."
|
|||||||
msgid "That's all, folks!"
|
msgid "That's all, folks!"
|
||||||
msgstr "Questo è tutto, gente!"
|
msgstr "Questo è tutto, gente!"
|
||||||
|
|
||||||
#: src/screens/VideoFeed/index.tsx:1071
|
#: src/screens/VideoFeed/index.tsx:1073
|
||||||
msgid "That's everything!"
|
msgid "That's everything!"
|
||||||
msgstr "È tutto!"
|
msgstr "È tutto!"
|
||||||
|
|
||||||
@@ -7065,7 +7065,7 @@ msgstr "Questo contenuto non è disponibile perché uno degli utenti coinvolti h
|
|||||||
msgid "This content is not viewable without a Bluesky account."
|
msgid "This content is not viewable without a Bluesky account."
|
||||||
msgstr "Questo contenuto non è visualizzabile senza un account Bluesky."
|
msgstr "Questo contenuto non è visualizzabile senza un account Bluesky."
|
||||||
|
|
||||||
#: src/screens/Messages/components/ChatListItem.tsx:276
|
#: src/screens/Messages/components/ChatListItem.tsx:284
|
||||||
msgid "This conversation is with a deleted or a deactivated account. Press for options."
|
msgid "This conversation is with a deleted or a deactivated account. Press for options."
|
||||||
msgstr "L'utente di questa conversazione ha disattivato o eliminato l'account. Premi per le opzioni."
|
msgstr "L'utente di questa conversazione ha disattivato o eliminato l'account. Premi per le opzioni."
|
||||||
|
|
||||||
@@ -7180,7 +7180,7 @@ msgstr "Questo dovrebbe creare un record di dominio in:"
|
|||||||
msgid "This user doesn't have any followers."
|
msgid "This user doesn't have any followers."
|
||||||
msgstr "Questo utente non ha follower."
|
msgstr "Questo utente non ha follower."
|
||||||
|
|
||||||
#: src/components/dms/MessagesListBlockedFooter.tsx:60
|
#: src/components/dms/MessagesListBlockedFooter.tsx:67
|
||||||
msgid "This user has blocked you"
|
msgid "This user has blocked you"
|
||||||
msgstr "Questo utente ti ha bloccato"
|
msgstr "Questo utente ti ha bloccato"
|
||||||
|
|
||||||
@@ -7359,10 +7359,10 @@ msgstr "Impossibile contattare il servizio. Verifica la tua connessione a intern
|
|||||||
msgid "Unable to delete"
|
msgid "Unable to delete"
|
||||||
msgstr "Impossibile eliminare"
|
msgstr "Impossibile eliminare"
|
||||||
|
|
||||||
#: src/components/dms/MessagesListBlockedFooter.tsx:89
|
|
||||||
#: src/components/dms/MessagesListBlockedFooter.tsx:96
|
#: src/components/dms/MessagesListBlockedFooter.tsx:96
|
||||||
#: src/components/dms/MessagesListBlockedFooter.tsx:104
|
#: src/components/dms/MessagesListBlockedFooter.tsx:103
|
||||||
#: src/components/dms/MessagesListBlockedFooter.tsx:111
|
#: src/components/dms/MessagesListBlockedFooter.tsx:111
|
||||||
|
#: src/components/dms/MessagesListBlockedFooter.tsx:118
|
||||||
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:197
|
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:197
|
||||||
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:283
|
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:283
|
||||||
#: src/view/com/profile/ProfileMenu.tsx:341
|
#: src/view/com/profile/ProfileMenu.tsx:341
|
||||||
@@ -7375,8 +7375,8 @@ msgctxt "action"
|
|||||||
msgid "Unblock"
|
msgid "Unblock"
|
||||||
msgstr "Sblocca"
|
msgstr "Sblocca"
|
||||||
|
|
||||||
#: src/components/dms/ConvoMenu.tsx:191
|
#: src/components/dms/ConvoMenu.tsx:250
|
||||||
#: src/components/dms/ConvoMenu.tsx:195
|
#: src/components/dms/ConvoMenu.tsx:253
|
||||||
msgid "Unblock account"
|
msgid "Unblock account"
|
||||||
msgstr "Sblocca account"
|
msgstr "Sblocca account"
|
||||||
|
|
||||||
@@ -7399,7 +7399,7 @@ msgstr "Annulla ripubblicazione"
|
|||||||
msgid "Undo repost ({0, plural, one {# repost} other {# reposts}})"
|
msgid "Undo repost ({0, plural, one {# repost} other {# reposts}})"
|
||||||
msgstr "Annulla ripubblicazione ({0, plural, one {# ripubblicazione} other {# ripubblicazioni}})"
|
msgstr "Annulla ripubblicazione ({0, plural, one {# ripubblicazione} other {# ripubblicazioni}})"
|
||||||
|
|
||||||
#: src/view/com/profile/FollowButton.tsx:60
|
#: src/view/com/profile/FollowButton.tsx:63
|
||||||
msgctxt "action"
|
msgctxt "action"
|
||||||
msgid "Unfollow"
|
msgid "Unfollow"
|
||||||
msgstr "Smetti di seguire"
|
msgstr "Smetti di seguire"
|
||||||
@@ -7413,7 +7413,7 @@ msgstr "Smetti di seguire {0}"
|
|||||||
msgid "Unfollow Account"
|
msgid "Unfollow Account"
|
||||||
msgstr "Smetti di seguire questo account"
|
msgstr "Smetti di seguire questo account"
|
||||||
|
|
||||||
#: src/screens/VideoFeed/index.tsx:801
|
#: src/screens/VideoFeed/index.tsx:803
|
||||||
msgid "Unfollow user"
|
msgid "Unfollow user"
|
||||||
msgstr "Smetti di seguire"
|
msgstr "Smetti di seguire"
|
||||||
|
|
||||||
@@ -7445,7 +7445,7 @@ msgstr "Riattiva {tag}"
|
|||||||
msgid "Unmute Account"
|
msgid "Unmute Account"
|
||||||
msgstr "Riattiva questo account"
|
msgstr "Riattiva questo account"
|
||||||
|
|
||||||
#: src/components/dms/ConvoMenu.tsx:179
|
#: src/components/dms/ConvoMenu.tsx:239
|
||||||
msgid "Unmute conversation"
|
msgid "Unmute conversation"
|
||||||
msgstr "Riattiva conversazione"
|
msgstr "Riattiva conversazione"
|
||||||
|
|
||||||
@@ -7746,11 +7746,11 @@ msgstr "Video da {0}: {text}"
|
|||||||
msgid "Video Games"
|
msgid "Video Games"
|
||||||
msgstr "Videogiochi"
|
msgstr "Videogiochi"
|
||||||
|
|
||||||
#: src/screens/VideoFeed/index.tsx:1029
|
#: src/screens/VideoFeed/index.tsx:1031
|
||||||
msgid "Video is paused"
|
msgid "Video is paused"
|
||||||
msgstr "Video in pausa"
|
msgstr "Video in pausa"
|
||||||
|
|
||||||
#: src/screens/VideoFeed/index.tsx:1029
|
#: src/screens/VideoFeed/index.tsx:1031
|
||||||
msgid "Video is playing"
|
msgid "Video is playing"
|
||||||
msgstr "Video in riproduzione"
|
msgstr "Video in riproduzione"
|
||||||
|
|
||||||
@@ -7785,12 +7785,12 @@ msgstr "Vedi l'avatar di {0}"
|
|||||||
|
|
||||||
#: src/components/ProfileCard.tsx:110
|
#: src/components/ProfileCard.tsx:110
|
||||||
#: src/screens/Profile/components/ProfileFeedHeader.tsx:450
|
#: src/screens/Profile/components/ProfileFeedHeader.tsx:450
|
||||||
#: src/screens/VideoFeed/index.tsx:762
|
#: src/screens/VideoFeed/index.tsx:763
|
||||||
#: src/view/com/notifications/NotificationFeedItem.tsx:409
|
#: src/view/com/notifications/NotificationFeedItem.tsx:409
|
||||||
msgid "View {0}'s profile"
|
msgid "View {0}'s profile"
|
||||||
msgstr "Vedi il profilo di {0}"
|
msgstr "Vedi il profilo di {0}"
|
||||||
|
|
||||||
#: src/components/dms/MessagesListHeader.tsx:167
|
#: src/components/dms/MessagesListHeader.tsx:173
|
||||||
msgid "View {displayName}'s profile"
|
msgid "View {displayName}'s profile"
|
||||||
msgstr "Vedi il profilo di {displayName}"
|
msgstr "Vedi il profilo di {displayName}"
|
||||||
|
|
||||||
@@ -7905,7 +7905,7 @@ msgstr "Non siamo riusciti a trovare alcun risultato per quell'hashtag."
|
|||||||
msgid "We couldn't find any results for that topic."
|
msgid "We couldn't find any results for that topic."
|
||||||
msgstr "Nessun risultato per questo argomento."
|
msgstr "Nessun risultato per questo argomento."
|
||||||
|
|
||||||
#: src/screens/Messages/Conversation.tsx:103
|
#: src/screens/Messages/Conversation.tsx:113
|
||||||
msgid "We couldn't load this conversation"
|
msgid "We couldn't load this conversation"
|
||||||
msgstr "Non riusciamo a caricare questa conversazione"
|
msgstr "Non riusciamo a caricare questa conversazione"
|
||||||
|
|
||||||
@@ -8037,7 +8037,7 @@ msgstr "Ops! Non è stato possibile caricare i video di tendenza."
|
|||||||
|
|
||||||
#: src/screens/Takendown.tsx:173
|
#: src/screens/Takendown.tsx:173
|
||||||
msgid "Why are you appealing?"
|
msgid "Why are you appealing?"
|
||||||
msgstr "Perché richiedi la revisione?"
|
msgstr "Per quale motivo fai ricorso?"
|
||||||
|
|
||||||
#: src/components/ReportDialog/SelectReportOptionView.tsx:42
|
#: src/components/ReportDialog/SelectReportOptionView.tsx:42
|
||||||
msgid "Why should this content be reviewed?"
|
msgid "Why should this content be reviewed?"
|
||||||
@@ -8192,7 +8192,7 @@ msgstr "Non hai salvato nessun feed."
|
|||||||
msgid "You have blocked the author or you have been blocked by the author."
|
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."
|
msgstr "Hai bloccato l'autore o sei stato bloccato dall'autore."
|
||||||
|
|
||||||
#: src/components/dms/MessagesListBlockedFooter.tsx:58
|
#: src/components/dms/MessagesListBlockedFooter.tsx:65
|
||||||
msgid "You have blocked this user"
|
msgid "You have blocked this user"
|
||||||
msgstr "Hai bloccato questo utente"
|
msgstr "Hai bloccato questo utente"
|
||||||
|
|
||||||
@@ -8329,15 +8329,15 @@ msgstr "Riceverai le notifiche per questo thread"
|
|||||||
msgid "You will receive an email with a \"reset code.\" Enter that code here, then enter your new password."
|
msgid "You will receive an email with a \"reset code.\" Enter that code here, then enter your new password."
|
||||||
msgstr "Riceverai un'email con un codice di recupero. Inserisci il codice qui, poi inserisci la tua nuova password."
|
msgstr "Riceverai un'email con un codice di recupero. Inserisci il codice qui, poi inserisci la tua nuova password."
|
||||||
|
|
||||||
#: src/screens/Messages/components/ChatListItem.tsx:133
|
#: src/screens/Messages/components/ChatListItem.tsx:139
|
||||||
msgid "You: {0}"
|
msgid "You: {0}"
|
||||||
msgstr "Tu: {0}"
|
msgstr "Tu: {0}"
|
||||||
|
|
||||||
#: src/screens/Messages/components/ChatListItem.tsx:162
|
#: src/screens/Messages/components/ChatListItem.tsx:168
|
||||||
msgid "You: {defaultEmbeddedContentMessage}"
|
msgid "You: {defaultEmbeddedContentMessage}"
|
||||||
msgstr "Tu: {defaultEmbeddedContentMessage}"
|
msgstr "Tu: {defaultEmbeddedContentMessage}"
|
||||||
|
|
||||||
#: src/screens/Messages/components/ChatListItem.tsx:155
|
#: src/screens/Messages/components/ChatListItem.tsx:161
|
||||||
msgid "You: {short}"
|
msgid "You: {short}"
|
||||||
msgstr "Tu: {short}"
|
msgstr "Tu: {short}"
|
||||||
|
|
||||||
@@ -8399,7 +8399,7 @@ msgstr "Hai raggiunto il limite giornaliero di video caricati (troppi byte)"
|
|||||||
msgid "You've reached your daily limit for video uploads (too many videos)"
|
msgid "You've reached your daily limit for video uploads (too many videos)"
|
||||||
msgstr "Hai raggiunto il limite giornaliero di video caricati (troppi video)"
|
msgstr "Hai raggiunto il limite giornaliero di video caricati (troppi video)"
|
||||||
|
|
||||||
#: src/screens/VideoFeed/index.tsx:1080
|
#: src/screens/VideoFeed/index.tsx:1082
|
||||||
msgid "You've run out of videos to watch. Maybe it's a good time to take a break?"
|
msgid "You've run out of videos to watch. Maybe it's a good time to take a break?"
|
||||||
msgstr "Non ci sono altri video da guardare. Forse è il momento giusto per fare una pausa?"
|
msgstr "Non ci sono altri video da guardare. Forse è il momento giusto per fare una pausa?"
|
||||||
|
|
||||||
@@ -8425,11 +8425,11 @@ msgstr "L'archivio del tuo account, che contiene tutti i record di dati pubblici
|
|||||||
|
|
||||||
#: src/screens/Takendown.tsx:214
|
#: src/screens/Takendown.tsx:214
|
||||||
msgid "Your account was found to be in violation of the <0>Bluesky Social Terms of Service</0>. You have been sent an email outlining the specific violation and suspension period, if applicable. You can appeal this decision if you believe it was made in error."
|
msgid "Your account was found to be in violation of the <0>Bluesky Social Terms of Service</0>. You have been sent an email outlining the specific violation and suspension period, if applicable. You can appeal this decision if you believe it was made in error."
|
||||||
msgstr "Abbiamo riscontrato che il tuo account viola i <0>termini di servizio di Bluesky Social</0>. Ti abbiamo inviato un'email che descrive la violazione e il periodo di sospensione, se applicabile. Se ritieni che questa decisione sia stata presa per errore, puoi richiedere una revisione della sospensione."
|
msgstr "Abbiamo riscontrato che il tuo account viola i <0>termini di servizio di Bluesky</0>. Ti abbiamo inviato un'email che descrive la violazione e il periodo di sospensione, se applicabile. Se ritieni che questa decisione sia stata presa per errore, puoi richiedere una revisione della sospensione."
|
||||||
|
|
||||||
#: src/screens/Takendown.tsx:154
|
#: src/screens/Takendown.tsx:154
|
||||||
msgid "Your appeal has been submitted. If your appeal succeeds, you will receive an email."
|
msgid "Your appeal has been submitted. If your appeal succeeds, you will receive an email."
|
||||||
msgstr "La tua richiesta di revisione è stata inviata. Riceverai un'email se la revisione avrà esito positivo."
|
msgstr "La richiesta di revisione è stata inviata. Se il ricorso ha esito positivo, riceverai un'email."
|
||||||
|
|
||||||
#: src/screens/Signup/StepInfo/index.tsx:205
|
#: src/screens/Signup/StepInfo/index.tsx:205
|
||||||
msgid "Your birth date"
|
msgid "Your birth date"
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+891
-611
File diff suppressed because it is too large
Load Diff
@@ -13,6 +13,7 @@ export const router = new Router({
|
|||||||
ModerationModlists: '/moderation/modlists',
|
ModerationModlists: '/moderation/modlists',
|
||||||
ModerationMutedAccounts: '/moderation/muted-accounts',
|
ModerationMutedAccounts: '/moderation/muted-accounts',
|
||||||
ModerationBlockedAccounts: '/moderation/blocked-accounts',
|
ModerationBlockedAccounts: '/moderation/blocked-accounts',
|
||||||
|
ModerationInteractionSettings: '/moderation/interaction-settings',
|
||||||
// profiles, threads, lists
|
// profiles, threads, lists
|
||||||
Profile: ['/profile/:name', '/profile/:name/rss'],
|
Profile: ['/profile/:name', '/profile/:name/rss'],
|
||||||
ProfileFollowers: '/profile/:name/followers',
|
ProfileFollowers: '/profile/:name/followers',
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ export const LoginForm = ({
|
|||||||
onSubmitEditing={onPressNext}
|
onSubmitEditing={onPressNext}
|
||||||
blurOnSubmit={false} // HACK: https://github.com/facebook/react-native/issues/21911#issuecomment-558343069 Keyboard blur behavior is now handled in onSubmitEditing
|
blurOnSubmit={false} // HACK: https://github.com/facebook/react-native/issues/21911#issuecomment-558343069 Keyboard blur behavior is now handled in onSubmitEditing
|
||||||
editable={!isProcessing}
|
editable={!isProcessing}
|
||||||
accessibilityHint={_(msg`Input your password`)}
|
accessibilityHint={_(msg`Enter your password`)}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
testID="forgotPasswordButton"
|
testID="forgotPasswordButton"
|
||||||
|
|||||||
@@ -281,7 +281,7 @@ function ChatListItemReady({
|
|||||||
!isDeletedAccount
|
!isDeletedAccount
|
||||||
? _(msg`Go to conversation with ${profile.handle}`)
|
? _(msg`Go to conversation with ${profile.handle}`)
|
||||||
: _(
|
: _(
|
||||||
msg`This conversation is with a deleted or a deactivated account. Press for options.`,
|
msg`This conversation is with a deleted or a deactivated account. Press for options`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
accessibilityActions={
|
accessibilityActions={
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import * as Toggle from '#/components/forms/Toggle'
|
|||||||
import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRight} from '#/components/icons/Chevron'
|
import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRight} from '#/components/icons/Chevron'
|
||||||
import {CircleBanSign_Stroke2_Corner0_Rounded as CircleBanSign} from '#/components/icons/CircleBanSign'
|
import {CircleBanSign_Stroke2_Corner0_Rounded as CircleBanSign} from '#/components/icons/CircleBanSign'
|
||||||
import {Props as SVGIconProps} from '#/components/icons/common'
|
import {Props as SVGIconProps} from '#/components/icons/common'
|
||||||
|
import {EditBig_Stroke2_Corner0_Rounded as EditBig} from '#/components/icons/EditBig'
|
||||||
import {Filter_Stroke2_Corner0_Rounded as Filter} from '#/components/icons/Filter'
|
import {Filter_Stroke2_Corner0_Rounded as Filter} from '#/components/icons/Filter'
|
||||||
import {Group3_Stroke2_Corner0_Rounded as Group} from '#/components/icons/Group'
|
import {Group3_Stroke2_Corner0_Rounded as Group} from '#/components/icons/Group'
|
||||||
import {Person_Stroke2_Corner0_Rounded as Person} from '#/components/icons/Person'
|
import {Person_Stroke2_Corner0_Rounded as Person} from '#/components/icons/Person'
|
||||||
@@ -199,6 +200,21 @@ export function ModerationScreenInner({
|
|||||||
a.overflow_hidden,
|
a.overflow_hidden,
|
||||||
t.atoms.bg_contrast_25,
|
t.atoms.bg_contrast_25,
|
||||||
]}>
|
]}>
|
||||||
|
<Link
|
||||||
|
label={_(msg`View your default post interaction settings`)}
|
||||||
|
testID="interactionSettingsBtn"
|
||||||
|
to="/moderation/interaction-settings">
|
||||||
|
{state => (
|
||||||
|
<SubItem
|
||||||
|
title={_(msg`Interaction settings`)}
|
||||||
|
icon={EditBig}
|
||||||
|
style={[
|
||||||
|
(state.hovered || state.pressed) && [t.atoms.bg_contrast_50],
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Link>
|
||||||
|
<Divider />
|
||||||
<Button
|
<Button
|
||||||
testID="mutedWordsBtn"
|
testID="mutedWordsBtn"
|
||||||
label={_(msg`Open muted words and tags settings`)}
|
label={_(msg`Open muted words and tags settings`)}
|
||||||
|
|||||||
@@ -0,0 +1,127 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import {View} from 'react-native'
|
||||||
|
import {msg, Trans} from '@lingui/macro'
|
||||||
|
import {useLingui} from '@lingui/react'
|
||||||
|
import deepEqual from 'lodash.isequal'
|
||||||
|
|
||||||
|
import {logger} from '#/logger'
|
||||||
|
import {usePostInteractionSettingsMutation} from '#/state/queries/post-interaction-settings'
|
||||||
|
import {createPostgateRecord} from '#/state/queries/postgate/util'
|
||||||
|
import {
|
||||||
|
usePreferencesQuery,
|
||||||
|
UsePreferencesQueryResponse,
|
||||||
|
} from '#/state/queries/preferences'
|
||||||
|
import {
|
||||||
|
threadgateAllowUISettingToAllowRecordValue,
|
||||||
|
threadgateRecordToAllowUISetting,
|
||||||
|
} from '#/state/queries/threadgate'
|
||||||
|
import * as Toast from '#/view/com/util/Toast'
|
||||||
|
import {atoms as a, useGutters} from '#/alf'
|
||||||
|
import {Admonition} from '#/components/Admonition'
|
||||||
|
import {PostInteractionSettingsForm} from '#/components/dialogs/PostInteractionSettingsDialog'
|
||||||
|
import * as Layout from '#/components/Layout'
|
||||||
|
import {Loader} from '#/components/Loader'
|
||||||
|
|
||||||
|
export function Screen() {
|
||||||
|
const gutters = useGutters(['base'])
|
||||||
|
const {data: preferences} = usePreferencesQuery()
|
||||||
|
return (
|
||||||
|
<Layout.Screen testID="ModerationInteractionSettingsScreen">
|
||||||
|
<Layout.Header.Outer>
|
||||||
|
<Layout.Header.BackButton />
|
||||||
|
<Layout.Header.Content>
|
||||||
|
<Layout.Header.TitleText>
|
||||||
|
<Trans>Post Interaction Settings</Trans>
|
||||||
|
</Layout.Header.TitleText>
|
||||||
|
</Layout.Header.Content>
|
||||||
|
<Layout.Header.Slot />
|
||||||
|
</Layout.Header.Outer>
|
||||||
|
<Layout.Content>
|
||||||
|
<View style={[gutters, a.gap_xl]}>
|
||||||
|
<Admonition type="tip">
|
||||||
|
<Trans>
|
||||||
|
The following settings will be used as your defaults when creating
|
||||||
|
new posts. You can edit these for a specific post from the
|
||||||
|
composer.
|
||||||
|
</Trans>
|
||||||
|
</Admonition>
|
||||||
|
{preferences ? (
|
||||||
|
<Inner preferences={preferences} />
|
||||||
|
) : (
|
||||||
|
<View style={[gutters, a.justify_center, a.align_center]}>
|
||||||
|
<Loader size="xl" />
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</Layout.Content>
|
||||||
|
</Layout.Screen>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Inner({preferences}: {preferences: UsePreferencesQueryResponse}) {
|
||||||
|
const {_} = useLingui()
|
||||||
|
const {mutateAsync: setPostInteractionSettings, isPending} =
|
||||||
|
usePostInteractionSettingsMutation()
|
||||||
|
const [error, setError] = React.useState<string | undefined>(undefined)
|
||||||
|
|
||||||
|
const allowUI = React.useMemo(() => {
|
||||||
|
return threadgateRecordToAllowUISetting({
|
||||||
|
$type: 'app.bsky.feed.threadgate',
|
||||||
|
post: '',
|
||||||
|
createdAt: new Date().toString(),
|
||||||
|
allow: preferences.postInteractionSettings.threadgateAllowRules,
|
||||||
|
})
|
||||||
|
}, [preferences.postInteractionSettings.threadgateAllowRules])
|
||||||
|
const postgate = React.useMemo(() => {
|
||||||
|
return createPostgateRecord({
|
||||||
|
post: '',
|
||||||
|
embeddingRules:
|
||||||
|
preferences.postInteractionSettings.postgateEmbeddingRules,
|
||||||
|
})
|
||||||
|
}, [preferences.postInteractionSettings.postgateEmbeddingRules])
|
||||||
|
|
||||||
|
const [maybeEditedAllowUI, setAllowUI] = React.useState(allowUI)
|
||||||
|
const [maybeEditedPostgate, setEditedPostgate] = React.useState(postgate)
|
||||||
|
|
||||||
|
const wasEdited = React.useMemo(() => {
|
||||||
|
return (
|
||||||
|
!deepEqual(allowUI, maybeEditedAllowUI) ||
|
||||||
|
!deepEqual(postgate.embeddingRules, maybeEditedPostgate.embeddingRules)
|
||||||
|
)
|
||||||
|
}, [postgate, allowUI, maybeEditedAllowUI, maybeEditedPostgate])
|
||||||
|
|
||||||
|
const onSave = React.useCallback(async () => {
|
||||||
|
setError('')
|
||||||
|
|
||||||
|
try {
|
||||||
|
await setPostInteractionSettings({
|
||||||
|
threadgateAllowRules:
|
||||||
|
threadgateAllowUISettingToAllowRecordValue(maybeEditedAllowUI),
|
||||||
|
postgateEmbeddingRules: maybeEditedPostgate.embeddingRules ?? [],
|
||||||
|
})
|
||||||
|
Toast.show(_(msg`Settings saved`))
|
||||||
|
} catch (e: any) {
|
||||||
|
logger.error(`Failed to save post interaction settings`, {
|
||||||
|
context: 'ModerationInteractionSettingsScreen',
|
||||||
|
safeMessage: e.message,
|
||||||
|
})
|
||||||
|
setError(_(msg`Failed to save settings. Please try again.`))
|
||||||
|
}
|
||||||
|
}, [_, maybeEditedPostgate, maybeEditedAllowUI, setPostInteractionSettings])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<PostInteractionSettingsForm
|
||||||
|
canSave={wasEdited}
|
||||||
|
isSaving={isPending}
|
||||||
|
onSave={onSave}
|
||||||
|
postgate={maybeEditedPostgate}
|
||||||
|
onChangePostgate={setEditedPostgate}
|
||||||
|
threadgateAllowUISettings={maybeEditedAllowUI}
|
||||||
|
onChangeThreadgateAllowUISettings={setAllowUI}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{error && <Admonition type="error">{error}</Admonition>}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -53,9 +53,7 @@ export function Layout({children}: React.PropsWithChildren<{}>) {
|
|||||||
aria-role="dialog"
|
aria-role="dialog"
|
||||||
aria-label={dialogLabel}
|
aria-label={dialogLabel}
|
||||||
accessibilityLabel={dialogLabel}
|
accessibilityLabel={dialogLabel}
|
||||||
accessibilityHint={_(
|
accessibilityHint={_(msg`Customizes your Bluesky experience`)}
|
||||||
msg`The following steps will help customize your Bluesky experience.`,
|
|
||||||
)}
|
|
||||||
style={[
|
style={[
|
||||||
// @ts-ignore web only -prf
|
// @ts-ignore web only -prf
|
||||||
isWeb ? a.fixed : a.absolute,
|
isWeb ? a.fixed : a.absolute,
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ export function StepFinished() {
|
|||||||
setActiveStarterPack(undefined)
|
setActiveStarterPack(undefined)
|
||||||
setHasCheckedForStarterPack(true)
|
setHasCheckedForStarterPack(true)
|
||||||
startProgressGuide(
|
startProgressGuide(
|
||||||
gate('new_postonboarding') ? 'follow-10' : 'like-10-and-follow-7',
|
gate('old_postonboarding') ? 'like-10-and-follow-7' : 'follow-10',
|
||||||
)
|
)
|
||||||
dispatch({type: 'finish'})
|
dispatch({type: 'finish'})
|
||||||
onboardDispatch({type: 'finish'})
|
onboardDispatch({type: 'finish'})
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import {Apple_Stroke2_Corner0_Rounded as Apple} from '#/components/icons/Apple'
|
|||||||
import {At_Stroke2_Corner0_Rounded as At} from '#/components/icons/At'
|
import {At_Stroke2_Corner0_Rounded as At} from '#/components/icons/At'
|
||||||
import {Atom_Stroke2_Corner0_Rounded as Atom} from '#/components/icons/Atom'
|
import {Atom_Stroke2_Corner0_Rounded as Atom} from '#/components/icons/Atom'
|
||||||
import {Celebrate_Stroke2_Corner0_Rounded as Celebrate} from '#/components/icons/Celebrate'
|
import {Celebrate_Stroke2_Corner0_Rounded as Celebrate} from '#/components/icons/Celebrate'
|
||||||
import {Coffee_Stroke2_Corner0_Rounded as Coffee} from '#/components/icons/Coffee'
|
|
||||||
import {
|
import {
|
||||||
EmojiArc_Stroke2_Corner0_Rounded as EmojiArc,
|
EmojiArc_Stroke2_Corner0_Rounded as EmojiArc,
|
||||||
EmojiHeartEyes_Stroke2_Corner0_Rounded as EmojiHeartEyes,
|
EmojiHeartEyes_Stroke2_Corner0_Rounded as EmojiHeartEyes,
|
||||||
@@ -13,8 +12,6 @@ import {GameController_Stroke2_Corner0_Rounded as GameController} from '#/compon
|
|||||||
import {Lab_Stroke2_Corner0_Rounded as Lab} from '#/components/icons/Lab'
|
import {Lab_Stroke2_Corner0_Rounded as Lab} from '#/components/icons/Lab'
|
||||||
import {Leaf_Stroke2_Corner0_Rounded as Leaf} from '#/components/icons/Leaf'
|
import {Leaf_Stroke2_Corner0_Rounded as Leaf} from '#/components/icons/Leaf'
|
||||||
import {MusicNote_Stroke2_Corner0_Rounded as MusicNote} from '#/components/icons/MusicNote'
|
import {MusicNote_Stroke2_Corner0_Rounded as MusicNote} from '#/components/icons/MusicNote'
|
||||||
import {PiggyBank_Stroke2_Corner0_Rounded as PiggyBank} from '#/components/icons/PiggyBank'
|
|
||||||
import {Poop_Stroke2_Corner0_Rounded as Poop} from '#/components/icons/Poop'
|
|
||||||
import {Rose_Stroke2_Corner0_Rounded as Rose} from '#/components/icons/Rose'
|
import {Rose_Stroke2_Corner0_Rounded as Rose} from '#/components/icons/Rose'
|
||||||
import {Shaka_Stroke2_Corner0_Rounded as Shaka} from '#/components/icons/Shaka'
|
import {Shaka_Stroke2_Corner0_Rounded as Shaka} from '#/components/icons/Shaka'
|
||||||
import {UFO_Stroke2_Corner0_Rounded as UFO} from '#/components/icons/UFO'
|
import {UFO_Stroke2_Corner0_Rounded as UFO} from '#/components/icons/UFO'
|
||||||
@@ -33,7 +30,6 @@ export const emojiNames = [
|
|||||||
'apple',
|
'apple',
|
||||||
'atom',
|
'atom',
|
||||||
'celebrate',
|
'celebrate',
|
||||||
'coffee',
|
|
||||||
'gameController',
|
'gameController',
|
||||||
'leaf',
|
'leaf',
|
||||||
'musicNote',
|
'musicNote',
|
||||||
@@ -43,8 +39,6 @@ export const emojiNames = [
|
|||||||
'zap',
|
'zap',
|
||||||
'explosion',
|
'explosion',
|
||||||
'lab',
|
'lab',
|
||||||
'piggyBank',
|
|
||||||
'poop',
|
|
||||||
] as const
|
] as const
|
||||||
export type EmojiName = (typeof emojiNames)[number]
|
export type EmojiName = (typeof emojiNames)[number]
|
||||||
|
|
||||||
@@ -81,10 +75,6 @@ export const emojiItems: Record<EmojiName, Emoji> = {
|
|||||||
name: 'celebrate',
|
name: 'celebrate',
|
||||||
component: Celebrate,
|
component: Celebrate,
|
||||||
},
|
},
|
||||||
coffee: {
|
|
||||||
name: 'coffee',
|
|
||||||
component: Coffee,
|
|
||||||
},
|
|
||||||
gameController: {
|
gameController: {
|
||||||
name: 'gameController',
|
name: 'gameController',
|
||||||
component: GameController,
|
component: GameController,
|
||||||
@@ -121,14 +111,6 @@ export const emojiItems: Record<EmojiName, Emoji> = {
|
|||||||
name: 'lab',
|
name: 'lab',
|
||||||
component: Lab,
|
component: Lab,
|
||||||
},
|
},
|
||||||
piggyBank: {
|
|
||||||
name: 'piggyBank',
|
|
||||||
component: PiggyBank,
|
|
||||||
},
|
|
||||||
poop: {
|
|
||||||
name: 'poop',
|
|
||||||
component: Poop,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const avatarColors = [
|
export const avatarColors = [
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export function ErrorState({error}: {error: string}) {
|
|||||||
color="secondary"
|
color="secondary"
|
||||||
variant="solid"
|
variant="solid"
|
||||||
label={_(msg`Go Back`)}
|
label={_(msg`Go Back`)}
|
||||||
accessibilityHint="Return to previous page"
|
accessibilityHint="Returns to previous page"
|
||||||
onPress={onPressBack}>
|
onPress={onPressBack}>
|
||||||
<ButtonText>
|
<ButtonText>
|
||||||
<Trans>Go Back</Trans>
|
<Trans>Go Back</Trans>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import {View} from 'react-native'
|
import {View} from 'react-native'
|
||||||
|
import {AppBskyUnspeccedDefs} from '@atproto/api'
|
||||||
import {Trans} from '@lingui/macro'
|
import {Trans} from '@lingui/macro'
|
||||||
|
|
||||||
import {logEvent} from '#/lib/statsig/statsig'
|
import {logEvent} from '#/lib/statsig/statsig'
|
||||||
@@ -27,6 +28,7 @@ function Inner() {
|
|||||||
const gutters = useGutters([0, 'compact'])
|
const gutters = useGutters([0, 'compact'])
|
||||||
const {data: trending, error, isLoading} = useTrendingTopics()
|
const {data: trending, error, isLoading} = useTrendingTopics()
|
||||||
const noRecs = !isLoading && !error && !trending?.suggested?.length
|
const noRecs = !isLoading && !error && !trending?.suggested?.length
|
||||||
|
const allFeeds = trending?.suggested && isAllFeeds(trending.suggested)
|
||||||
|
|
||||||
return error || noRecs ? null : (
|
return error || noRecs ? null : (
|
||||||
<>
|
<>
|
||||||
@@ -50,9 +52,17 @@ function Inner() {
|
|||||||
<Trans>Recommended</Trans>
|
<Trans>Recommended</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<Text style={[t.atoms.text_contrast_high, a.leading_snug]}>
|
{!allFeeds ? (
|
||||||
<Trans>Feeds we think you might like.</Trans>
|
<Text style={[t.atoms.text_contrast_high, a.leading_snug]}>
|
||||||
</Text>
|
<Trans>
|
||||||
|
Content from across the network we think you might like.
|
||||||
|
</Trans>
|
||||||
|
</Text>
|
||||||
|
) : (
|
||||||
|
<Text style={[t.atoms.text_contrast_high, a.leading_snug]}>
|
||||||
|
<Trans>Feeds we think you might like.</Trans>
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
@@ -98,3 +108,10 @@ function Inner() {
|
|||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isAllFeeds(topics: AppBskyUnspeccedDefs.TrendingTopic[]) {
|
||||||
|
return topics.every(topic => {
|
||||||
|
const segments = topic.link.split('/').slice(1)
|
||||||
|
return segments[0] === 'profile' && segments[2] === 'feed'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
|||||||
import {appVersion, BUNDLE_DATE, bundleInfo} from '#/lib/app-info'
|
import {appVersion, BUNDLE_DATE, bundleInfo} from '#/lib/app-info'
|
||||||
import {STATUS_PAGE_URL} from '#/lib/constants'
|
import {STATUS_PAGE_URL} from '#/lib/constants'
|
||||||
import {CommonNavigatorParams} from '#/lib/routes/types'
|
import {CommonNavigatorParams} from '#/lib/routes/types'
|
||||||
|
import {useDevModeEnabled} from '#/state/preferences/dev-mode'
|
||||||
import * as Toast from '#/view/com/util/Toast'
|
import * as Toast from '#/view/com/util/Toast'
|
||||||
import * as SettingsList from '#/screens/Settings/components/SettingsList'
|
import * as SettingsList from '#/screens/Settings/components/SettingsList'
|
||||||
import {CodeLines_Stroke2_Corner2_Rounded as CodeLinesIcon} from '#/components/icons/CodeLines'
|
import {CodeLines_Stroke2_Corner2_Rounded as CodeLinesIcon} from '#/components/icons/CodeLines'
|
||||||
@@ -18,6 +19,7 @@ import * as Layout from '#/components/Layout'
|
|||||||
type Props = NativeStackScreenProps<CommonNavigatorParams, 'AboutSettings'>
|
type Props = NativeStackScreenProps<CommonNavigatorParams, 'AboutSettings'>
|
||||||
export function AboutSettingsScreen({}: Props) {
|
export function AboutSettingsScreen({}: Props) {
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
const [devModeEnabled, setDevModeEnabled] = useDevModeEnabled()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout.Screen>
|
<Layout.Screen>
|
||||||
@@ -65,7 +67,16 @@ export function AboutSettingsScreen({}: Props) {
|
|||||||
</SettingsList.LinkItem>
|
</SettingsList.LinkItem>
|
||||||
<SettingsList.PressableItem
|
<SettingsList.PressableItem
|
||||||
label={_(msg`Version ${appVersion}`)}
|
label={_(msg`Version ${appVersion}`)}
|
||||||
accessibilityHint={_(msg`Copy build version to clipboard`)}
|
accessibilityHint={_(msg`Copies build version to clipboard`)}
|
||||||
|
onLongPress={() => {
|
||||||
|
const newDevModeEnabled = !devModeEnabled
|
||||||
|
setDevModeEnabled(newDevModeEnabled)
|
||||||
|
Toast.show(
|
||||||
|
newDevModeEnabled
|
||||||
|
? _(msg`Developer mode enabled`)
|
||||||
|
: _(msg`Developer mode disabled`),
|
||||||
|
)
|
||||||
|
}}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
setStringAsync(
|
setStringAsync(
|
||||||
`Build version: ${appVersion}; Bundle info: ${bundleInfo}; Bundle date: ${BUNDLE_DATE}; Platform: ${Platform.OS}; Platform version: ${Platform.Version}`,
|
`Build version: ${appVersion}; Bundle info: ${bundleInfo}; Bundle date: ${BUNDLE_DATE}; Platform: ${Platform.OS}; Platform version: ${Platform.Version}`,
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ export function AccountSettingsScreen({}: Props) {
|
|||||||
</SettingsList.PressableItem>
|
</SettingsList.PressableItem>
|
||||||
<SettingsList.PressableItem
|
<SettingsList.PressableItem
|
||||||
label={_(msg`Handle`)}
|
label={_(msg`Handle`)}
|
||||||
accessibilityHint={_(msg`Open change handle dialog`)}
|
accessibilityHint={_(msg`Opens change handle dialog`)}
|
||||||
onPress={() => changeHandleControl.open()}>
|
onPress={() => changeHandleControl.open()}>
|
||||||
<SettingsList.ItemIcon icon={AtIcon} />
|
<SettingsList.ItemIcon icon={AtIcon} />
|
||||||
<SettingsList.ItemText>
|
<SettingsList.ItemText>
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ function AppIcon({icon, size = 50}: {icon: AppIconSet; size: number}) {
|
|||||||
return (
|
return (
|
||||||
<PressableScale
|
<PressableScale
|
||||||
accessibilityLabel={icon.name}
|
accessibilityLabel={icon.name}
|
||||||
accessibilityHint={_(msg`Tap to change app icon`)}
|
accessibilityHint={_(msg`Changes app icon`)}
|
||||||
targetScale={0.95}
|
targetScale={0.95}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
if (isAndroid) {
|
if (isAndroid) {
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ export function SettingsScreen({}: Props) {
|
|||||||
<SettingsList.PressableItem
|
<SettingsList.PressableItem
|
||||||
label={_(msg`Switch account`)}
|
label={_(msg`Switch account`)}
|
||||||
accessibilityHint={_(
|
accessibilityHint={_(
|
||||||
msg`Show other accounts you can switch to`,
|
msg`Shows other accounts you can switch to`,
|
||||||
)}
|
)}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
if (!reducedMotion) {
|
if (!reducedMotion) {
|
||||||
@@ -205,7 +205,7 @@ export function SettingsScreen({}: Props) {
|
|||||||
<SettingsList.PressableItem
|
<SettingsList.PressableItem
|
||||||
onPress={() => Linking.openURL(HELP_DESK_URL)}
|
onPress={() => Linking.openURL(HELP_DESK_URL)}
|
||||||
label={_(msg`Help`)}
|
label={_(msg`Help`)}
|
||||||
accessibilityHint={_(msg`Open helpdesk in browser`)}>
|
accessibilityHint={_(msg`Opens helpdesk in browser`)}>
|
||||||
<SettingsList.ItemIcon icon={CircleQuestionIcon} />
|
<SettingsList.ItemIcon icon={CircleQuestionIcon} />
|
||||||
<SettingsList.ItemText>
|
<SettingsList.ItemText>
|
||||||
<Trans>Help</Trans>
|
<Trans>Help</Trans>
|
||||||
@@ -421,7 +421,7 @@ function AccountRow({
|
|||||||
<View style={[{width: 28}]} />
|
<View style={[{width: 28}]} />
|
||||||
)}
|
)}
|
||||||
<SettingsList.ItemText>
|
<SettingsList.ItemText>
|
||||||
<Trans>{sanitizeHandle(account.handle, '@')}</Trans>
|
{sanitizeHandle(account.handle, '@')}
|
||||||
</SettingsList.ItemText>
|
</SettingsList.ItemText>
|
||||||
{pendingDid === account.did && <SettingsList.ItemIcon icon={Loader} />}
|
{pendingDid === account.did && <SettingsList.ItemIcon icon={Loader} />}
|
||||||
</SettingsList.PressableItem>
|
</SettingsList.PressableItem>
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ import {useMutation, useQueryClient} from '@tanstack/react-query'
|
|||||||
|
|
||||||
import {HITSLOP_10} from '#/lib/constants'
|
import {HITSLOP_10} from '#/lib/constants'
|
||||||
import {cleanError} from '#/lib/strings/errors'
|
import {cleanError} from '#/lib/strings/errors'
|
||||||
|
import {createFullHandle, validateServiceHandle} from '#/lib/strings/handles'
|
||||||
import {sanitizeHandle} from '#/lib/strings/handles'
|
import {sanitizeHandle} from '#/lib/strings/handles'
|
||||||
import {createFullHandle, validateHandle} from '#/lib/strings/handles'
|
|
||||||
import {useFetchDid, useUpdateHandleMutation} from '#/state/queries/handle'
|
import {useFetchDid, useUpdateHandleMutation} from '#/state/queries/handle'
|
||||||
import {RQKEY as RQKEY_PROFILE} from '#/state/queries/profile'
|
import {RQKEY as RQKEY_PROFILE} from '#/state/queries/profile'
|
||||||
import {useServiceQuery} from '#/state/queries/service'
|
import {useServiceQuery} from '#/state/queries/service'
|
||||||
@@ -172,7 +172,7 @@ function ProvidedHandlePage({
|
|||||||
const host = serviceInfo.availableUserDomains[0]
|
const host = serviceInfo.availableUserDomains[0]
|
||||||
|
|
||||||
const validation = useMemo(
|
const validation = useMemo(
|
||||||
() => validateHandle(subdomain, host, true),
|
() => validateServiceHandle(subdomain, host),
|
||||||
[subdomain, host],
|
[subdomain, host],
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -537,7 +537,7 @@ function OwnHandlePage({goToServiceHandle}: {goToServiceHandle: () => void}) {
|
|||||||
|
|
||||||
<Button
|
<Button
|
||||||
label={_(msg`Use default provider`)}
|
label={_(msg`Use default provider`)}
|
||||||
accessibilityHint={_(msg`Go back to previous page`)}
|
accessibilityHint={_(msg`Returns to previous page`)}
|
||||||
onPress={goToServiceHandle}
|
onPress={goToServiceHandle}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {logEvent} from '#/lib/statsig/statsig'
|
|||||||
import {
|
import {
|
||||||
createFullHandle,
|
createFullHandle,
|
||||||
maxServiceHandleLength,
|
maxServiceHandleLength,
|
||||||
validateHandle,
|
validateServiceHandle,
|
||||||
} from '#/lib/strings/handles'
|
} from '#/lib/strings/handles'
|
||||||
import {useAgent} from '#/state/session'
|
import {useAgent} from '#/state/session'
|
||||||
import {ScreenTransition} from '#/screens/Login/ScreenTransition'
|
import {ScreenTransition} from '#/screens/Login/ScreenTransition'
|
||||||
@@ -37,7 +37,7 @@ export function StepHandle() {
|
|||||||
value: handle,
|
value: handle,
|
||||||
})
|
})
|
||||||
|
|
||||||
const newValidCheck = validateHandle(handle, state.userDomain)
|
const newValidCheck = validateServiceHandle(handle, state.userDomain)
|
||||||
if (!newValidCheck.overall) {
|
if (!newValidCheck.overall) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -97,7 +97,7 @@ export function StepHandle() {
|
|||||||
})
|
})
|
||||||
}, [dispatch, state.activeStep])
|
}, [dispatch, state.activeStep])
|
||||||
|
|
||||||
const validCheck = validateHandle(draftValue, state.userDomain, true)
|
const validCheck = validateServiceHandle(draftValue, state.userDomain)
|
||||||
return (
|
return (
|
||||||
<ScreenTransition>
|
<ScreenTransition>
|
||||||
<View style={[a.gap_lg]}>
|
<View style={[a.gap_lg]}>
|
||||||
|
|||||||
@@ -285,7 +285,7 @@ function WizardInner({
|
|||||||
<Layout.Header.Outer>
|
<Layout.Header.Outer>
|
||||||
<Layout.Header.BackButton
|
<Layout.Header.BackButton
|
||||||
label={_(msg`Back`)}
|
label={_(msg`Back`)}
|
||||||
accessibilityHint={_(msg`Go back to the previous step`)}
|
accessibilityHint={_(msg`Returns to the previous step`)}
|
||||||
onPress={evt => {
|
onPress={evt => {
|
||||||
if (state.currentStep !== 'Details') {
|
if (state.currentStep !== 'Details') {
|
||||||
evt.preventDefault()
|
evt.preventDefault()
|
||||||
|
|||||||
@@ -806,7 +806,9 @@ function Overlay({
|
|||||||
: _(msg`Follow ${handle}`)
|
: _(msg`Follow ${handle}`)
|
||||||
}
|
}
|
||||||
accessibilityHint={
|
accessibilityHint={
|
||||||
profile.viewer?.following ? _(msg`Unfollow user`) : ''
|
profile.viewer?.following
|
||||||
|
? _(msg`Unfollows the user`)
|
||||||
|
: ''
|
||||||
}
|
}
|
||||||
size="small"
|
size="small"
|
||||||
variant="solid"
|
variant="solid"
|
||||||
@@ -936,7 +938,7 @@ function ExpandableRichTextView({
|
|||||||
/>
|
/>
|
||||||
{constrained && !screenReaderEnabled && (
|
{constrained && !screenReaderEnabled && (
|
||||||
<Pressable
|
<Pressable
|
||||||
accessibilityHint={_(msg`Tap to expand or collapse post text.`)}
|
accessibilityHint={_(msg`Expands or collapses post text`)}
|
||||||
accessibilityLabel={expanded ? _(msg`Read less`) : _(msg`Read more`)}
|
accessibilityLabel={expanded ? _(msg`Read less`) : _(msg`Read more`)}
|
||||||
hitSlop={HITSLOP_20}
|
hitSlop={HITSLOP_20}
|
||||||
onPress={() => setExpanded(prev => !prev)}
|
onPress={() => setExpanded(prev => !prev)}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import {device, useStorage} from '#/storage'
|
||||||
|
|
||||||
|
export function useDevModeEnabled() {
|
||||||
|
const [devModeEnabled = false, setDevModeEnabled] = useStorage(device, [
|
||||||
|
'devMode',
|
||||||
|
])
|
||||||
|
|
||||||
|
return [devModeEnabled, setDevModeEnabled] as const
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import {AppBskyActorDefs} from '@atproto/api'
|
||||||
|
import {useMutation, useQueryClient} from '@tanstack/react-query'
|
||||||
|
|
||||||
|
import {preferencesQueryKey} from '#/state/queries/preferences'
|
||||||
|
import {useAgent} from '#/state/session'
|
||||||
|
|
||||||
|
export function usePostInteractionSettingsMutation() {
|
||||||
|
const qc = useQueryClient()
|
||||||
|
const agent = useAgent()
|
||||||
|
return useMutation({
|
||||||
|
async mutationFn(props: AppBskyActorDefs.PostInteractionSettingsPref) {
|
||||||
|
await agent.setPostInteractionSettings(props)
|
||||||
|
},
|
||||||
|
async onSuccess() {
|
||||||
|
await qc.invalidateQueries({
|
||||||
|
queryKey: preferencesQueryKey,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -39,4 +39,8 @@ export const DEFAULT_LOGGED_OUT_PREFERENCES: UsePreferencesQueryResponse = {
|
|||||||
activeProgressGuide: undefined,
|
activeProgressGuide: undefined,
|
||||||
nuxs: [],
|
nuxs: [],
|
||||||
},
|
},
|
||||||
|
postInteractionSettings: {
|
||||||
|
threadgateAllowRules: undefined,
|
||||||
|
postgateEmbeddingRules: [],
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
Un$Typed,
|
Un$Typed,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
import {
|
import {
|
||||||
|
keepPreviousData,
|
||||||
QueryClient,
|
QueryClient,
|
||||||
useMutation,
|
useMutation,
|
||||||
useQuery,
|
useQuery,
|
||||||
@@ -84,7 +85,13 @@ export function useProfileQuery({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useProfilesQuery({handles}: {handles: string[]}) {
|
export function useProfilesQuery({
|
||||||
|
handles,
|
||||||
|
maintainData,
|
||||||
|
}: {
|
||||||
|
handles: string[]
|
||||||
|
maintainData?: boolean
|
||||||
|
}) {
|
||||||
const agent = useAgent()
|
const agent = useAgent()
|
||||||
return useQuery({
|
return useQuery({
|
||||||
staleTime: STALE.MINUTES.FIVE,
|
staleTime: STALE.MINUTES.FIVE,
|
||||||
@@ -93,6 +100,7 @@ export function useProfilesQuery({handles}: {handles: string[]}) {
|
|||||||
const res = await agent.getProfiles({actors: handles})
|
const res = await agent.getProfiles({actors: handles})
|
||||||
return res.data
|
return res.data
|
||||||
},
|
},
|
||||||
|
placeholderData: maintainData ? keepPreviousData : undefined,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,3 +4,4 @@ export type ThreadgateAllowUISetting =
|
|||||||
| {type: 'mention'}
|
| {type: 'mention'}
|
||||||
| {type: 'following'}
|
| {type: 'following'}
|
||||||
| {type: 'list'; list: string}
|
| {type: 'list'; list: string}
|
||||||
|
| {type: 'followers'}
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ export function threadgateRecordToAllowUISetting(
|
|||||||
setting = {type: 'following'}
|
setting = {type: 'following'}
|
||||||
} else if (AppBskyFeedThreadgate.isListRule(allow)) {
|
} else if (AppBskyFeedThreadgate.isListRule(allow)) {
|
||||||
setting = {type: 'list', list: allow.list}
|
setting = {type: 'list', list: allow.list}
|
||||||
|
} else if (AppBskyFeedThreadgate.isFollowerRule(allow)) {
|
||||||
|
setting = {type: 'followers'}
|
||||||
}
|
}
|
||||||
return setting
|
return setting
|
||||||
})
|
})
|
||||||
@@ -76,6 +78,8 @@ export function threadgateAllowUISettingToAllowRecordValue(
|
|||||||
allow.push({$type: 'app.bsky.feed.threadgate#mentionRule'})
|
allow.push({$type: 'app.bsky.feed.threadgate#mentionRule'})
|
||||||
} else if (rule.type === 'following') {
|
} else if (rule.type === 'following') {
|
||||||
allow.push({$type: 'app.bsky.feed.threadgate#followingRule'})
|
allow.push({$type: 'app.bsky.feed.threadgate#followingRule'})
|
||||||
|
} else if (rule.type === 'followers') {
|
||||||
|
allow.push({$type: 'app.bsky.feed.threadgate#followerRule'})
|
||||||
} else if (rule.type === 'list') {
|
} else if (rule.type === 'list') {
|
||||||
allow.push({
|
allow.push({
|
||||||
$type: 'app.bsky.feed.threadgate#listRule',
|
$type: 'app.bsky.feed.threadgate#listRule',
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import {useGate} from '#/lib/statsig/statsig'
|
|
||||||
import {useLanguagePrefs} from '#/state/preferences/languages'
|
import {useLanguagePrefs} from '#/state/preferences/languages'
|
||||||
import {useServiceConfigQuery} from '#/state/queries/service-config'
|
import {useServiceConfigQuery} from '#/state/queries/service-config'
|
||||||
import {device} from '#/storage'
|
import {device} from '#/storage'
|
||||||
@@ -14,7 +13,6 @@ const Context = React.createContext<Context>({
|
|||||||
})
|
})
|
||||||
|
|
||||||
export function Provider({children}: React.PropsWithChildren<{}>) {
|
export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||||
const gate = useGate()
|
|
||||||
const langPrefs = useLanguagePrefs()
|
const langPrefs = useLanguagePrefs()
|
||||||
const {data: config, isLoading: isInitialLoad} = useServiceConfigQuery()
|
const {data: config, isLoading: isInitialLoad} = useServiceConfigQuery()
|
||||||
const ctx = React.useMemo<Context>(() => {
|
const ctx = React.useMemo<Context>(() => {
|
||||||
@@ -45,23 +43,12 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||||||
* the server, we can exit early.
|
* the server, we can exit early.
|
||||||
*/
|
*/
|
||||||
const enabled = Boolean(config?.topicsEnabled)
|
const enabled = Boolean(config?.topicsEnabled)
|
||||||
if (!enabled) {
|
|
||||||
// cache for next reload
|
|
||||||
device.set(['trendingBetaEnabled'], enabled)
|
|
||||||
return {enabled: false}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Service is enabled, but also check statsig in case we're rolling back.
|
|
||||||
*/
|
|
||||||
const gateEnabled = gate('trending_topics_beta')
|
|
||||||
const _enabled = enabled && gateEnabled
|
|
||||||
|
|
||||||
// update cache
|
// update cache
|
||||||
device.set(['trendingBetaEnabled'], _enabled)
|
device.set(['trendingBetaEnabled'], enabled)
|
||||||
|
|
||||||
return {enabled: _enabled}
|
return {enabled}
|
||||||
}, [isInitialLoad, config, gate, langPrefs.contentLanguages])
|
}, [isInitialLoad, config, langPrefs.contentLanguages])
|
||||||
return <Context.Provider value={ctx}>{children}</Context.Provider>
|
return <Context.Provider value={ctx}>{children}</Context.Provider>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+69
-3
@@ -1,5 +1,5 @@
|
|||||||
|
import {useCallback, useEffect, useState} from 'react'
|
||||||
import {MMKV} from 'react-native-mmkv'
|
import {MMKV} from 'react-native-mmkv'
|
||||||
import {Did} from '@atproto/api'
|
|
||||||
|
|
||||||
import {Account, Device} from '#/storage/schema'
|
import {Account, Device} from '#/storage/schema'
|
||||||
|
|
||||||
@@ -65,6 +65,72 @@ export class Storage<Scopes extends unknown[], Schema> {
|
|||||||
removeMany<Key extends keyof Schema>(scopes: [...Scopes], keys: Key[]) {
|
removeMany<Key extends keyof Schema>(scopes: [...Scopes], keys: Key[]) {
|
||||||
keys.forEach(key => this.remove([...scopes, key]))
|
keys.forEach(key => this.remove([...scopes, key]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fires a callback when the storage associated with a given key changes
|
||||||
|
*
|
||||||
|
* @returns Listener - call `remove()` to stop listening
|
||||||
|
*/
|
||||||
|
addOnValueChangedListener<Key extends keyof Schema>(
|
||||||
|
scopes: [...Scopes, Key],
|
||||||
|
callback: () => void,
|
||||||
|
) {
|
||||||
|
return this.store.addOnValueChangedListener(key => {
|
||||||
|
if (key === scopes.join(this.sep)) {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type StorageSchema<T extends Storage<any, any>> = T extends Storage<
|
||||||
|
any,
|
||||||
|
infer U
|
||||||
|
>
|
||||||
|
? U
|
||||||
|
: never
|
||||||
|
type StorageScopes<T extends Storage<any, any>> = T extends Storage<
|
||||||
|
infer S,
|
||||||
|
any
|
||||||
|
>
|
||||||
|
? S
|
||||||
|
: never
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook to use a storage instance. Acts like a useState hook, but persists the
|
||||||
|
* value in storage.
|
||||||
|
*/
|
||||||
|
export function useStorage<
|
||||||
|
Store extends Storage<any, any>,
|
||||||
|
Key extends keyof StorageSchema<Store>,
|
||||||
|
>(
|
||||||
|
storage: Store,
|
||||||
|
scopes: [...StorageScopes<Store>, Key],
|
||||||
|
): [
|
||||||
|
StorageSchema<Store>[Key] | undefined,
|
||||||
|
(data: StorageSchema<Store>[Key]) => void,
|
||||||
|
] {
|
||||||
|
type Schema = StorageSchema<Store>
|
||||||
|
const [value, setValue] = useState<Schema[Key] | undefined>(() =>
|
||||||
|
storage.get(scopes),
|
||||||
|
)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const sub = storage.addOnValueChangedListener(scopes, () => {
|
||||||
|
setValue(storage.get(scopes))
|
||||||
|
})
|
||||||
|
return () => sub.remove()
|
||||||
|
}, [storage, scopes])
|
||||||
|
|
||||||
|
const setter = useCallback(
|
||||||
|
(data: Schema[Key]) => {
|
||||||
|
setValue(data)
|
||||||
|
storage.set(scopes, data)
|
||||||
|
},
|
||||||
|
[storage, scopes],
|
||||||
|
)
|
||||||
|
|
||||||
|
return [value, setter] as const
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,10 +143,10 @@ export const device = new Storage<[], Device>({id: 'bsky_device'})
|
|||||||
/**
|
/**
|
||||||
* Account data that's specific to the account on this device
|
* Account data that's specific to the account on this device
|
||||||
*/
|
*/
|
||||||
export const account = new Storage<[Did], Account>({id: 'bsky_account'})
|
export const account = new Storage<[string], Account>({id: 'bsky_account'})
|
||||||
|
|
||||||
if (__DEV__ && typeof window !== 'undefined') {
|
if (__DEV__ && typeof window !== 'undefined') {
|
||||||
// @ts-ignore
|
// @ts-expect-error - dev global
|
||||||
window.bsky_storage = {
|
window.bsky_storage = {
|
||||||
device,
|
device,
|
||||||
account,
|
account,
|
||||||
|
|||||||
@@ -9,8 +9,10 @@ export type Device = {
|
|||||||
countryCode: string | undefined
|
countryCode: string | undefined
|
||||||
}
|
}
|
||||||
trendingBetaEnabled: boolean
|
trendingBetaEnabled: boolean
|
||||||
|
devMode: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Account = {
|
export type Account = {
|
||||||
searchTermHistory?: string[]
|
searchTermHistory?: string[]
|
||||||
|
searchAccountHistory?: string[]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -187,6 +187,7 @@ input:focus {
|
|||||||
animation: rotate 500ms linear infinite;
|
animation: rotate 500ms linear infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* animations for atoms */
|
||||||
@keyframes fadeIn {
|
@keyframes fadeIn {
|
||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
@@ -205,6 +206,38 @@ input:focus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes zoomIn {
|
||||||
|
from {
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideInLeft {
|
||||||
|
from {
|
||||||
|
transform: translateX(-100%);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideOutLeft {
|
||||||
|
from {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: translateX(-100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* animating radix dropdowns requires knowing the data attributes */
|
||||||
|
.dropdown-menu-transform-origin > * {
|
||||||
|
transform-origin: var(--radix-dropdown-menu-content-transform-origin);
|
||||||
|
}
|
||||||
|
|
||||||
.force-no-clicks > *,
|
.force-no-clicks > *,
|
||||||
.force-no-clicks * {
|
.force-no-clicks * {
|
||||||
pointer-events: none !important;
|
pointer-events: none !important;
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ import {
|
|||||||
useLanguagePrefs,
|
useLanguagePrefs,
|
||||||
useLanguagePrefsApi,
|
useLanguagePrefsApi,
|
||||||
} from '#/state/preferences/languages'
|
} from '#/state/preferences/languages'
|
||||||
|
import {usePreferencesQuery} from '#/state/queries/preferences'
|
||||||
import {useProfileQuery} from '#/state/queries/profile'
|
import {useProfileQuery} from '#/state/queries/profile'
|
||||||
import {Gif} from '#/state/queries/tenor'
|
import {Gif} from '#/state/queries/tenor'
|
||||||
import {useAgent, useSession} from '#/state/session'
|
import {useAgent, useSession} from '#/state/session'
|
||||||
@@ -169,6 +170,7 @@ export const ComposePost = ({
|
|||||||
const discardPromptControl = Prompt.usePromptControl()
|
const discardPromptControl = Prompt.usePromptControl()
|
||||||
const {closeAllDialogs} = useDialogStateControlContext()
|
const {closeAllDialogs} = useDialogStateControlContext()
|
||||||
const {closeAllModals} = useModalControls()
|
const {closeAllModals} = useModalControls()
|
||||||
|
const {data: preferences} = usePreferencesQuery()
|
||||||
|
|
||||||
const [isKeyboardVisible] = useIsKeyboardVisible({iosUseWillEvents: true})
|
const [isKeyboardVisible] = useIsKeyboardVisible({iosUseWillEvents: true})
|
||||||
const [isPublishing, setIsPublishing] = useState(false)
|
const [isPublishing, setIsPublishing] = useState(false)
|
||||||
@@ -177,7 +179,13 @@ export const ComposePost = ({
|
|||||||
|
|
||||||
const [composerState, composerDispatch] = useReducer(
|
const [composerState, composerDispatch] = useReducer(
|
||||||
composerReducer,
|
composerReducer,
|
||||||
{initImageUris, initQuoteUri: initQuote?.uri, initText, initMention},
|
{
|
||||||
|
initImageUris,
|
||||||
|
initQuoteUri: initQuote?.uri,
|
||||||
|
initText,
|
||||||
|
initMention,
|
||||||
|
initInteractionSettings: preferences?.postInteractionSettings,
|
||||||
|
},
|
||||||
createComposerState,
|
createComposerState,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1233,7 +1241,7 @@ function ComposerFooter({
|
|||||||
onPress={onEmojiButtonPress}
|
onPress={onEmojiButtonPress}
|
||||||
style={a.p_sm}
|
style={a.p_sm}
|
||||||
label={_(msg`Open emoji picker`)}
|
label={_(msg`Open emoji picker`)}
|
||||||
accessibilityHint={_(msg`Open emoji picker`)}
|
accessibilityHint={_(msg`Opens emoji picker`)}
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
shape="round"
|
shape="round"
|
||||||
color="primary">
|
color="primary">
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ export function ComposerReplyTo({replyTo}: {replyTo: ComposerOptsPostRef}) {
|
|||||||
msg`Expand or collapse the full post you are replying to`,
|
msg`Expand or collapse the full post you are replying to`,
|
||||||
)}
|
)}
|
||||||
accessibilityHint={_(
|
accessibilityHint={_(
|
||||||
msg`Expand or collapse the full post you are replying to`,
|
msg`Expands or collapses the full post you are replying to`,
|
||||||
)}>
|
)}>
|
||||||
<PreviewableUserAvatar
|
<PreviewableUserAvatar
|
||||||
size={50}
|
size={50}
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
import {ImagePickerAsset} from 'expo-image-picker'
|
import {ImagePickerAsset} from 'expo-image-picker'
|
||||||
import {AppBskyFeedPostgate, AppBskyRichtextFacet, RichText} from '@atproto/api'
|
import {
|
||||||
|
AppBskyFeedPostgate,
|
||||||
|
AppBskyRichtextFacet,
|
||||||
|
BskyPreferences,
|
||||||
|
RichText,
|
||||||
|
} from '@atproto/api'
|
||||||
import {nanoid} from 'nanoid/non-secure'
|
import {nanoid} from 'nanoid/non-secure'
|
||||||
|
|
||||||
import {SelfLabel} from '#/lib/moderation'
|
import {SelfLabel} from '#/lib/moderation'
|
||||||
@@ -13,7 +18,7 @@ import {
|
|||||||
import {ComposerImage, createInitialImages} from '#/state/gallery'
|
import {ComposerImage, createInitialImages} from '#/state/gallery'
|
||||||
import {createPostgateRecord} from '#/state/queries/postgate/util'
|
import {createPostgateRecord} from '#/state/queries/postgate/util'
|
||||||
import {Gif} from '#/state/queries/tenor'
|
import {Gif} from '#/state/queries/tenor'
|
||||||
import {threadgateViewToAllowUISetting} from '#/state/queries/threadgate'
|
import {threadgateRecordToAllowUISetting} from '#/state/queries/threadgate'
|
||||||
import {ThreadgateAllowUISetting} from '#/state/queries/threadgate'
|
import {ThreadgateAllowUISetting} from '#/state/queries/threadgate'
|
||||||
import {ComposerOpts} from '#/state/shell/composer'
|
import {ComposerOpts} from '#/state/shell/composer'
|
||||||
import {
|
import {
|
||||||
@@ -477,11 +482,15 @@ export function createComposerState({
|
|||||||
initMention,
|
initMention,
|
||||||
initImageUris,
|
initImageUris,
|
||||||
initQuoteUri,
|
initQuoteUri,
|
||||||
|
initInteractionSettings,
|
||||||
}: {
|
}: {
|
||||||
initText: string | undefined
|
initText: string | undefined
|
||||||
initMention: string | undefined
|
initMention: string | undefined
|
||||||
initImageUris: ComposerOpts['imageUris']
|
initImageUris: ComposerOpts['imageUris']
|
||||||
initQuoteUri: string | undefined
|
initQuoteUri: string | undefined
|
||||||
|
initInteractionSettings:
|
||||||
|
| BskyPreferences['postInteractionSettings']
|
||||||
|
| undefined
|
||||||
}): ComposerState {
|
}): ComposerState {
|
||||||
let media: ImagesMedia | undefined
|
let media: ImagesMedia | undefined
|
||||||
if (initImageUris?.length) {
|
if (initImageUris?.length) {
|
||||||
@@ -591,8 +600,16 @@ export function createComposerState({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
postgate: createPostgateRecord({post: ''}),
|
postgate: createPostgateRecord({
|
||||||
threadgate: threadgateViewToAllowUISetting(undefined),
|
post: '',
|
||||||
|
embeddingRules: initInteractionSettings?.postgateEmbeddingRules || [],
|
||||||
|
}),
|
||||||
|
threadgate: threadgateRecordToAllowUISetting({
|
||||||
|
$type: 'app.bsky.feed.threadgate',
|
||||||
|
post: '',
|
||||||
|
createdAt: new Date().toString(),
|
||||||
|
allow: initInteractionSettings?.threadgateAllowRules,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ export function EmojiPicker({state, close, pinToTop}: IProps) {
|
|||||||
<Pressable
|
<Pressable
|
||||||
accessible
|
accessible
|
||||||
accessibilityLabel={_(msg`Close emoji picker`)}
|
accessibilityLabel={_(msg`Close emoji picker`)}
|
||||||
accessibilityHint={_(msg`Tap to close the emoji picker`)}
|
accessibilityHint={_(msg`Closes the emoji picker`)}
|
||||||
onPress={close}
|
onPress={close}
|
||||||
style={[a.fixed, a.inset_0]}
|
style={[a.fixed, a.inset_0]}
|
||||||
/>
|
/>
|
||||||
@@ -171,7 +171,7 @@ export function EmojiPicker({state, close, pinToTop}: IProps) {
|
|||||||
<Pressable
|
<Pressable
|
||||||
accessible
|
accessible
|
||||||
accessibilityLabel={_(msg`Close emoji picker`)}
|
accessibilityLabel={_(msg`Close emoji picker`)}
|
||||||
accessibilityHint={_(msg`Tap to close the emoji picker`)}
|
accessibilityHint={_(msg`Closes the emoji picker`)}
|
||||||
onPress={close}
|
onPress={close}
|
||||||
style={[a.fixed, a.inset_0]}
|
style={[a.fixed, a.inset_0]}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ export function ModalsContainer() {
|
|||||||
}
|
}
|
||||||
handleIndicatorStyle={{backgroundColor: pal.text.color}}
|
handleIndicatorStyle={{backgroundColor: pal.text.color}}
|
||||||
handleStyle={[styles.handle, pal.view]}
|
handleStyle={[styles.handle, pal.view]}
|
||||||
|
backgroundStyle={pal.view}
|
||||||
onChange={onBottomSheetChange}>
|
onChange={onBottomSheetChange}>
|
||||||
{element}
|
{element}
|
||||||
</BottomSheet>
|
</BottomSheet>
|
||||||
|
|||||||
@@ -242,6 +242,11 @@ let PostThreadItemLoaded = ({
|
|||||||
return makeProfileLink(post.author, 'post', urip.rkey, 'quotes')
|
return makeProfileLink(post.author, 'post', urip.rkey, 'quotes')
|
||||||
}, [post.uri, post.author])
|
}, [post.uri, post.author])
|
||||||
const quotesTitle = _(msg`Quotes of this post`)
|
const quotesTitle = _(msg`Quotes of this post`)
|
||||||
|
const onlyFollowersCanReply = !!threadgateRecord?.allow?.find(
|
||||||
|
rule => rule.$type === 'app.bsky.feed.threadgate#followerRule',
|
||||||
|
)
|
||||||
|
const showFollowButton =
|
||||||
|
currentAccount?.did !== post.author.did && !onlyFollowersCanReply
|
||||||
|
|
||||||
const translatorUrl = getTranslatorLink(
|
const translatorUrl = getTranslatorLink(
|
||||||
record?.text || '',
|
record?.text || '',
|
||||||
@@ -344,7 +349,7 @@ let PostThreadItemLoaded = ({
|
|||||||
</Text>
|
</Text>
|
||||||
</Link>
|
</Link>
|
||||||
</View>
|
</View>
|
||||||
{currentAccount?.did !== post.author.did && (
|
{showFollowButton && (
|
||||||
<View>
|
<View>
|
||||||
<PostThreadFollowBtn did={post.author.did} />
|
<PostThreadFollowBtn did={post.author.did} />
|
||||||
</View>
|
</View>
|
||||||
@@ -806,7 +811,7 @@ function BackdatedPostIndicator({post}: {post: AppBskyFeedDefs.PostView}) {
|
|||||||
<Button
|
<Button
|
||||||
label={_(msg`Archived post`)}
|
label={_(msg`Archived post`)}
|
||||||
accessibilityHint={_(
|
accessibilityHint={_(
|
||||||
msg`Show information about when this post was created`,
|
msg`Shows information about when this post was created`,
|
||||||
)}
|
)}
|
||||||
onPress={e => {
|
onPress={e => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
|||||||
@@ -6,11 +6,12 @@ import {useQueryClient} from '@tanstack/react-query'
|
|||||||
|
|
||||||
import {HITSLOP_20} from '#/lib/constants'
|
import {HITSLOP_20} from '#/lib/constants'
|
||||||
import {makeProfileLink} from '#/lib/routes/links'
|
import {makeProfileLink} from '#/lib/routes/links'
|
||||||
import {shareUrl} from '#/lib/sharing'
|
import {shareText, shareUrl} from '#/lib/sharing'
|
||||||
import {toShareUrl} from '#/lib/strings/url-helpers'
|
import {toShareUrl} from '#/lib/strings/url-helpers'
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {Shadow} from '#/state/cache/types'
|
import {Shadow} from '#/state/cache/types'
|
||||||
import {useModalControls} from '#/state/modals'
|
import {useModalControls} from '#/state/modals'
|
||||||
|
import {useDevModeEnabled} from '#/state/preferences/dev-mode'
|
||||||
import {
|
import {
|
||||||
RQKEY as profileQueryKey,
|
RQKEY as profileQueryKey,
|
||||||
useProfileBlockMutationQueue,
|
useProfileBlockMutationQueue,
|
||||||
@@ -52,6 +53,7 @@ let ProfileMenu = ({
|
|||||||
const isBlocked = profile.viewer?.blocking || profile.viewer?.blockedBy
|
const isBlocked = profile.viewer?.blocking || profile.viewer?.blockedBy
|
||||||
const isFollowingBlockedAccount = isFollowing && isBlocked
|
const isFollowingBlockedAccount = isFollowing && isBlocked
|
||||||
const isLabelerAndNotBlocked = !!profile.associated?.labeler && !isBlocked
|
const isLabelerAndNotBlocked = !!profile.associated?.labeler && !isBlocked
|
||||||
|
const [devModeEnabled] = useDevModeEnabled()
|
||||||
|
|
||||||
const [queueMute, queueUnmute] = useProfileMuteMutationQueue(profile)
|
const [queueMute, queueUnmute] = useProfileMuteMutationQueue(profile)
|
||||||
const [queueBlock, queueUnblock] = useProfileBlockMutationQueue(profile)
|
const [queueBlock, queueUnblock] = useProfileBlockMutationQueue(profile)
|
||||||
@@ -167,6 +169,14 @@ let ProfileMenu = ({
|
|||||||
reportDialogControl.open()
|
reportDialogControl.open()
|
||||||
}, [reportDialogControl])
|
}, [reportDialogControl])
|
||||||
|
|
||||||
|
const onPressShareATUri = React.useCallback(() => {
|
||||||
|
shareText(`at://${profile.did}`)
|
||||||
|
}, [profile.did])
|
||||||
|
|
||||||
|
const onPressShareDID = React.useCallback(() => {
|
||||||
|
shareText(profile.did)
|
||||||
|
}, [profile.did])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EventStopper onKeyDown={false}>
|
<EventStopper onKeyDown={false}>
|
||||||
<Menu.Root>
|
<Menu.Root>
|
||||||
@@ -308,6 +318,31 @@ let ProfileMenu = ({
|
|||||||
</Menu.Group>
|
</Menu.Group>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
{devModeEnabled ? (
|
||||||
|
<>
|
||||||
|
<Menu.Divider />
|
||||||
|
<Menu.Group>
|
||||||
|
<Menu.Item
|
||||||
|
testID="profileHeaderDropdownShareATURIBtn"
|
||||||
|
label={_(msg`Copy at:// URI`)}
|
||||||
|
onPress={onPressShareATUri}>
|
||||||
|
<Menu.ItemText>
|
||||||
|
<Trans>Copy at:// URI</Trans>
|
||||||
|
</Menu.ItemText>
|
||||||
|
<Menu.ItemIcon icon={Share} />
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Item
|
||||||
|
testID="profileHeaderDropdownShareDIDBtn"
|
||||||
|
label={_(msg`Copy DID`)}
|
||||||
|
onPress={onPressShareDID}>
|
||||||
|
<Menu.ItemText>
|
||||||
|
<Trans>Copy DID</Trans>
|
||||||
|
</Menu.ItemText>
|
||||||
|
<Menu.ItemIcon icon={Share} />
|
||||||
|
</Menu.Item>
|
||||||
|
</Menu.Group>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
</Menu.Outer>
|
</Menu.Outer>
|
||||||
</Menu.Root>
|
</Menu.Root>
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {useLingui} from '@lingui/react'
|
|||||||
|
|
||||||
import {usePalette} from '#/lib/hooks/usePalette'
|
import {usePalette} from '#/lib/hooks/usePalette'
|
||||||
import {useTheme} from '#/lib/ThemeContext'
|
import {useTheme} from '#/lib/ThemeContext'
|
||||||
|
import * as Layout from '#/components/Layout'
|
||||||
import {Text} from '../text/Text'
|
import {Text} from '../text/Text'
|
||||||
|
|
||||||
export function ErrorMessage({
|
export function ErrorMessage({
|
||||||
@@ -31,39 +32,44 @@ export function ErrorMessage({
|
|||||||
const pal = usePalette('error')
|
const pal = usePalette('error')
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
return (
|
return (
|
||||||
<View testID="errorMessageView" style={[styles.outer, pal.view, style]}>
|
<Layout.Center>
|
||||||
<View
|
<View testID="errorMessageView" style={[styles.outer, pal.view, style]}>
|
||||||
style={[styles.errorIcon, {backgroundColor: theme.palette.error.icon}]}>
|
<View
|
||||||
<FontAwesomeIcon
|
style={[
|
||||||
icon="exclamation"
|
styles.errorIcon,
|
||||||
style={pal.text as FontAwesomeIconStyle}
|
{backgroundColor: theme.palette.error.icon},
|
||||||
size={16}
|
]}>
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
<Text
|
|
||||||
type="sm-medium"
|
|
||||||
style={[styles.message, pal.text]}
|
|
||||||
numberOfLines={numberOfLines}>
|
|
||||||
{message}
|
|
||||||
</Text>
|
|
||||||
{onPressTryAgain && (
|
|
||||||
<TouchableOpacity
|
|
||||||
testID="errorMessageTryAgainButton"
|
|
||||||
style={styles.btn}
|
|
||||||
onPress={onPressTryAgain}
|
|
||||||
accessibilityRole="button"
|
|
||||||
accessibilityLabel={_(msg`Retry`)}
|
|
||||||
accessibilityHint={_(
|
|
||||||
msg`Retries the last action, which errored out`,
|
|
||||||
)}>
|
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
icon="arrows-rotate"
|
icon="exclamation"
|
||||||
style={{color: theme.palette.error.icon}}
|
style={pal.text as FontAwesomeIconStyle}
|
||||||
size={18}
|
size={16}
|
||||||
/>
|
/>
|
||||||
</TouchableOpacity>
|
</View>
|
||||||
)}
|
<Text
|
||||||
</View>
|
type="sm-medium"
|
||||||
|
style={[styles.message, pal.text]}
|
||||||
|
numberOfLines={numberOfLines}>
|
||||||
|
{message}
|
||||||
|
</Text>
|
||||||
|
{onPressTryAgain && (
|
||||||
|
<TouchableOpacity
|
||||||
|
testID="errorMessageTryAgainButton"
|
||||||
|
style={styles.btn}
|
||||||
|
onPress={onPressTryAgain}
|
||||||
|
accessibilityRole="button"
|
||||||
|
accessibilityLabel={_(msg`Retry`)}
|
||||||
|
accessibilityHint={_(
|
||||||
|
msg`Retries the last action, which errored out`,
|
||||||
|
)}>
|
||||||
|
<FontAwesomeIcon
|
||||||
|
icon="arrows-rotate"
|
||||||
|
style={{color: theme.palette.error.icon}}
|
||||||
|
size={18}
|
||||||
|
/>
|
||||||
|
</TouchableOpacity>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</Layout.Center>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -293,7 +293,9 @@ const DropdownItems = ({
|
|||||||
onPress={() => onPressItem(index)}
|
onPress={() => onPressItem(index)}
|
||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
accessibilityLabel={item.label}
|
accessibilityLabel={item.label}
|
||||||
accessibilityHint={_(msg`Option ${index + 1} of ${numItems}`)}>
|
accessibilityHint={_(
|
||||||
|
msg`Selects option ${index + 1} of ${numItems}`,
|
||||||
|
)}>
|
||||||
{item.icon && (
|
{item.icon && (
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
style={styles.icon}
|
style={styles.icon}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import {useOpenLink} from '#/lib/hooks/useOpenLink'
|
|||||||
import {getCurrentRoute} from '#/lib/routes/helpers'
|
import {getCurrentRoute} from '#/lib/routes/helpers'
|
||||||
import {makeProfileLink} from '#/lib/routes/links'
|
import {makeProfileLink} from '#/lib/routes/links'
|
||||||
import {CommonNavigatorParams, NavigationProp} from '#/lib/routes/types'
|
import {CommonNavigatorParams, NavigationProp} from '#/lib/routes/types'
|
||||||
import {shareUrl} from '#/lib/sharing'
|
import {shareText, shareUrl} from '#/lib/sharing'
|
||||||
import {logEvent} from '#/lib/statsig/statsig'
|
import {logEvent} from '#/lib/statsig/statsig'
|
||||||
import {richTextToString} from '#/lib/strings/rich-text-helpers'
|
import {richTextToString} from '#/lib/strings/rich-text-helpers'
|
||||||
import {toShareUrl} from '#/lib/strings/url-helpers'
|
import {toShareUrl} from '#/lib/strings/url-helpers'
|
||||||
@@ -33,6 +33,7 @@ import {useProfileShadow} from '#/state/cache/profile-shadow'
|
|||||||
import {useFeedFeedbackContext} from '#/state/feed-feedback'
|
import {useFeedFeedbackContext} from '#/state/feed-feedback'
|
||||||
import {useLanguagePrefs} from '#/state/preferences'
|
import {useLanguagePrefs} from '#/state/preferences'
|
||||||
import {useHiddenPosts, useHiddenPostsApi} from '#/state/preferences'
|
import {useHiddenPosts, useHiddenPostsApi} from '#/state/preferences'
|
||||||
|
import {useDevModeEnabled} from '#/state/preferences/dev-mode'
|
||||||
import {usePinnedPostMutation} from '#/state/queries/pinned-post'
|
import {usePinnedPostMutation} from '#/state/queries/pinned-post'
|
||||||
import {
|
import {
|
||||||
usePostDeleteMutation,
|
usePostDeleteMutation,
|
||||||
@@ -122,6 +123,7 @@ let PostDropdownMenuItems = ({
|
|||||||
const hideReplyConfirmControl = useDialogControl()
|
const hideReplyConfirmControl = useDialogControl()
|
||||||
const {mutateAsync: toggleReplyVisibility} =
|
const {mutateAsync: toggleReplyVisibility} =
|
||||||
useToggleReplyVisibilityMutation()
|
useToggleReplyVisibilityMutation()
|
||||||
|
const [devModeEnabled] = useDevModeEnabled()
|
||||||
|
|
||||||
const postUri = post.uri
|
const postUri = post.uri
|
||||||
const postCid = post.cid
|
const postCid = post.cid
|
||||||
@@ -366,6 +368,14 @@ let PostDropdownMenuItems = ({
|
|||||||
}
|
}
|
||||||
}, [_, queueBlock])
|
}, [_, queueBlock])
|
||||||
|
|
||||||
|
const onShareATURI = useCallback(() => {
|
||||||
|
shareText(postUri)
|
||||||
|
}, [postUri])
|
||||||
|
|
||||||
|
const onShareAuthorDID = useCallback(() => {
|
||||||
|
shareText(postAuthor.did)
|
||||||
|
}, [postAuthor.did])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Menu.Outer>
|
<Menu.Outer>
|
||||||
@@ -647,6 +657,28 @@ let PostDropdownMenuItems = ({
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Menu.Group>
|
</Menu.Group>
|
||||||
|
|
||||||
|
{devModeEnabled ? (
|
||||||
|
<>
|
||||||
|
<Menu.Divider />
|
||||||
|
<Menu.Group>
|
||||||
|
<Menu.Item
|
||||||
|
testID="postAtUriShareBtn"
|
||||||
|
label={_(msg`Copy post at:// URI`)}
|
||||||
|
onPress={onShareATURI}>
|
||||||
|
<Menu.ItemText>{_(msg`Copy post at:// URI`)}</Menu.ItemText>
|
||||||
|
<Menu.ItemIcon icon={Share} position="right" />
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Item
|
||||||
|
testID="postAuthorDIDShareBtn"
|
||||||
|
label={_(msg`Copy author DID`)}
|
||||||
|
onPress={onShareAuthorDID}>
|
||||||
|
<Menu.ItemText>{_(msg`Copy author DID`)}</Menu.ItemText>
|
||||||
|
<Menu.ItemIcon icon={Share} position="right" />
|
||||||
|
</Menu.Item>
|
||||||
|
</Menu.Group>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Menu.Outer>
|
</Menu.Outer>
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ export function AutoSizedImage({
|
|||||||
onPressIn={onPressIn}
|
onPressIn={onPressIn}
|
||||||
// alt here is what screen readers actually use
|
// alt here is what screen readers actually use
|
||||||
accessibilityLabel={image.alt}
|
accessibilityLabel={image.alt}
|
||||||
accessibilityHint={_(msg`Tap to view full image`)}
|
accessibilityHint={_(msg`Views full image`)}
|
||||||
style={[
|
style={[
|
||||||
a.w_full,
|
a.w_full,
|
||||||
a.rounded_md,
|
a.rounded_md,
|
||||||
@@ -218,7 +218,7 @@ export function AutoSizedImage({
|
|||||||
onPressIn={onPressIn}
|
onPressIn={onPressIn}
|
||||||
// alt here is what screen readers actually use
|
// alt here is what screen readers actually use
|
||||||
accessibilityLabel={image.alt}
|
accessibilityLabel={image.alt}
|
||||||
accessibilityHint={_(msg`Tap to view full image`)}
|
accessibilityHint={_(msg`Views full image`)}
|
||||||
style={[a.h_full]}>
|
style={[a.h_full]}>
|
||||||
{contents}
|
{contents}
|
||||||
</Pressable>
|
</Pressable>
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import {makeProfileLink} from '#/lib/routes/links'
|
|||||||
import {shareUrl} from '#/lib/sharing'
|
import {shareUrl} from '#/lib/sharing'
|
||||||
import {useGate} from '#/lib/statsig/statsig'
|
import {useGate} from '#/lib/statsig/statsig'
|
||||||
import {toShareUrl} from '#/lib/strings/url-helpers'
|
import {toShareUrl} from '#/lib/strings/url-helpers'
|
||||||
|
import {useProfileShadow} from '#/state/cache/profile-shadow'
|
||||||
import {Shadow} from '#/state/cache/types'
|
import {Shadow} from '#/state/cache/types'
|
||||||
import {useFeedFeedbackContext} from '#/state/feed-feedback'
|
import {useFeedFeedbackContext} from '#/state/feed-feedback'
|
||||||
import {
|
import {
|
||||||
@@ -94,6 +95,15 @@ let PostCtrls = ({
|
|||||||
post.author.viewer?.blockingByList,
|
post.author.viewer?.blockingByList,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const shadowedAuthor = useProfileShadow(post.author)
|
||||||
|
const followersCanReply = !!threadgateRecord?.allow?.find(
|
||||||
|
rule => rule.$type === 'app.bsky.feed.threadgate#followerRule',
|
||||||
|
)
|
||||||
|
const canOverrideReplyDisabled =
|
||||||
|
followersCanReply &&
|
||||||
|
shadowedAuthor.viewer?.following?.startsWith('at://did')
|
||||||
|
const replyDisabled = post.viewer?.replyDisabled && !canOverrideReplyDisabled
|
||||||
|
|
||||||
const shouldShowLoggedOutWarning = React.useMemo(() => {
|
const shouldShowLoggedOutWarning = React.useMemo(() => {
|
||||||
return (
|
return (
|
||||||
post.author.did !== currentAccount?.did &&
|
post.author.did !== currentAccount?.did &&
|
||||||
@@ -247,13 +257,13 @@ let PostCtrls = ({
|
|||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
big ? a.align_center : [a.flex_1, a.align_start, {marginLeft: -6}],
|
big ? a.align_center : [a.flex_1, a.align_start, {marginLeft: -6}],
|
||||||
post.viewer?.replyDisabled ? {opacity: 0.5} : undefined,
|
replyDisabled ? {opacity: 0.5} : undefined,
|
||||||
]}>
|
]}>
|
||||||
<Pressable
|
<Pressable
|
||||||
testID="replyBtn"
|
testID="replyBtn"
|
||||||
style={btnStyle}
|
style={btnStyle}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
if (!post.viewer?.replyDisabled) {
|
if (!replyDisabled) {
|
||||||
playHaptic('Light')
|
playHaptic('Light')
|
||||||
requireAuth(() => onPressReply())
|
requireAuth(() => onPressReply())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ function PlaceholderOverlay({
|
|||||||
<Pressable
|
<Pressable
|
||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
accessibilityLabel={_(msg`Play Video`)}
|
accessibilityLabel={_(msg`Play Video`)}
|
||||||
accessibilityHint={_(msg`Play Video`)}
|
accessibilityHint={_(msg`Plays the video`)}
|
||||||
onPress={onPress}
|
onPress={onPress}
|
||||||
style={[styles.overlayContainer]}>
|
style={[styles.overlayContainer]}>
|
||||||
{!isPlayerActive ? (
|
{!isPlayerActive ? (
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ function PlaybackControls({
|
|||||||
return (
|
return (
|
||||||
<Pressable
|
<Pressable
|
||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
accessibilityHint={_(msg`Play or pause the GIF`)}
|
accessibilityHint={_(msg`Plays or pauses the GIF`)}
|
||||||
accessibilityLabel={isPlaying ? _(msg`Pause`) : _(msg`Play`)}
|
accessibilityLabel={isPlaying ? _(msg`Pause`) : _(msg`Play`)}
|
||||||
style={[
|
style={[
|
||||||
a.absolute,
|
a.absolute,
|
||||||
|
|||||||
@@ -132,13 +132,13 @@ function VideoControls({
|
|||||||
onPress={enterFullscreen}
|
onPress={enterFullscreen}
|
||||||
style={a.flex_1}
|
style={a.flex_1}
|
||||||
accessibilityLabel={_(msg`Video`)}
|
accessibilityLabel={_(msg`Video`)}
|
||||||
accessibilityHint={_(msg`Tap to enter full screen`)}
|
accessibilityHint={_(msg`Enters full screen`)}
|
||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
/>
|
/>
|
||||||
<ControlButton
|
<ControlButton
|
||||||
onPress={togglePlayback}
|
onPress={togglePlayback}
|
||||||
label={isPlaying ? _(msg`Pause`) : _(msg`Play`)}
|
label={isPlaying ? _(msg`Pause`) : _(msg`Play`)}
|
||||||
accessibilityHint={_(msg`Tap to play or pause`)}
|
accessibilityHint={_(msg`Plays or pauses the video`)}
|
||||||
style={{left: 6}}>
|
style={{left: 6}}>
|
||||||
{isPlaying ? (
|
{isPlaying ? (
|
||||||
<PauseIcon width={13} fill={t.palette.white} />
|
<PauseIcon width={13} fill={t.palette.white} />
|
||||||
@@ -155,7 +155,7 @@ function VideoControls({
|
|||||||
? _(msg({message: `Unmute`, context: 'video'}))
|
? _(msg({message: `Unmute`, context: 'video'}))
|
||||||
: _(msg({message: `Mute`, context: 'video'}))
|
: _(msg({message: `Mute`, context: 'video'}))
|
||||||
}
|
}
|
||||||
accessibilityHint={_(msg`Tap to toggle sound`)}
|
accessibilityHint={_(msg`Toggles the sound`)}
|
||||||
style={{right: 6}}>
|
style={{right: 6}}>
|
||||||
{muted ? (
|
{muted ? (
|
||||||
<MuteIcon width={13} fill={t.palette.white} />
|
<MuteIcon width={13} fill={t.palette.white} />
|
||||||
|
|||||||
@@ -1007,7 +1007,7 @@ function ErrorScreen({error}: {error: string}) {
|
|||||||
<Button
|
<Button
|
||||||
type="default"
|
type="default"
|
||||||
accessibilityLabel={_(msg`Go back`)}
|
accessibilityLabel={_(msg`Go back`)}
|
||||||
accessibilityHint={_(msg`Return to previous page`)}
|
accessibilityHint={_(msg`Returns to previous page`)}
|
||||||
onPress={onPressBack}
|
onPress={onPressBack}
|
||||||
style={{flexShrink: 1}}>
|
style={{flexShrink: 1}}>
|
||||||
<Text type="button" style={pal.text}>
|
<Text type="button" style={pal.text}>
|
||||||
|
|||||||
+237
-285
@@ -1,4 +1,4 @@
|
|||||||
import React from 'react'
|
import React, {useCallback, useLayoutEffect, useMemo} from 'react'
|
||||||
import {
|
import {
|
||||||
ActivityIndicator,
|
ActivityIndicator,
|
||||||
Image,
|
Image,
|
||||||
@@ -10,7 +10,6 @@ import {
|
|||||||
View,
|
View,
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import {ScrollView as RNGHScrollView} from 'react-native-gesture-handler'
|
import {ScrollView as RNGHScrollView} from 'react-native-gesture-handler'
|
||||||
import RNPickerSelect from 'react-native-picker-select'
|
|
||||||
import {AppBskyActorDefs, AppBskyFeedDefs, moderateProfile} from '@atproto/api'
|
import {AppBskyActorDefs, AppBskyFeedDefs, moderateProfile} from '@atproto/api'
|
||||||
import {
|
import {
|
||||||
FontAwesomeIcon,
|
FontAwesomeIcon,
|
||||||
@@ -18,11 +17,10 @@ import {
|
|||||||
} from '@fortawesome/react-native-fontawesome'
|
} from '@fortawesome/react-native-fontawesome'
|
||||||
import {msg, Trans} from '@lingui/macro'
|
import {msg, Trans} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import AsyncStorage from '@react-native-async-storage/async-storage'
|
|
||||||
import {useFocusEffect, useNavigation} from '@react-navigation/native'
|
import {useFocusEffect, useNavigation} from '@react-navigation/native'
|
||||||
|
|
||||||
import {APP_LANGUAGES, LANGUAGES} from '#/lib/../locale/languages'
|
import {APP_LANGUAGES, LANGUAGES} from '#/lib/../locale/languages'
|
||||||
import {createHitslop} from '#/lib/constants'
|
import {createHitslop, HITSLOP_20} from '#/lib/constants'
|
||||||
import {HITSLOP_10} from '#/lib/constants'
|
import {HITSLOP_10} from '#/lib/constants'
|
||||||
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
||||||
import {usePalette} from '#/lib/hooks/usePalette'
|
import {usePalette} from '#/lib/hooks/usePalette'
|
||||||
@@ -37,7 +35,6 @@ import {
|
|||||||
import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
import {sanitizeDisplayName} from '#/lib/strings/display-names'
|
||||||
import {augmentSearchQuery} from '#/lib/strings/helpers'
|
import {augmentSearchQuery} from '#/lib/strings/helpers'
|
||||||
import {languageName} from '#/locale/helpers'
|
import {languageName} from '#/locale/helpers'
|
||||||
import {logger} from '#/logger'
|
|
||||||
import {isNative, isWeb} from '#/platform/detection'
|
import {isNative, isWeb} from '#/platform/detection'
|
||||||
import {listenSoftReset} from '#/state/events'
|
import {listenSoftReset} from '#/state/events'
|
||||||
import {useLanguagePrefs} from '#/state/preferences/languages'
|
import {useLanguagePrefs} from '#/state/preferences/languages'
|
||||||
@@ -45,9 +42,9 @@ import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
|||||||
import {useActorAutocompleteQuery} from '#/state/queries/actor-autocomplete'
|
import {useActorAutocompleteQuery} from '#/state/queries/actor-autocomplete'
|
||||||
import {useActorSearch} from '#/state/queries/actor-search'
|
import {useActorSearch} from '#/state/queries/actor-search'
|
||||||
import {usePopularFeedsSearch} from '#/state/queries/feed'
|
import {usePopularFeedsSearch} from '#/state/queries/feed'
|
||||||
|
import {useProfilesQuery} from '#/state/queries/profile'
|
||||||
import {useSearchPostsQuery} from '#/state/queries/search-posts'
|
import {useSearchPostsQuery} from '#/state/queries/search-posts'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
import {useSetDrawerOpen} from '#/state/shell'
|
|
||||||
import {useSetMinimalShellMode} from '#/state/shell'
|
import {useSetMinimalShellMode} from '#/state/shell'
|
||||||
import {Pager} from '#/view/com/pager/Pager'
|
import {Pager} from '#/view/com/pager/Pager'
|
||||||
import {TabBar} from '#/view/com/pager/TabBar'
|
import {TabBar} from '#/view/com/pager/TabBar'
|
||||||
@@ -61,17 +58,24 @@ import {SearchLinkCard, SearchProfileCard} from '#/view/shell/desktop/Search'
|
|||||||
import {makeSearchQuery, parseSearchQuery} from '#/screens/Search/utils'
|
import {makeSearchQuery, parseSearchQuery} from '#/screens/Search/utils'
|
||||||
import {
|
import {
|
||||||
atoms as a,
|
atoms as a,
|
||||||
|
native,
|
||||||
|
platform,
|
||||||
tokens,
|
tokens,
|
||||||
useBreakpoints,
|
useBreakpoints,
|
||||||
useTheme as useThemeNew,
|
useTheme,
|
||||||
web,
|
web,
|
||||||
} from '#/alf'
|
} from '#/alf'
|
||||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||||
import * as FeedCard from '#/components/FeedCard'
|
import * as FeedCard from '#/components/FeedCard'
|
||||||
import {SearchInput} from '#/components/forms/SearchInput'
|
import {SearchInput} from '#/components/forms/SearchInput'
|
||||||
import {ChevronBottom_Stroke2_Corner0_Rounded as ChevronDown} from '#/components/icons/Chevron'
|
import {
|
||||||
import {Menu_Stroke2_Corner0_Rounded as Menu} from '#/components/icons/Menu'
|
ChevronBottom_Stroke2_Corner0_Rounded as ChevronDownIcon,
|
||||||
|
ChevronTopBottom_Stroke2_Corner0_Rounded as ChevronUpDownIcon,
|
||||||
|
} from '#/components/icons/Chevron'
|
||||||
|
import {Earth_Stroke2_Corner0_Rounded as EarthIcon} from '#/components/icons/Globe'
|
||||||
import * as Layout from '#/components/Layout'
|
import * as Layout from '#/components/Layout'
|
||||||
|
import * as Menu from '#/components/Menu'
|
||||||
|
import {account, useStorage} from '#/storage'
|
||||||
|
|
||||||
function Loader() {
|
function Loader() {
|
||||||
return (
|
return (
|
||||||
@@ -278,7 +282,7 @@ let SearchScreenFeedsResults = ({
|
|||||||
query: string
|
query: string
|
||||||
active: boolean
|
active: boolean
|
||||||
}): React.ReactNode => {
|
}): React.ReactNode => {
|
||||||
const t = useThemeNew()
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
|
||||||
const {data: results, isFetched} = usePopularFeedsSearch({
|
const {data: results, isFetched} = usePopularFeedsSearch({
|
||||||
@@ -323,103 +327,95 @@ function SearchLanguageDropdown({
|
|||||||
value: string
|
value: string
|
||||||
onChange(value: string): void
|
onChange(value: string): void
|
||||||
}) {
|
}) {
|
||||||
const t = useThemeNew()
|
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const {appLanguage, contentLanguages} = useLanguagePrefs()
|
const {appLanguage, contentLanguages} = useLanguagePrefs()
|
||||||
|
|
||||||
const items = React.useMemo(() => {
|
const languages = useMemo(() => {
|
||||||
return [
|
return LANGUAGES.filter(
|
||||||
{
|
(lang, index, self) =>
|
||||||
label: _(msg`Any language`),
|
Boolean(lang.code2) && // reduce to the code2 varieties
|
||||||
inputLabel: _(msg`Any language`),
|
index === self.findIndex(t => t.code2 === lang.code2), // remove dupes (which will happen)
|
||||||
value: '',
|
|
||||||
key: '*',
|
|
||||||
},
|
|
||||||
].concat(
|
|
||||||
LANGUAGES.filter(
|
|
||||||
(lang, index, self) =>
|
|
||||||
Boolean(lang.code2) && // reduce to the code2 varieties
|
|
||||||
index === self.findIndex(t => t.code2 === lang.code2), // remove dupes (which will happen)
|
|
||||||
)
|
|
||||||
.map(l => ({
|
|
||||||
label: languageName(l, appLanguage),
|
|
||||||
inputLabel: languageName(l, appLanguage),
|
|
||||||
value: l.code2,
|
|
||||||
key: l.code2 + l.code3,
|
|
||||||
}))
|
|
||||||
.sort((a, b) => {
|
|
||||||
// prioritize user's languages
|
|
||||||
const aIsUser = contentLanguages.includes(a.value)
|
|
||||||
const bIsUser = contentLanguages.includes(b.value)
|
|
||||||
if (aIsUser && !bIsUser) return -1
|
|
||||||
if (bIsUser && !aIsUser) return 1
|
|
||||||
// prioritize "common" langs in the network
|
|
||||||
const aIsCommon = !!APP_LANGUAGES.find(al => al.code2 === a.value)
|
|
||||||
const bIsCommon = !!APP_LANGUAGES.find(al => al.code2 === b.value)
|
|
||||||
if (aIsCommon && !bIsCommon) return -1
|
|
||||||
if (bIsCommon && !aIsCommon) return 1
|
|
||||||
// fall back to alphabetical
|
|
||||||
return a.label.localeCompare(b.label)
|
|
||||||
}),
|
|
||||||
)
|
)
|
||||||
}, [_, appLanguage, contentLanguages])
|
.map(l => ({
|
||||||
|
label: languageName(l, appLanguage),
|
||||||
|
value: l.code2,
|
||||||
|
key: l.code2 + l.code3,
|
||||||
|
}))
|
||||||
|
.sort((a, b) => {
|
||||||
|
// prioritize user's languages
|
||||||
|
const aIsUser = contentLanguages.includes(a.value)
|
||||||
|
const bIsUser = contentLanguages.includes(b.value)
|
||||||
|
if (aIsUser && !bIsUser) return -1
|
||||||
|
if (bIsUser && !aIsUser) return 1
|
||||||
|
// prioritize "common" langs in the network
|
||||||
|
const aIsCommon = !!APP_LANGUAGES.find(al => al.code2 === a.value)
|
||||||
|
const bIsCommon = !!APP_LANGUAGES.find(al => al.code2 === b.value)
|
||||||
|
if (aIsCommon && !bIsCommon) return -1
|
||||||
|
if (bIsCommon && !aIsCommon) return 1
|
||||||
|
// fall back to alphabetical
|
||||||
|
return a.label.localeCompare(b.label)
|
||||||
|
})
|
||||||
|
}, [appLanguage, contentLanguages])
|
||||||
|
|
||||||
const style = {
|
const currentLanguageLabel =
|
||||||
backgroundColor: t.atoms.bg_contrast_25.backgroundColor,
|
languages.find(lang => lang.value === value)?.label ?? _(msg`All languages`)
|
||||||
color: t.atoms.text.color,
|
|
||||||
fontSize: a.text_xs.fontSize,
|
|
||||||
fontFamily: 'inherit',
|
|
||||||
fontWeight: a.font_bold.fontWeight,
|
|
||||||
paddingHorizontal: 14,
|
|
||||||
paddingRight: 32,
|
|
||||||
paddingVertical: 8,
|
|
||||||
borderRadius: a.rounded_full.borderRadius,
|
|
||||||
borderWidth: a.border.borderWidth,
|
|
||||||
borderColor: t.atoms.border_contrast_low.borderColor,
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RNPickerSelect
|
<Menu.Root>
|
||||||
darkTheme={t.scheme === 'dark'}
|
<Menu.Trigger
|
||||||
placeholder={{}}
|
label={_(
|
||||||
value={value}
|
msg`Filter search by language (currently: ${currentLanguageLabel})`,
|
||||||
onValueChange={onChange}
|
)}>
|
||||||
items={items}
|
{({props}) => (
|
||||||
Icon={() => (
|
<Button
|
||||||
<ChevronDown fill={t.atoms.text_contrast_low.color} size="sm" />
|
{...props}
|
||||||
)}
|
label={props.accessibilityLabel}
|
||||||
useNativeAndroidPickerStyle={false}
|
size="small"
|
||||||
style={{
|
color={platform({native: 'primary', default: 'secondary'})}
|
||||||
iconContainer: {
|
variant={platform({native: 'ghost', default: 'solid'})}
|
||||||
pointerEvents: 'none',
|
style={native([
|
||||||
right: a.px_sm.paddingRight,
|
a.py_sm,
|
||||||
top: 0,
|
a.px_sm,
|
||||||
bottom: 0,
|
{marginRight: tokens.space.sm * -1},
|
||||||
display: 'flex',
|
])}>
|
||||||
justifyContent: 'center',
|
<ButtonIcon icon={EarthIcon} />
|
||||||
},
|
<ButtonText>{currentLanguageLabel}</ButtonText>
|
||||||
inputAndroid: {
|
<ButtonIcon
|
||||||
...style,
|
icon={platform({
|
||||||
paddingVertical: 2,
|
native: ChevronUpDownIcon,
|
||||||
},
|
default: ChevronDownIcon,
|
||||||
inputIOS: {
|
})}
|
||||||
...style,
|
/>
|
||||||
},
|
</Button>
|
||||||
inputWeb: web({
|
)}
|
||||||
...style,
|
</Menu.Trigger>
|
||||||
cursor: 'pointer',
|
<Menu.Outer
|
||||||
// @ts-ignore web only
|
// HACKFIX: Currently there is no height limit for Radix dropdowns,
|
||||||
'-moz-appearance': 'none',
|
// so if it's too tall it just goes off screen. TODO: fix internally -sfn
|
||||||
'-webkit-appearance': 'none',
|
style={web({maxHeight: '70vh'})}>
|
||||||
appearance: 'none',
|
<Menu.LabelText>
|
||||||
outline: 0,
|
<Trans>Filter search by language</Trans>
|
||||||
borderWidth: 0,
|
</Menu.LabelText>
|
||||||
overflow: 'hidden',
|
<Menu.Item label={_(msg`All languages`)} onPress={() => onChange('')}>
|
||||||
whiteSpace: 'nowrap',
|
<Menu.ItemText>
|
||||||
textOverflow: 'ellipsis',
|
<Trans>All languages</Trans>
|
||||||
}),
|
</Menu.ItemText>
|
||||||
}}
|
<Menu.ItemRadio selected={value === ''} />
|
||||||
/>
|
</Menu.Item>
|
||||||
|
<Menu.Divider />
|
||||||
|
<Menu.Group>
|
||||||
|
{languages.map(lang => (
|
||||||
|
<Menu.Item
|
||||||
|
key={lang.key}
|
||||||
|
label={lang.label}
|
||||||
|
onPress={() => onChange(lang.value)}>
|
||||||
|
<Menu.ItemText>{lang.label}</Menu.ItemText>
|
||||||
|
<Menu.ItemRadio selected={value === lang.value} />
|
||||||
|
</Menu.Item>
|
||||||
|
))}
|
||||||
|
</Menu.Group>
|
||||||
|
</Menu.Outer>
|
||||||
|
</Menu.Root>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,12 +530,7 @@ let SearchScreenInner = ({
|
|||||||
<Pager
|
<Pager
|
||||||
onPageSelected={onPageSelected}
|
onPageSelected={onPageSelected}
|
||||||
renderTabBar={props => (
|
renderTabBar={props => (
|
||||||
<Layout.Center
|
<Layout.Center style={[a.z_10, web([a.sticky, {top: headerHeight}])]}>
|
||||||
style={[
|
|
||||||
a.z_10,
|
|
||||||
web([a.sticky]),
|
|
||||||
{top: isWeb ? headerHeight : undefined},
|
|
||||||
]}>
|
|
||||||
<TabBar items={sections.map(section => section.title)} {...props} />
|
<TabBar items={sections.map(section => section.title)} {...props} />
|
||||||
</Layout.Center>
|
</Layout.Center>
|
||||||
)}
|
)}
|
||||||
@@ -597,13 +588,13 @@ SearchScreenInner = React.memo(SearchScreenInner)
|
|||||||
export function SearchScreen(
|
export function SearchScreen(
|
||||||
props: NativeStackScreenProps<SearchTabNavigatorParams, 'Search'>,
|
props: NativeStackScreenProps<SearchTabNavigatorParams, 'Search'>,
|
||||||
) {
|
) {
|
||||||
const t = useThemeNew()
|
const t = useTheme()
|
||||||
const {gtMobile} = useBreakpoints()
|
const {gtMobile} = useBreakpoints()
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
const textInput = React.useRef<TextInput>(null)
|
const textInput = React.useRef<TextInput>(null)
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const setDrawerOpen = useSetDrawerOpen()
|
|
||||||
const setMinimalShellMode = useSetMinimalShellMode()
|
const setMinimalShellMode = useSetMinimalShellMode()
|
||||||
|
const {currentAccount} = useSession()
|
||||||
|
|
||||||
// Query terms
|
// Query terms
|
||||||
const queryParam = props.route?.params?.q ?? ''
|
const queryParam = props.route?.params?.q ?? ''
|
||||||
@@ -612,20 +603,72 @@ export function SearchScreen(
|
|||||||
useActorAutocompleteQuery(searchText, true)
|
useActorAutocompleteQuery(searchText, true)
|
||||||
|
|
||||||
const [showAutocomplete, setShowAutocomplete] = React.useState(false)
|
const [showAutocomplete, setShowAutocomplete] = React.useState(false)
|
||||||
const [searchHistory, setSearchHistory] = React.useState<string[]>([])
|
|
||||||
const [selectedProfiles, setSelectedProfiles] = React.useState<
|
const [termHistory = [], setTermHistory] = useStorage(account, [
|
||||||
AppBskyActorDefs.ProfileViewBasic[]
|
currentAccount?.did ?? 'pwi',
|
||||||
>([])
|
'searchTermHistory',
|
||||||
|
] as const)
|
||||||
|
const [accountHistory = [], setAccountHistory] = useStorage(account, [
|
||||||
|
currentAccount?.did ?? 'pwi',
|
||||||
|
'searchAccountHistory',
|
||||||
|
])
|
||||||
|
|
||||||
|
const {data: accountHistoryProfiles} = useProfilesQuery({
|
||||||
|
handles: accountHistory,
|
||||||
|
maintainData: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
const updateSearchHistory = useCallback(
|
||||||
|
async (item: string) => {
|
||||||
|
if (!item) return
|
||||||
|
const newSearchHistory = [
|
||||||
|
item,
|
||||||
|
...termHistory.filter(search => search !== item),
|
||||||
|
].slice(0, 6)
|
||||||
|
setTermHistory(newSearchHistory)
|
||||||
|
},
|
||||||
|
[termHistory, setTermHistory],
|
||||||
|
)
|
||||||
|
|
||||||
|
const updateProfileHistory = useCallback(
|
||||||
|
async (item: AppBskyActorDefs.ProfileViewBasic) => {
|
||||||
|
const newAccountHistory = [
|
||||||
|
item.did,
|
||||||
|
...accountHistory.filter(p => p !== item.did),
|
||||||
|
].slice(0, 5)
|
||||||
|
setAccountHistory(newAccountHistory)
|
||||||
|
},
|
||||||
|
[accountHistory, setAccountHistory],
|
||||||
|
)
|
||||||
|
|
||||||
|
const deleteSearchHistoryItem = useCallback(
|
||||||
|
async (item: string) => {
|
||||||
|
setTermHistory(termHistory.filter(search => search !== item))
|
||||||
|
},
|
||||||
|
[termHistory, setTermHistory],
|
||||||
|
)
|
||||||
|
const deleteProfileHistoryItem = useCallback(
|
||||||
|
async (item: AppBskyActorDefs.ProfileViewBasic) => {
|
||||||
|
setAccountHistory(accountHistory.filter(p => p !== item.did))
|
||||||
|
},
|
||||||
|
[accountHistory, setAccountHistory],
|
||||||
|
)
|
||||||
|
|
||||||
const {params, query, queryWithParams} = useQueryManager({
|
const {params, query, queryWithParams} = useQueryManager({
|
||||||
initialQuery: queryParam,
|
initialQuery: queryParam,
|
||||||
})
|
})
|
||||||
const showFilters = Boolean(queryWithParams && !showAutocomplete)
|
const showFilters = Boolean(queryWithParams && !showAutocomplete)
|
||||||
/*
|
|
||||||
* Arbitrary sizing, so guess and check, used for sticky header alignment and
|
// web only - measure header height for sticky positioning
|
||||||
* sizing.
|
const [headerHeight, setHeaderHeight] = React.useState(0)
|
||||||
*/
|
const headerRef = React.useRef(null)
|
||||||
const headerHeight = 60 + (showFilters ? 40 : 0)
|
useLayoutEffect(() => {
|
||||||
|
if (isWeb) {
|
||||||
|
if (!headerRef.current) return
|
||||||
|
const measurement = (headerRef.current as Element).getBoundingClientRect()
|
||||||
|
setHeaderHeight(measurement.height)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
useNonReactiveCallback(() => {
|
useNonReactiveCallback(() => {
|
||||||
@@ -635,30 +678,6 @@ export function SearchScreen(
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
const loadSearchHistory = async () => {
|
|
||||||
try {
|
|
||||||
const history = await AsyncStorage.getItem('searchHistory')
|
|
||||||
if (history !== null) {
|
|
||||||
setSearchHistory(JSON.parse(history))
|
|
||||||
}
|
|
||||||
const profiles = await AsyncStorage.getItem('selectedProfiles')
|
|
||||||
if (profiles !== null) {
|
|
||||||
setSelectedProfiles(JSON.parse(profiles))
|
|
||||||
}
|
|
||||||
} catch (e: any) {
|
|
||||||
logger.error('Failed to load search history', {message: e})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
loadSearchHistory()
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const onPressMenu = React.useCallback(() => {
|
|
||||||
textInput.current?.blur()
|
|
||||||
setDrawerOpen(true)
|
|
||||||
}, [setDrawerOpen])
|
|
||||||
|
|
||||||
const onPressClearQuery = React.useCallback(() => {
|
const onPressClearQuery = React.useCallback(() => {
|
||||||
scrollToTopWeb()
|
scrollToTopWeb()
|
||||||
setSearchText('')
|
setSearchText('')
|
||||||
@@ -670,57 +689,6 @@ export function SearchScreen(
|
|||||||
setSearchText(text)
|
setSearchText(text)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const updateSearchHistory = React.useCallback(
|
|
||||||
async (newQuery: string) => {
|
|
||||||
newQuery = newQuery.trim()
|
|
||||||
if (newQuery) {
|
|
||||||
let newHistory = [
|
|
||||||
newQuery,
|
|
||||||
...searchHistory.filter(q => q !== newQuery),
|
|
||||||
]
|
|
||||||
|
|
||||||
if (newHistory.length > 5) {
|
|
||||||
newHistory = newHistory.slice(0, 5)
|
|
||||||
}
|
|
||||||
|
|
||||||
setSearchHistory(newHistory)
|
|
||||||
try {
|
|
||||||
await AsyncStorage.setItem(
|
|
||||||
'searchHistory',
|
|
||||||
JSON.stringify(newHistory),
|
|
||||||
)
|
|
||||||
} catch (e: any) {
|
|
||||||
logger.error('Failed to save search history', {message: e})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[searchHistory, setSearchHistory],
|
|
||||||
)
|
|
||||||
|
|
||||||
const updateSelectedProfiles = React.useCallback(
|
|
||||||
async (profile: AppBskyActorDefs.ProfileViewBasic) => {
|
|
||||||
let newProfiles = [
|
|
||||||
profile,
|
|
||||||
...selectedProfiles.filter(p => p.did !== profile.did),
|
|
||||||
]
|
|
||||||
|
|
||||||
if (newProfiles.length > 5) {
|
|
||||||
newProfiles = newProfiles.slice(0, 5)
|
|
||||||
}
|
|
||||||
|
|
||||||
setSelectedProfiles(newProfiles)
|
|
||||||
try {
|
|
||||||
await AsyncStorage.setItem(
|
|
||||||
'selectedProfiles',
|
|
||||||
JSON.stringify(newProfiles),
|
|
||||||
)
|
|
||||||
} catch (e: any) {
|
|
||||||
logger.error('Failed to save selected profiles', {message: e})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[selectedProfiles, setSelectedProfiles],
|
|
||||||
)
|
|
||||||
|
|
||||||
const navigateToItem = React.useCallback(
|
const navigateToItem = React.useCallback(
|
||||||
(item: string) => {
|
(item: string) => {
|
||||||
scrollToTopWeb()
|
scrollToTopWeb()
|
||||||
@@ -774,10 +742,10 @@ export function SearchScreen(
|
|||||||
(profile: AppBskyActorDefs.ProfileViewBasic) => {
|
(profile: AppBskyActorDefs.ProfileViewBasic) => {
|
||||||
// Slight delay to avoid updating during push nav animation.
|
// Slight delay to avoid updating during push nav animation.
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
updateSelectedProfiles(profile)
|
updateProfileHistory(profile)
|
||||||
}, 400)
|
}, 400)
|
||||||
},
|
},
|
||||||
[updateSelectedProfiles],
|
[updateProfileHistory],
|
||||||
)
|
)
|
||||||
|
|
||||||
const onSoftReset = React.useCallback(() => {
|
const onSoftReset = React.useCallback(() => {
|
||||||
@@ -798,36 +766,6 @@ export function SearchScreen(
|
|||||||
}, [onSoftReset, setMinimalShellMode]),
|
}, [onSoftReset, setMinimalShellMode]),
|
||||||
)
|
)
|
||||||
|
|
||||||
const handleRemoveHistoryItem = React.useCallback(
|
|
||||||
(itemToRemove: string) => {
|
|
||||||
const updatedHistory = searchHistory.filter(item => item !== itemToRemove)
|
|
||||||
setSearchHistory(updatedHistory)
|
|
||||||
AsyncStorage.setItem(
|
|
||||||
'searchHistory',
|
|
||||||
JSON.stringify(updatedHistory),
|
|
||||||
).catch(e => {
|
|
||||||
logger.error('Failed to update search history', {message: e})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
[searchHistory],
|
|
||||||
)
|
|
||||||
|
|
||||||
const handleRemoveProfile = React.useCallback(
|
|
||||||
(profileToRemove: AppBskyActorDefs.ProfileViewBasic) => {
|
|
||||||
const updatedProfiles = selectedProfiles.filter(
|
|
||||||
profile => profile.did !== profileToRemove.did,
|
|
||||||
)
|
|
||||||
setSelectedProfiles(updatedProfiles)
|
|
||||||
AsyncStorage.setItem(
|
|
||||||
'selectedProfiles',
|
|
||||||
JSON.stringify(updatedProfiles),
|
|
||||||
).catch(e => {
|
|
||||||
logger.error('Failed to update selected profiles', {message: e})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
[selectedProfiles],
|
|
||||||
)
|
|
||||||
|
|
||||||
const onSearchInputFocus = React.useCallback(() => {
|
const onSearchInputFocus = React.useCallback(() => {
|
||||||
if (isWeb) {
|
if (isWeb) {
|
||||||
// Prevent a jump on iPad by ensuring that
|
// Prevent a jump on iPad by ensuring that
|
||||||
@@ -843,75 +781,89 @@ export function SearchScreen(
|
|||||||
return (
|
return (
|
||||||
<Layout.Screen testID="searchScreen">
|
<Layout.Screen testID="searchScreen">
|
||||||
<View
|
<View
|
||||||
|
ref={headerRef}
|
||||||
|
onLayout={evt => {
|
||||||
|
if (isWeb) setHeaderHeight(evt.nativeEvent.layout.height)
|
||||||
|
}}
|
||||||
style={[
|
style={[
|
||||||
|
a.relative,
|
||||||
|
a.z_10,
|
||||||
web({
|
web({
|
||||||
height: headerHeight,
|
|
||||||
position: 'sticky',
|
position: 'sticky',
|
||||||
top: 0,
|
top: 0,
|
||||||
zIndex: 1,
|
|
||||||
}),
|
}),
|
||||||
]}>
|
]}>
|
||||||
<Layout.Center>
|
<Layout.Center style={t.atoms.bg}>
|
||||||
<View style={[a.p_md, a.pb_sm, a.gap_sm, t.atoms.bg]}>
|
{!gtMobile && (
|
||||||
<View style={[a.flex_row, a.gap_sm]}>
|
<View
|
||||||
{!gtMobile && !showAutocomplete && (
|
// HACK: shift up search input. we can't remove the top padding
|
||||||
<Button
|
// on the search input because it messes up the layout animation
|
||||||
testID="viewHeaderBackOrMenuBtn"
|
// if we add it only when the header is hidden
|
||||||
onPress={onPressMenu}
|
style={{marginBottom: tokens.space.xs * -1}}>
|
||||||
hitSlop={HITSLOP_10}
|
<Layout.Header.Outer noBottomBorder>
|
||||||
label={_(msg`Menu`)}
|
<Layout.Header.MenuButton />
|
||||||
accessibilityHint={_(
|
<Layout.Header.Content align="left">
|
||||||
msg`Access navigation links and settings`,
|
<Layout.Header.TitleText>
|
||||||
)}
|
<Trans>Search</Trans>
|
||||||
size="large"
|
</Layout.Header.TitleText>
|
||||||
variant="solid"
|
</Layout.Header.Content>
|
||||||
color="secondary"
|
{showFilters ? (
|
||||||
shape="square">
|
<SearchLanguageDropdown
|
||||||
<ButtonIcon icon={Menu} size="lg" />
|
value={params.lang}
|
||||||
</Button>
|
onChange={params.setLang}
|
||||||
)}
|
/>
|
||||||
<View style={[a.flex_1]}>
|
) : (
|
||||||
<SearchInput
|
<Layout.Header.Slot />
|
||||||
ref={textInput}
|
)}
|
||||||
value={searchText}
|
</Layout.Header.Outer>
|
||||||
onFocus={onSearchInputFocus}
|
|
||||||
onChangeText={onChangeText}
|
|
||||||
onClearText={onPressClearQuery}
|
|
||||||
onSubmitEditing={onSubmit}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
{showAutocomplete && (
|
|
||||||
<Button
|
|
||||||
label={_(msg`Cancel search`)}
|
|
||||||
size="large"
|
|
||||||
variant="ghost"
|
|
||||||
color="secondary"
|
|
||||||
style={[a.px_sm]}
|
|
||||||
onPress={onPressCancelSearch}
|
|
||||||
hitSlop={HITSLOP_10}>
|
|
||||||
<ButtonText>
|
|
||||||
<Trans>Cancel</Trans>
|
|
||||||
</ButtonText>
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</View>
|
</View>
|
||||||
|
)}
|
||||||
|
<View style={[a.px_md, a.pt_sm, a.pb_sm, a.overflow_hidden]}>
|
||||||
|
<View style={[a.gap_sm]}>
|
||||||
|
<View style={[a.w_full, a.flex_row, a.align_stretch, a.gap_xs]}>
|
||||||
|
<View style={[a.flex_1]}>
|
||||||
|
<SearchInput
|
||||||
|
ref={textInput}
|
||||||
|
value={searchText}
|
||||||
|
onFocus={onSearchInputFocus}
|
||||||
|
onChangeText={onChangeText}
|
||||||
|
onClearText={onPressClearQuery}
|
||||||
|
onSubmitEditing={onSubmit}
|
||||||
|
placeholder={_(msg`Search for posts, users, or feeds`)}
|
||||||
|
hitSlop={{...HITSLOP_20, top: 0}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
{showAutocomplete && (
|
||||||
|
<Button
|
||||||
|
label={_(msg`Cancel search`)}
|
||||||
|
size="large"
|
||||||
|
variant="ghost"
|
||||||
|
color="secondary"
|
||||||
|
style={[a.px_sm]}
|
||||||
|
onPress={onPressCancelSearch}
|
||||||
|
hitSlop={HITSLOP_10}>
|
||||||
|
<ButtonText>
|
||||||
|
<Trans>Cancel</Trans>
|
||||||
|
</ButtonText>
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
|
||||||
{showFilters && (
|
{showFilters && gtMobile && (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
a.flex_row,
|
a.flex_row,
|
||||||
a.align_center,
|
a.align_center,
|
||||||
a.justify_between,
|
a.justify_between,
|
||||||
a.gap_sm,
|
a.gap_sm,
|
||||||
]}>
|
]}>
|
||||||
<View style={[{width: 140}]}>
|
|
||||||
<SearchLanguageDropdown
|
<SearchLanguageDropdown
|
||||||
value={params.lang}
|
value={params.lang}
|
||||||
onChange={params.setLang}
|
onChange={params.setLang}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
)}
|
||||||
)}
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</Layout.Center>
|
</Layout.Center>
|
||||||
</View>
|
</View>
|
||||||
@@ -932,12 +884,12 @@ export function SearchScreen(
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<SearchHistory
|
<SearchHistory
|
||||||
searchHistory={searchHistory}
|
searchHistory={termHistory}
|
||||||
selectedProfiles={selectedProfiles}
|
selectedProfiles={accountHistoryProfiles?.profiles || []}
|
||||||
onItemClick={handleHistoryItemClick}
|
onItemClick={handleHistoryItemClick}
|
||||||
onProfileClick={handleProfileClick}
|
onProfileClick={handleProfileClick}
|
||||||
onRemoveItemClick={handleRemoveHistoryItem}
|
onRemoveItemClick={deleteSearchHistoryItem}
|
||||||
onRemoveProfileClick={handleRemoveProfile}
|
onRemoveProfileClick={deleteProfileHistoryItem}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
@@ -1087,7 +1039,7 @@ function SearchHistory({
|
|||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
accessibilityLabel={_(msg`Remove profile`)}
|
accessibilityLabel={_(msg`Remove profile`)}
|
||||||
accessibilityHint={_(
|
accessibilityHint={_(
|
||||||
msg`Remove profile from search history`,
|
msg`Removes profile from search history`,
|
||||||
)}
|
)}
|
||||||
onPress={() => onRemoveProfileClick(profile)}
|
onPress={() => onRemoveProfileClick(profile)}
|
||||||
hitSlop={createHitslop(6)}
|
hitSlop={createHitslop(6)}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {useFocusGuards} from '@radix-ui/react-focus-guards'
|
|||||||
import {FocusScope} from '@radix-ui/react-focus-scope'
|
import {FocusScope} from '@radix-ui/react-focus-scope'
|
||||||
import {RemoveScrollBar} from 'react-remove-scroll-bar'
|
import {RemoveScrollBar} from 'react-remove-scroll-bar'
|
||||||
|
|
||||||
|
import {useA11y} from '#/state/a11y'
|
||||||
import {useModals} from '#/state/modals'
|
import {useModals} from '#/state/modals'
|
||||||
import {ComposerOpts, useComposerState} from '#/state/shell/composer'
|
import {ComposerOpts, useComposerState} from '#/state/shell/composer'
|
||||||
import {
|
import {
|
||||||
@@ -12,7 +13,7 @@ import {
|
|||||||
EmojiPickerPosition,
|
EmojiPickerPosition,
|
||||||
EmojiPickerState,
|
EmojiPickerState,
|
||||||
} from '#/view/com/composer/text-input/web/EmojiPicker.web'
|
} from '#/view/com/composer/text-input/web/EmojiPicker.web'
|
||||||
import {useBreakpoints, useTheme} from '#/alf'
|
import {atoms as a, flatten, useBreakpoints, useTheme} from '#/alf'
|
||||||
import {ComposePost, useComposerCancelRef} from '../com/composer/Composer'
|
import {ComposePost, useComposerCancelRef} from '../com/composer/Composer'
|
||||||
|
|
||||||
const BOTTOM_BAR_HEIGHT = 61
|
const BOTTOM_BAR_HEIGHT = 61
|
||||||
@@ -41,6 +42,7 @@ function Inner({state}: {state: ComposerOpts}) {
|
|||||||
const {isModalActive} = useModals()
|
const {isModalActive} = useModals()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {gtMobile} = useBreakpoints()
|
const {gtMobile} = useBreakpoints()
|
||||||
|
const {reduceMotionEnabled} = useA11y()
|
||||||
const [pickerState, setPickerState] = React.useState<EmojiPickerState>({
|
const [pickerState, setPickerState] = React.useState<EmojiPickerState>({
|
||||||
isOpen: false,
|
isOpen: false,
|
||||||
pos: {top: 0, left: 0, right: 0, bottom: 0, nextFocusRef: null},
|
pos: {top: 0, left: 0, right: 0, bottom: 0, nextFocusRef: null},
|
||||||
@@ -71,17 +73,15 @@ function Inner({state}: {state: ComposerOpts}) {
|
|||||||
<DismissableLayer
|
<DismissableLayer
|
||||||
role="dialog"
|
role="dialog"
|
||||||
aria-modal
|
aria-modal
|
||||||
style={{
|
style={flatten([
|
||||||
position: 'fixed',
|
{position: 'fixed'},
|
||||||
top: 0,
|
a.inset_0,
|
||||||
left: 0,
|
{backgroundColor: '#000c'},
|
||||||
width: '100%',
|
a.flex,
|
||||||
height: '100%',
|
a.flex_col,
|
||||||
backgroundColor: '#000c',
|
a.align_center,
|
||||||
display: 'flex',
|
!reduceMotionEnabled && a.fade_in,
|
||||||
flexDirection: 'column',
|
])}
|
||||||
alignItems: 'center',
|
|
||||||
}}
|
|
||||||
onFocusOutside={evt => evt.preventDefault()}
|
onFocusOutside={evt => evt.preventDefault()}
|
||||||
onInteractOutside={evt => evt.preventDefault()}
|
onInteractOutside={evt => evt.preventDefault()}
|
||||||
onDismiss={() => {
|
onDismiss={() => {
|
||||||
@@ -96,6 +96,11 @@ function Inner({state}: {state: ComposerOpts}) {
|
|||||||
!gtMobile && styles.containerMobile,
|
!gtMobile && styles.containerMobile,
|
||||||
t.atoms.bg,
|
t.atoms.bg,
|
||||||
t.atoms.border_contrast_medium,
|
t.atoms.border_contrast_medium,
|
||||||
|
!reduceMotionEnabled && [
|
||||||
|
a.zoom_fade_in,
|
||||||
|
{animationDelay: 0.1},
|
||||||
|
{animationFillMode: 'backwards'},
|
||||||
|
],
|
||||||
]}>
|
]}>
|
||||||
<ComposePost
|
<ComposePost
|
||||||
cancelRef={ref}
|
cancelRef={ref}
|
||||||
@@ -123,14 +128,14 @@ const styles = StyleSheet.create({
|
|||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
marginBottom: 0,
|
marginBottom: 0,
|
||||||
borderWidth: 1,
|
borderWidth: 1,
|
||||||
// @ts-ignore web only
|
// @ts-expect-error web only
|
||||||
maxHeight: 'calc(100% - (40px * 2))',
|
maxHeight: 'calc(100% - (40px * 2))',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
},
|
},
|
||||||
containerMobile: {
|
containerMobile: {
|
||||||
borderRadius: 0,
|
borderRadius: 0,
|
||||||
marginBottom: BOTTOM_BAR_HEIGHT,
|
marginBottom: BOTTOM_BAR_HEIGHT,
|
||||||
// @ts-ignore web only
|
// @ts-expect-error web only
|
||||||
maxHeight: `calc(100% - ${BOTTOM_BAR_HEIGHT}px)`,
|
maxHeight: `calc(100% - ${BOTTOM_BAR_HEIGHT}px)`,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import {LoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder'
|
|||||||
import {PressableWithHover} from '#/view/com/util/PressableWithHover'
|
import {PressableWithHover} from '#/view/com/util/PressableWithHover'
|
||||||
import {UserAvatar} from '#/view/com/util/UserAvatar'
|
import {UserAvatar} from '#/view/com/util/UserAvatar'
|
||||||
import {NavSignupCard} from '#/view/shell/NavSignupCard'
|
import {NavSignupCard} from '#/view/shell/NavSignupCard'
|
||||||
import {atoms as a, tokens, useBreakpoints, useTheme} from '#/alf'
|
import {atoms as a, tokens, useBreakpoints, useTheme, web} from '#/alf'
|
||||||
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
|
||||||
import {DialogControlProps} from '#/components/Dialog'
|
import {DialogControlProps} from '#/components/Dialog'
|
||||||
import {ArrowBoxLeft_Stroke2_Corner0_Rounded as LeaveIcon} from '#/components/icons/ArrowBoxLeft'
|
import {ArrowBoxLeft_Stroke2_Corner0_Rounded as LeaveIcon} from '#/components/icons/ArrowBoxLeft'
|
||||||
@@ -235,7 +235,10 @@ function SwitchMenuItems({
|
|||||||
closeEverything()
|
closeEverything()
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Menu.Outer>
|
<Menu.Outer
|
||||||
|
// HACKFIX: Currently there is no height limit for Radix dropdowns,
|
||||||
|
// so if it's too tall it just goes off screen. TODO: fix internally -sfn
|
||||||
|
style={web({maxHeight: '70vh'})}>
|
||||||
{accounts && accounts.length > 0 && (
|
{accounts && accounts.length > 0 && (
|
||||||
<>
|
<>
|
||||||
<Menu.Group>
|
<Menu.Group>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, {useEffect} from 'react'
|
import {useEffect, useLayoutEffect, useState} from 'react'
|
||||||
import {StyleSheet, TouchableWithoutFeedback, View} from 'react-native'
|
import {StyleSheet, TouchableWithoutFeedback, View} from 'react-native'
|
||||||
import {msg} from '@lingui/macro'
|
import {msg} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
@@ -33,6 +33,20 @@ function ShellInner() {
|
|||||||
const closeAllActiveElements = useCloseAllActiveElements()
|
const closeAllActiveElements = useCloseAllActiveElements()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const showDrawer = !isDesktop && isDrawerOpen
|
const showDrawer = !isDesktop && isDrawerOpen
|
||||||
|
const [showDrawerDelayedExit, setShowDrawerDelayedExit] = useState(showDrawer)
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
if (showDrawer !== showDrawerDelayedExit) {
|
||||||
|
if (showDrawer) {
|
||||||
|
setShowDrawerDelayedExit(true)
|
||||||
|
} else {
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
setShowDrawerDelayedExit(false)
|
||||||
|
}, 160)
|
||||||
|
return () => clearTimeout(timeout)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [showDrawer, showDrawerDelayedExit])
|
||||||
|
|
||||||
useComposerKeyboardShortcut()
|
useComposerKeyboardShortcut()
|
||||||
useIntentHandler()
|
useIntentHandler()
|
||||||
@@ -56,7 +70,7 @@ function ShellInner() {
|
|||||||
<Lightbox />
|
<Lightbox />
|
||||||
<PortalOutlet />
|
<PortalOutlet />
|
||||||
|
|
||||||
{showDrawer && (
|
{showDrawerDelayedExit && (
|
||||||
<>
|
<>
|
||||||
<RemoveScrollBar />
|
<RemoveScrollBar />
|
||||||
<TouchableWithoutFeedback
|
<TouchableWithoutFeedback
|
||||||
@@ -66,20 +80,27 @@ function ShellInner() {
|
|||||||
setDrawerOpen(false)
|
setDrawerOpen(false)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
accessibilityLabel={_(msg`Close navigation footer`)}
|
accessibilityLabel={_(msg`Close drawer menu`)}
|
||||||
accessibilityHint={_(msg`Closes bottom navigation bar`)}>
|
accessibilityHint="">
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.drawerMask,
|
styles.drawerMask,
|
||||||
{
|
{
|
||||||
backgroundColor: select(t.name, {
|
backgroundColor: showDrawer
|
||||||
light: 'rgba(0, 57, 117, 0.1)',
|
? select(t.name, {
|
||||||
dark: 'rgba(1, 82, 168, 0.1)',
|
light: 'rgba(0, 57, 117, 0.1)',
|
||||||
dim: 'rgba(10, 13, 16, 0.8)',
|
dark: 'rgba(1, 82, 168, 0.1)',
|
||||||
}),
|
dim: 'rgba(10, 13, 16, 0.8)',
|
||||||
|
})
|
||||||
|
: 'transparent',
|
||||||
},
|
},
|
||||||
|
a.transition_color,
|
||||||
]}>
|
]}>
|
||||||
<View style={styles.drawerContainer}>
|
<View
|
||||||
|
style={[
|
||||||
|
styles.drawerContainer,
|
||||||
|
showDrawer ? a.slide_in_left : a.slide_out_left,
|
||||||
|
]}>
|
||||||
<DrawerContent />
|
<DrawerContent />
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
@@ -109,7 +130,6 @@ const styles = StyleSheet.create({
|
|||||||
backgroundColor: colors.black, // TODO
|
backgroundColor: colors.black, // TODO
|
||||||
},
|
},
|
||||||
drawerMask: {
|
drawerMask: {
|
||||||
// @ts-ignore web only
|
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
@@ -118,10 +138,11 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
drawerContainer: {
|
drawerContainer: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
// @ts-ignore web only
|
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
top: 0,
|
top: 0,
|
||||||
left: 0,
|
left: 0,
|
||||||
height: '100%',
|
height: '100%',
|
||||||
|
width: 330,
|
||||||
|
maxWidth: '80%',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"types": ["node"],
|
"types": ["node", "jest"],
|
||||||
"paths": {
|
"paths": {
|
||||||
"#/*": ["./src/*"],
|
"#/*": ["./src/*"],
|
||||||
"lib/*": ["./src/lib/*"],
|
"lib/*": ["./src/lib/*"],
|
||||||
|
|||||||
@@ -277,7 +277,7 @@
|
|||||||
multiformats "^9.9.0"
|
multiformats "^9.9.0"
|
||||||
zod "^3.23.8"
|
zod "^3.23.8"
|
||||||
|
|
||||||
"@atproto/lexicon@^0.4.7":
|
"@atproto/lexicon@^0.4.4", "@atproto/lexicon@^0.4.7":
|
||||||
version "0.4.7"
|
version "0.4.7"
|
||||||
resolved "https://registry.yarnpkg.com/@atproto/lexicon/-/lexicon-0.4.7.tgz#f5d31615c21bcfd3e655f1e4f11a40a62fea9f86"
|
resolved "https://registry.yarnpkg.com/@atproto/lexicon/-/lexicon-0.4.7.tgz#f5d31615c21bcfd3e655f1e4f11a40a62fea9f86"
|
||||||
integrity sha512-/x6h3tAiDNzSi4eXtC8ke65B7UzsagtlGRHmUD95698x5lBRpDnpizj0fZWTZVYed5qnOmz/ZEue+v3wDmO61g==
|
integrity sha512-/x6h3tAiDNzSi4eXtC8ke65B7UzsagtlGRHmUD95698x5lBRpDnpizj0fZWTZVYed5qnOmz/ZEue+v3wDmO61g==
|
||||||
|
|||||||
Reference in New Issue
Block a user