Merge remote-tracking branch 'upstream/main' into invite-code-warning
This commit is contained in:
commit
b164f151cc
76 changed files with 1718 additions and 1240 deletions
|
@ -4,7 +4,7 @@ import {openApp, loginAsAlice, createServer} from '../util'
|
||||||
|
|
||||||
describe('Home screen', () => {
|
describe('Home screen', () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await createServer('?users&follows&posts')
|
await createServer('?users&follows&posts&feeds')
|
||||||
await openApp({permissions: {notifications: 'YES'}})
|
await openApp({permissions: {notifications: 'YES'}})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -13,6 +13,23 @@ describe('Home screen', () => {
|
||||||
await element(by.id('homeScreenFeedTabs-Following')).tap()
|
await element(by.id('homeScreenFeedTabs-Following')).tap()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Can go to feeds page using feeds button in tab bar', async () => {
|
||||||
|
await element(by.id('homeScreenFeedTabs-Feeds ✨')).tap()
|
||||||
|
await expect(element(by.text('Discover new feeds'))).toBeVisible()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Feeds button disappears after pinning a feed', async () => {
|
||||||
|
await element(by.id('bottomBarProfileBtn')).tap()
|
||||||
|
await element(by.id('profilePager-selector')).swipe('left')
|
||||||
|
await element(by.id('profilePager-selector-4')).tap()
|
||||||
|
await element(by.id('feed-alice-favs')).tap()
|
||||||
|
await element(by.id('pinBtn')).tap()
|
||||||
|
await element(by.id('bottomBarHomeBtn')).tap()
|
||||||
|
await expect(
|
||||||
|
element(by.id('homeScreenFeedTabs-Feeds ✨')),
|
||||||
|
).not.toBeVisible()
|
||||||
|
})
|
||||||
|
|
||||||
it('Can like posts', async () => {
|
it('Can like posts', async () => {
|
||||||
const carlaPosts = by.id('feedItem-by-carla.test')
|
const carlaPosts = by.id('feedItem-by-carla.test')
|
||||||
await expect(
|
await expect(
|
||||||
|
@ -65,14 +82,14 @@ describe('Home screen', () => {
|
||||||
|
|
||||||
it('Can swipe between feeds', async () => {
|
it('Can swipe between feeds', async () => {
|
||||||
await element(by.id('homeScreen')).swipe('left', 'fast', 0.75)
|
await element(by.id('homeScreen')).swipe('left', 'fast', 0.75)
|
||||||
await expect(element(by.id('whatshotFeedPage'))).toBeVisible()
|
await expect(element(by.id('customFeedPage'))).toBeVisible()
|
||||||
await element(by.id('homeScreen')).swipe('right', 'fast', 0.75)
|
await element(by.id('homeScreen')).swipe('right', 'fast', 0.75)
|
||||||
await expect(element(by.id('followingFeedPage'))).toBeVisible()
|
await expect(element(by.id('followingFeedPage'))).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Can tap between feeds', async () => {
|
it('Can tap between feeds', async () => {
|
||||||
await element(by.id("homeScreenFeedTabs-What's hot")).tap()
|
await element(by.id('homeScreenFeedTabs-alice-favs')).tap()
|
||||||
await expect(element(by.id('whatshotFeedPage'))).toBeVisible()
|
await expect(element(by.id('customFeedPage'))).toBeVisible()
|
||||||
await element(by.id('homeScreenFeedTabs-Following')).tap()
|
await element(by.id('homeScreenFeedTabs-Following')).tap()
|
||||||
await expect(element(by.id('followingFeedPage'))).toBeVisible()
|
await expect(element(by.id('followingFeedPage'))).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,12 +1,41 @@
|
||||||
|
const pkg = require('./package.json')
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
const hasSentryToken = !!process.env.SENTRY_AUTH_TOKEN
|
/**
|
||||||
|
* App version number. Should be incremented as part of a release cycle.
|
||||||
|
*/
|
||||||
|
const VERSION = pkg.version
|
||||||
|
|
||||||
|
/**
|
||||||
|
* iOS build number. Must be incremented for each TestFlight version.
|
||||||
|
*/
|
||||||
|
const IOS_BUILD_NUMBER = '5'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Android build number. Must be incremented for each release.
|
||||||
|
*/
|
||||||
|
const ANDROID_VERSION_CODE = 46
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses built-in Expo env vars
|
||||||
|
*
|
||||||
|
* @see https://docs.expo.dev/build-reference/variables/#built-in-environment-variables
|
||||||
|
*/
|
||||||
|
const PLATFORM = process.env.EAS_BUILD_PLATFORM
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Additional granularity for the `dist` field
|
||||||
|
*/
|
||||||
|
const DIST_BUILD_NUMBER =
|
||||||
|
PLATFORM === 'android' ? ANDROID_VERSION_CODE : IOS_BUILD_NUMBER
|
||||||
|
|
||||||
return {
|
return {
|
||||||
expo: {
|
expo: {
|
||||||
|
version: VERSION,
|
||||||
name: 'Bluesky',
|
name: 'Bluesky',
|
||||||
slug: 'bluesky',
|
slug: 'bluesky',
|
||||||
scheme: 'bluesky',
|
scheme: 'bluesky',
|
||||||
owner: 'blueskysocial',
|
owner: 'blueskysocial',
|
||||||
version: '1.57.0',
|
|
||||||
runtimeVersion: {
|
runtimeVersion: {
|
||||||
policy: 'appVersion',
|
policy: 'appVersion',
|
||||||
},
|
},
|
||||||
|
@ -19,7 +48,7 @@ module.exports = function () {
|
||||||
backgroundColor: '#ffffff',
|
backgroundColor: '#ffffff',
|
||||||
},
|
},
|
||||||
ios: {
|
ios: {
|
||||||
buildNumber: '4',
|
buildNumber: IOS_BUILD_NUMBER,
|
||||||
supportsTablet: false,
|
supportsTablet: false,
|
||||||
bundleIdentifier: 'xyz.blueskyweb.app',
|
bundleIdentifier: 'xyz.blueskyweb.app',
|
||||||
config: {
|
config: {
|
||||||
|
@ -43,7 +72,7 @@ module.exports = function () {
|
||||||
backgroundColor: '#ffffff',
|
backgroundColor: '#ffffff',
|
||||||
},
|
},
|
||||||
android: {
|
android: {
|
||||||
versionCode: 46,
|
versionCode: ANDROID_VERSION_CODE,
|
||||||
adaptiveIcon: {
|
adaptiveIcon: {
|
||||||
foregroundImage: './assets/adaptive-icon.png',
|
foregroundImage: './assets/adaptive-icon.png',
|
||||||
backgroundColor: '#ffffff',
|
backgroundColor: '#ffffff',
|
||||||
|
@ -74,7 +103,7 @@ module.exports = function () {
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
'expo-localization',
|
'expo-localization',
|
||||||
hasSentryToken && 'sentry-expo',
|
Boolean(process.env.SENTRY_AUTH_TOKEN) && 'sentry-expo',
|
||||||
[
|
[
|
||||||
'expo-build-properties',
|
'expo-build-properties',
|
||||||
{
|
{
|
||||||
|
@ -100,11 +129,16 @@ module.exports = function () {
|
||||||
},
|
},
|
||||||
hooks: {
|
hooks: {
|
||||||
postPublish: [
|
postPublish: [
|
||||||
|
/*
|
||||||
|
* @see https://docs.expo.dev/guides/using-sentry/#app-configuration
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
file: 'sentry-expo/upload-sourcemaps',
|
file: 'sentry-expo/upload-sourcemaps',
|
||||||
config: {
|
config: {
|
||||||
organization: 'blueskyweb',
|
organization: 'blueskyweb',
|
||||||
project: 'react-native',
|
project: 'react-native',
|
||||||
|
release: VERSION,
|
||||||
|
dist: `${PLATFORM}.${VERSION}.${DIST_BUILD_NUMBER}`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
25
eas.json
25
eas.json
|
@ -11,28 +11,19 @@
|
||||||
"extends": "base",
|
"extends": "base",
|
||||||
"developmentClient": true,
|
"developmentClient": true,
|
||||||
"distribution": "internal",
|
"distribution": "internal",
|
||||||
|
"channel": "development",
|
||||||
"ios": {
|
"ios": {
|
||||||
"simulator": true,
|
"simulator": true,
|
||||||
"resourceClass": "large"
|
"resourceClass": "large"
|
||||||
},
|
}
|
||||||
"channel": "development"
|
|
||||||
},
|
|
||||||
"development-device": {
|
|
||||||
"extends": "base",
|
|
||||||
"developmentClient": true,
|
|
||||||
"distribution": "internal",
|
|
||||||
"ios": {
|
|
||||||
"resourceClass": "large"
|
|
||||||
},
|
|
||||||
"channel": "development"
|
|
||||||
},
|
},
|
||||||
"preview": {
|
"preview": {
|
||||||
"extends": "base",
|
"extends": "base",
|
||||||
"distribution": "internal",
|
"distribution": "internal",
|
||||||
|
"channel": "preview",
|
||||||
"ios": {
|
"ios": {
|
||||||
"resourceClass": "large"
|
"resourceClass": "large"
|
||||||
},
|
}
|
||||||
"channel": "preview"
|
|
||||||
},
|
},
|
||||||
"production": {
|
"production": {
|
||||||
"extends": "base",
|
"extends": "base",
|
||||||
|
@ -40,14 +31,6 @@
|
||||||
"resourceClass": "large"
|
"resourceClass": "large"
|
||||||
},
|
},
|
||||||
"channel": "production"
|
"channel": "production"
|
||||||
},
|
|
||||||
"dev-android-apk": {
|
|
||||||
"extends": "base",
|
|
||||||
"developmentClient": true,
|
|
||||||
"android": {
|
|
||||||
"buildType": "apk",
|
|
||||||
"gradleCommand": ":app:assembleRelease"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"submit": {
|
"submit": {
|
||||||
|
|
6
index.js
6
index.js
|
@ -3,10 +3,12 @@ import 'react-native-gesture-handler' // must be first
|
||||||
import {LogBox} from 'react-native'
|
import {LogBox} from 'react-native'
|
||||||
LogBox.ignoreLogs(['Require cycle:']) // suppress require-cycle warnings, it's fine
|
LogBox.ignoreLogs(['Require cycle:']) // suppress require-cycle warnings, it's fine
|
||||||
|
|
||||||
import 'platform/polyfills'
|
import '#/platform/polyfills'
|
||||||
import {registerRootComponent} from 'expo'
|
import {registerRootComponent} from 'expo'
|
||||||
|
import {doPolyfill} from '#/lib/api/api-polyfill'
|
||||||
|
doPolyfill()
|
||||||
|
|
||||||
import App from './src/App'
|
import App from '#/App'
|
||||||
|
|
||||||
// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
|
// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
|
||||||
// It also ensures that whether you load the app in Expo Go or in a native build,
|
// It also ensures that whether you load the app in Expo Go or in a native build,
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import 'platform/polyfills'
|
import '#/platform/polyfills'
|
||||||
import {registerRootComponent} from 'expo'
|
import {registerRootComponent} from 'expo'
|
||||||
import App from './src/App'
|
import {doPolyfill} from '#/lib/api/api-polyfill'
|
||||||
|
import App from '#/App'
|
||||||
|
|
||||||
|
doPolyfill()
|
||||||
registerRootComponent(App)
|
registerRootComponent(App)
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
"perf:test:measure": "NODE_ENV=test flashlight test --bundleId xyz.blueskyweb.app --testCommand 'yarn perf:test' --duration 150000 --resultsFilePath .perf/results.json",
|
"perf:test:measure": "NODE_ENV=test flashlight test --bundleId xyz.blueskyweb.app --testCommand 'yarn perf:test' --duration 150000 --resultsFilePath .perf/results.json",
|
||||||
"perf:test:results": "NODE_ENV=test flashlight report .perf/results.json",
|
"perf:test:results": "NODE_ENV=test flashlight report .perf/results.json",
|
||||||
"perf:measure": "NODE_ENV=test flashlight measure",
|
"perf:measure": "NODE_ENV=test flashlight measure",
|
||||||
"build:apk": "eas build -p android --profile dev-android-apk",
|
|
||||||
"intl:extract": "lingui extract",
|
"intl:extract": "lingui extract",
|
||||||
"intl:compile": "lingui compile"
|
"intl:compile": "lingui compile"
|
||||||
},
|
},
|
||||||
|
|
|
@ -16,14 +16,7 @@ export type FeedTunerFn = (
|
||||||
export class FeedViewPostsSlice {
|
export class FeedViewPostsSlice {
|
||||||
isFlattenedReply = false
|
isFlattenedReply = false
|
||||||
|
|
||||||
constructor(public items: FeedViewPost[] = []) {}
|
constructor(public items: FeedViewPost[], public _reactKey: string) {}
|
||||||
|
|
||||||
get _reactKey() {
|
|
||||||
const rootItem = this.isFlattenedReply ? this.items[1] : this.items[0]
|
|
||||||
return `slice-${rootItem.post.uri}-${
|
|
||||||
rootItem.reason?.indexedAt || rootItem.post.indexedAt
|
|
||||||
}`
|
|
||||||
}
|
|
||||||
|
|
||||||
get uri() {
|
get uri() {
|
||||||
if (this.isFlattenedReply) {
|
if (this.isFlattenedReply) {
|
||||||
|
@ -118,28 +111,34 @@ export class FeedViewPostsSlice {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NoopFeedTuner {
|
export class NoopFeedTuner {
|
||||||
reset() {}
|
private keyCounter = 0
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.keyCounter = 0
|
||||||
|
}
|
||||||
tune(
|
tune(
|
||||||
feed: FeedViewPost[],
|
feed: FeedViewPost[],
|
||||||
_tunerFns: FeedTunerFn[] = [],
|
|
||||||
_opts?: {dryRun: boolean; maintainOrder: boolean},
|
_opts?: {dryRun: boolean; maintainOrder: boolean},
|
||||||
): FeedViewPostsSlice[] {
|
): FeedViewPostsSlice[] {
|
||||||
return feed.map(item => new FeedViewPostsSlice([item]))
|
return feed.map(
|
||||||
|
item => new FeedViewPostsSlice([item], `slice-${this.keyCounter++}`),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FeedTuner {
|
export class FeedTuner {
|
||||||
|
private keyCounter = 0
|
||||||
seenUris: Set<string> = new Set()
|
seenUris: Set<string> = new Set()
|
||||||
|
|
||||||
constructor() {}
|
constructor(public tunerFns: FeedTunerFn[]) {}
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
|
this.keyCounter = 0
|
||||||
this.seenUris.clear()
|
this.seenUris.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
tune(
|
tune(
|
||||||
feed: FeedViewPost[],
|
feed: FeedViewPost[],
|
||||||
tunerFns: FeedTunerFn[] = [],
|
|
||||||
{dryRun, maintainOrder}: {dryRun: boolean; maintainOrder: boolean} = {
|
{dryRun, maintainOrder}: {dryRun: boolean; maintainOrder: boolean} = {
|
||||||
dryRun: false,
|
dryRun: false,
|
||||||
maintainOrder: false,
|
maintainOrder: false,
|
||||||
|
@ -148,7 +147,9 @@ export class FeedTuner {
|
||||||
let slices: FeedViewPostsSlice[] = []
|
let slices: FeedViewPostsSlice[] = []
|
||||||
|
|
||||||
if (maintainOrder) {
|
if (maintainOrder) {
|
||||||
slices = feed.map(item => new FeedViewPostsSlice([item]))
|
slices = feed.map(
|
||||||
|
item => new FeedViewPostsSlice([item], `slice-${this.keyCounter++}`),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
// arrange the posts into thread slices
|
// arrange the posts into thread slices
|
||||||
for (let i = feed.length - 1; i >= 0; i--) {
|
for (let i = feed.length - 1; i >= 0; i--) {
|
||||||
|
@ -164,12 +165,14 @@ export class FeedTuner {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
slices.unshift(new FeedViewPostsSlice([item]))
|
slices.unshift(
|
||||||
|
new FeedViewPostsSlice([item], `slice-${this.keyCounter++}`),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// run the custom tuners
|
// run the custom tuners
|
||||||
for (const tunerFn of tunerFns) {
|
for (const tunerFn of this.tunerFns) {
|
||||||
slices = tunerFn(this, slices.slice())
|
slices = tunerFn(this, slices.slice())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,15 @@
|
||||||
import {
|
import {
|
||||||
AppBskyFeedDefs,
|
AppBskyFeedDefs,
|
||||||
AppBskyFeedGetAuthorFeed as GetAuthorFeed,
|
AppBskyFeedGetAuthorFeed as GetAuthorFeed,
|
||||||
BskyAgent,
|
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
import {FeedAPI, FeedAPIResponse} from './types'
|
import {FeedAPI, FeedAPIResponse} from './types'
|
||||||
|
import {getAgent} from '#/state/session'
|
||||||
|
|
||||||
export class AuthorFeedAPI implements FeedAPI {
|
export class AuthorFeedAPI implements FeedAPI {
|
||||||
constructor(
|
constructor(public params: GetAuthorFeed.QueryParams) {}
|
||||||
public agent: BskyAgent,
|
|
||||||
public params: GetAuthorFeed.QueryParams,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
|
async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
|
||||||
const res = await this.agent.getAuthorFeed({
|
const res = await getAgent().getAuthorFeed({
|
||||||
...this.params,
|
...this.params,
|
||||||
limit: 1,
|
limit: 1,
|
||||||
})
|
})
|
||||||
|
@ -26,7 +23,7 @@ export class AuthorFeedAPI implements FeedAPI {
|
||||||
cursor: string | undefined
|
cursor: string | undefined
|
||||||
limit: number
|
limit: number
|
||||||
}): Promise<FeedAPIResponse> {
|
}): Promise<FeedAPIResponse> {
|
||||||
const res = await this.agent.getAuthorFeed({
|
const res = await getAgent().getAuthorFeed({
|
||||||
...this.params,
|
...this.params,
|
||||||
cursor,
|
cursor,
|
||||||
limit,
|
limit,
|
||||||
|
|
|
@ -1,18 +1,15 @@
|
||||||
import {
|
import {
|
||||||
AppBskyFeedDefs,
|
AppBskyFeedDefs,
|
||||||
AppBskyFeedGetFeed as GetCustomFeed,
|
AppBskyFeedGetFeed as GetCustomFeed,
|
||||||
BskyAgent,
|
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
import {FeedAPI, FeedAPIResponse} from './types'
|
import {FeedAPI, FeedAPIResponse} from './types'
|
||||||
|
import {getAgent} from '#/state/session'
|
||||||
|
|
||||||
export class CustomFeedAPI implements FeedAPI {
|
export class CustomFeedAPI implements FeedAPI {
|
||||||
constructor(
|
constructor(public params: GetCustomFeed.QueryParams) {}
|
||||||
public agent: BskyAgent,
|
|
||||||
public params: GetCustomFeed.QueryParams,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
|
async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
|
||||||
const res = await this.agent.app.bsky.feed.getFeed({
|
const res = await getAgent().app.bsky.feed.getFeed({
|
||||||
...this.params,
|
...this.params,
|
||||||
limit: 1,
|
limit: 1,
|
||||||
})
|
})
|
||||||
|
@ -26,7 +23,7 @@ export class CustomFeedAPI implements FeedAPI {
|
||||||
cursor: string | undefined
|
cursor: string | undefined
|
||||||
limit: number
|
limit: number
|
||||||
}): Promise<FeedAPIResponse> {
|
}): Promise<FeedAPIResponse> {
|
||||||
const res = await this.agent.app.bsky.feed.getFeed({
|
const res = await getAgent().app.bsky.feed.getFeed({
|
||||||
...this.params,
|
...this.params,
|
||||||
cursor,
|
cursor,
|
||||||
limit,
|
limit,
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import {AppBskyFeedDefs, BskyAgent} from '@atproto/api'
|
import {AppBskyFeedDefs} from '@atproto/api'
|
||||||
import {FeedAPI, FeedAPIResponse} from './types'
|
import {FeedAPI, FeedAPIResponse} from './types'
|
||||||
|
import {getAgent} from '#/state/session'
|
||||||
|
|
||||||
export class FollowingFeedAPI implements FeedAPI {
|
export class FollowingFeedAPI implements FeedAPI {
|
||||||
constructor(public agent: BskyAgent) {}
|
constructor() {}
|
||||||
|
|
||||||
async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
|
async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
|
||||||
const res = await this.agent.getTimeline({
|
const res = await getAgent().getTimeline({
|
||||||
limit: 1,
|
limit: 1,
|
||||||
})
|
})
|
||||||
return res.data.feed[0]
|
return res.data.feed[0]
|
||||||
|
@ -18,7 +19,7 @@ export class FollowingFeedAPI implements FeedAPI {
|
||||||
cursor: string | undefined
|
cursor: string | undefined
|
||||||
limit: number
|
limit: number
|
||||||
}): Promise<FeedAPIResponse> {
|
}): Promise<FeedAPIResponse> {
|
||||||
const res = await this.agent.getTimeline({
|
const res = await getAgent().getTimeline({
|
||||||
cursor,
|
cursor,
|
||||||
limit,
|
limit,
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,18 +1,15 @@
|
||||||
import {
|
import {
|
||||||
AppBskyFeedDefs,
|
AppBskyFeedDefs,
|
||||||
AppBskyFeedGetActorLikes as GetActorLikes,
|
AppBskyFeedGetActorLikes as GetActorLikes,
|
||||||
BskyAgent,
|
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
import {FeedAPI, FeedAPIResponse} from './types'
|
import {FeedAPI, FeedAPIResponse} from './types'
|
||||||
|
import {getAgent} from '#/state/session'
|
||||||
|
|
||||||
export class LikesFeedAPI implements FeedAPI {
|
export class LikesFeedAPI implements FeedAPI {
|
||||||
constructor(
|
constructor(public params: GetActorLikes.QueryParams) {}
|
||||||
public agent: BskyAgent,
|
|
||||||
public params: GetActorLikes.QueryParams,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
|
async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
|
||||||
const res = await this.agent.getActorLikes({
|
const res = await getAgent().getActorLikes({
|
||||||
...this.params,
|
...this.params,
|
||||||
limit: 1,
|
limit: 1,
|
||||||
})
|
})
|
||||||
|
@ -26,7 +23,7 @@ export class LikesFeedAPI implements FeedAPI {
|
||||||
cursor: string | undefined
|
cursor: string | undefined
|
||||||
limit: number
|
limit: number
|
||||||
}): Promise<FeedAPIResponse> {
|
}): Promise<FeedAPIResponse> {
|
||||||
const res = await this.agent.getActorLikes({
|
const res = await getAgent().getActorLikes({
|
||||||
...this.params,
|
...this.params,
|
||||||
cursor,
|
cursor,
|
||||||
limit,
|
limit,
|
||||||
|
|
|
@ -1,18 +1,15 @@
|
||||||
import {
|
import {
|
||||||
AppBskyFeedDefs,
|
AppBskyFeedDefs,
|
||||||
AppBskyFeedGetListFeed as GetListFeed,
|
AppBskyFeedGetListFeed as GetListFeed,
|
||||||
BskyAgent,
|
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
import {FeedAPI, FeedAPIResponse} from './types'
|
import {FeedAPI, FeedAPIResponse} from './types'
|
||||||
|
import {getAgent} from '#/state/session'
|
||||||
|
|
||||||
export class ListFeedAPI implements FeedAPI {
|
export class ListFeedAPI implements FeedAPI {
|
||||||
constructor(
|
constructor(public params: GetListFeed.QueryParams) {}
|
||||||
public agent: BskyAgent,
|
|
||||||
public params: GetListFeed.QueryParams,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
|
async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
|
||||||
const res = await this.agent.app.bsky.feed.getListFeed({
|
const res = await getAgent().app.bsky.feed.getListFeed({
|
||||||
...this.params,
|
...this.params,
|
||||||
limit: 1,
|
limit: 1,
|
||||||
})
|
})
|
||||||
|
@ -26,7 +23,7 @@ export class ListFeedAPI implements FeedAPI {
|
||||||
cursor: string | undefined
|
cursor: string | undefined
|
||||||
limit: number
|
limit: number
|
||||||
}): Promise<FeedAPIResponse> {
|
}): Promise<FeedAPIResponse> {
|
||||||
const res = await this.agent.app.bsky.feed.getListFeed({
|
const res = await getAgent().app.bsky.feed.getListFeed({
|
||||||
...this.params,
|
...this.params,
|
||||||
cursor,
|
cursor,
|
||||||
limit,
|
limit,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {AppBskyFeedDefs, AppBskyFeedGetTimeline, BskyAgent} from '@atproto/api'
|
import {AppBskyFeedDefs, AppBskyFeedGetTimeline} from '@atproto/api'
|
||||||
import shuffle from 'lodash.shuffle'
|
import shuffle from 'lodash.shuffle'
|
||||||
import {timeout} from 'lib/async/timeout'
|
import {timeout} from 'lib/async/timeout'
|
||||||
import {bundleAsync} from 'lib/async/bundle'
|
import {bundleAsync} from 'lib/async/bundle'
|
||||||
|
@ -7,6 +7,7 @@ import {FeedTuner} from '../feed-manip'
|
||||||
import {FeedAPI, FeedAPIResponse, ReasonFeedSource} from './types'
|
import {FeedAPI, FeedAPIResponse, ReasonFeedSource} from './types'
|
||||||
import {FeedParams} from '#/state/queries/post-feed'
|
import {FeedParams} from '#/state/queries/post-feed'
|
||||||
import {FeedTunerFn} from '../feed-manip'
|
import {FeedTunerFn} from '../feed-manip'
|
||||||
|
import {getAgent} from '#/state/session'
|
||||||
|
|
||||||
const REQUEST_WAIT_MS = 500 // 500ms
|
const REQUEST_WAIT_MS = 500 // 500ms
|
||||||
const POST_AGE_CUTOFF = 60e3 * 60 * 24 // 24hours
|
const POST_AGE_CUTOFF = 60e3 * 60 * 24 // 24hours
|
||||||
|
@ -18,16 +19,12 @@ export class MergeFeedAPI implements FeedAPI {
|
||||||
itemCursor = 0
|
itemCursor = 0
|
||||||
sampleCursor = 0
|
sampleCursor = 0
|
||||||
|
|
||||||
constructor(
|
constructor(public params: FeedParams, public feedTuners: FeedTunerFn[]) {
|
||||||
public agent: BskyAgent,
|
this.following = new MergeFeedSource_Following(this.feedTuners)
|
||||||
public params: FeedParams,
|
|
||||||
public feedTuners: FeedTunerFn[],
|
|
||||||
) {
|
|
||||||
this.following = new MergeFeedSource_Following(this.agent, this.feedTuners)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
this.following = new MergeFeedSource_Following(this.agent, this.feedTuners)
|
this.following = new MergeFeedSource_Following(this.feedTuners)
|
||||||
this.customFeeds = [] // just empty the array, they will be captured in _fetchNext()
|
this.customFeeds = [] // just empty the array, they will be captured in _fetchNext()
|
||||||
this.feedCursor = 0
|
this.feedCursor = 0
|
||||||
this.itemCursor = 0
|
this.itemCursor = 0
|
||||||
|
@ -35,8 +32,7 @@ export class MergeFeedAPI implements FeedAPI {
|
||||||
if (this.params.mergeFeedEnabled && this.params.mergeFeedSources) {
|
if (this.params.mergeFeedEnabled && this.params.mergeFeedSources) {
|
||||||
this.customFeeds = shuffle(
|
this.customFeeds = shuffle(
|
||||||
this.params.mergeFeedSources.map(
|
this.params.mergeFeedSources.map(
|
||||||
feedUri =>
|
feedUri => new MergeFeedSource_Custom(feedUri, this.feedTuners),
|
||||||
new MergeFeedSource_Custom(this.agent, feedUri, this.feedTuners),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -45,7 +41,7 @@ export class MergeFeedAPI implements FeedAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
|
async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> {
|
||||||
const res = await this.agent.getTimeline({
|
const res = await getAgent().getTimeline({
|
||||||
limit: 1,
|
limit: 1,
|
||||||
})
|
})
|
||||||
return res.data.feed[0]
|
return res.data.feed[0]
|
||||||
|
@ -137,7 +133,7 @@ class MergeFeedSource {
|
||||||
queue: AppBskyFeedDefs.FeedViewPost[] = []
|
queue: AppBskyFeedDefs.FeedViewPost[] = []
|
||||||
hasMore = true
|
hasMore = true
|
||||||
|
|
||||||
constructor(public agent: BskyAgent, public feedTuners: FeedTunerFn[]) {}
|
constructor(public feedTuners: FeedTunerFn[]) {}
|
||||||
|
|
||||||
get numReady() {
|
get numReady() {
|
||||||
return this.queue.length
|
return this.queue.length
|
||||||
|
@ -184,7 +180,7 @@ class MergeFeedSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
class MergeFeedSource_Following extends MergeFeedSource {
|
class MergeFeedSource_Following extends MergeFeedSource {
|
||||||
tuner = new FeedTuner()
|
tuner = new FeedTuner(this.feedTuners)
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
super.reset()
|
super.reset()
|
||||||
|
@ -199,9 +195,9 @@ class MergeFeedSource_Following extends MergeFeedSource {
|
||||||
cursor: string | undefined,
|
cursor: string | undefined,
|
||||||
limit: number,
|
limit: number,
|
||||||
): Promise<AppBskyFeedGetTimeline.Response> {
|
): Promise<AppBskyFeedGetTimeline.Response> {
|
||||||
const res = await this.agent.getTimeline({cursor, limit})
|
const res = await getAgent().getTimeline({cursor, limit})
|
||||||
// run the tuner pre-emptively to ensure better mixing
|
// run the tuner pre-emptively to ensure better mixing
|
||||||
const slices = this.tuner.tune(res.data.feed, this.feedTuners, {
|
const slices = this.tuner.tune(res.data.feed, {
|
||||||
dryRun: false,
|
dryRun: false,
|
||||||
maintainOrder: true,
|
maintainOrder: true,
|
||||||
})
|
})
|
||||||
|
@ -213,20 +209,16 @@ class MergeFeedSource_Following extends MergeFeedSource {
|
||||||
class MergeFeedSource_Custom extends MergeFeedSource {
|
class MergeFeedSource_Custom extends MergeFeedSource {
|
||||||
minDate: Date
|
minDate: Date
|
||||||
|
|
||||||
constructor(
|
constructor(public feedUri: string, public feedTuners: FeedTunerFn[]) {
|
||||||
public agent: BskyAgent,
|
super(feedTuners)
|
||||||
public feedUri: string,
|
|
||||||
public feedTuners: FeedTunerFn[],
|
|
||||||
) {
|
|
||||||
super(agent, feedTuners)
|
|
||||||
this.sourceInfo = {
|
this.sourceInfo = {
|
||||||
$type: 'reasonFeedSource',
|
$type: 'reasonFeedSource',
|
||||||
displayName: feedUri.split('/').pop() || '',
|
displayName: feedUri.split('/').pop() || '',
|
||||||
uri: feedUriToHref(feedUri),
|
uri: feedUriToHref(feedUri),
|
||||||
}
|
}
|
||||||
this.minDate = new Date(Date.now() - POST_AGE_CUTOFF)
|
this.minDate = new Date(Date.now() - POST_AGE_CUTOFF)
|
||||||
this.agent.app.bsky.feed
|
getAgent()
|
||||||
.getFeedGenerator({
|
.app.bsky.feed.getFeedGenerator({
|
||||||
feed: feedUri,
|
feed: feedUri,
|
||||||
})
|
})
|
||||||
.then(
|
.then(
|
||||||
|
@ -244,7 +236,7 @@ class MergeFeedSource_Custom extends MergeFeedSource {
|
||||||
limit: number,
|
limit: number,
|
||||||
): Promise<AppBskyFeedGetTimeline.Response> {
|
): Promise<AppBskyFeedGetTimeline.Response> {
|
||||||
try {
|
try {
|
||||||
const res = await this.agent.app.bsky.feed.getFeed({
|
const res = await getAgent().app.bsky.feed.getFeed({
|
||||||
cursor,
|
cursor,
|
||||||
limit,
|
limit,
|
||||||
feed: this.feedUri,
|
feed: this.feedUri,
|
||||||
|
|
|
@ -116,8 +116,8 @@ export async function DEFAULT_FEEDS(
|
||||||
} else {
|
} else {
|
||||||
// production
|
// production
|
||||||
return {
|
return {
|
||||||
pinned: [PROD_DEFAULT_FEED('whats-hot')],
|
pinned: [],
|
||||||
saved: [PROD_DEFAULT_FEED('whats-hot')],
|
saved: [],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,22 +7,35 @@ import {useAnalytics} from '#/lib/analytics/analytics'
|
||||||
import {useSessionApi, SessionAccount} from '#/state/session'
|
import {useSessionApi, SessionAccount} from '#/state/session'
|
||||||
import * as Toast from '#/view/com/util/Toast'
|
import * as Toast from '#/view/com/util/Toast'
|
||||||
import {useCloseAllActiveElements} from '#/state/util'
|
import {useCloseAllActiveElements} from '#/state/util'
|
||||||
|
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
||||||
|
|
||||||
export function useAccountSwitcher() {
|
export function useAccountSwitcher() {
|
||||||
const {track} = useAnalytics()
|
const {track} = useAnalytics()
|
||||||
const {selectAccount, clearCurrentAccount} = useSessionApi()
|
const {selectAccount, clearCurrentAccount} = useSessionApi()
|
||||||
const closeAllActiveElements = useCloseAllActiveElements()
|
const closeAllActiveElements = useCloseAllActiveElements()
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
|
const {setShowLoggedOut} = useLoggedOutViewControls()
|
||||||
|
|
||||||
const onPressSwitchAccount = useCallback(
|
const onPressSwitchAccount = useCallback(
|
||||||
async (acct: SessionAccount) => {
|
async (account: SessionAccount) => {
|
||||||
track('Settings:SwitchAccountButtonClicked')
|
track('Settings:SwitchAccountButtonClicked')
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (account.accessJwt) {
|
||||||
closeAllActiveElements()
|
closeAllActiveElements()
|
||||||
navigation.navigate(isWeb ? 'Home' : 'HomeTab')
|
navigation.navigate(isWeb ? 'Home' : 'HomeTab')
|
||||||
await selectAccount(acct)
|
await selectAccount(account)
|
||||||
Toast.show(`Signed in as ${acct.handle}`)
|
setTimeout(() => {
|
||||||
|
Toast.show(`Signed in as @${account.handle}`)
|
||||||
|
}, 100)
|
||||||
|
} else {
|
||||||
|
closeAllActiveElements()
|
||||||
|
setShowLoggedOut(true)
|
||||||
|
Toast.show(
|
||||||
|
`Please sign in as @${account.handle}`,
|
||||||
|
'circle-exclamation',
|
||||||
|
)
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Toast.show('Sorry! We need you to enter your password.')
|
Toast.show('Sorry! We need you to enter your password.')
|
||||||
clearCurrentAccount() // back user out to login
|
clearCurrentAccount() // back user out to login
|
||||||
|
@ -34,6 +47,7 @@ export function useAccountSwitcher() {
|
||||||
selectAccount,
|
selectAccount,
|
||||||
closeAllActiveElements,
|
closeAllActiveElements,
|
||||||
navigation,
|
navigation,
|
||||||
|
setShowLoggedOut,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@ export function init(queryClient: QueryClient) {
|
||||||
)
|
)
|
||||||
if (event.request.trigger.type === 'push') {
|
if (event.request.trigger.type === 'push') {
|
||||||
// refresh notifications in the background
|
// refresh notifications in the background
|
||||||
queryClient.invalidateQueries({queryKey: RQKEY_NOTIFS()})
|
queryClient.resetQueries({queryKey: RQKEY_NOTIFS()})
|
||||||
// handle payload-based deeplinks
|
// handle payload-based deeplinks
|
||||||
let payload
|
let payload
|
||||||
if (isIOS) {
|
if (isIOS) {
|
||||||
|
@ -121,7 +121,7 @@ export function init(queryClient: QueryClient) {
|
||||||
logger.DebugContext.notifications,
|
logger.DebugContext.notifications,
|
||||||
)
|
)
|
||||||
track('Notificatons:OpenApp')
|
track('Notificatons:OpenApp')
|
||||||
queryClient.invalidateQueries({queryKey: RQKEY_NOTIFS()})
|
queryClient.resetQueries({queryKey: RQKEY_NOTIFS()})
|
||||||
resetToTab('NotificationsTab') // open notifications tab
|
resetToTab('NotificationsTab') // open notifications tab
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -8,6 +8,15 @@ export const queryClient = new QueryClient({
|
||||||
// so we NEVER want to enable this
|
// so we NEVER want to enable this
|
||||||
// -prf
|
// -prf
|
||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
|
// Structural sharing between responses makes it impossible to rely on
|
||||||
|
// "first seen" timestamps on objects to determine if they're fresh.
|
||||||
|
// Disable this optimization so that we can rely on "first seen" timestamps.
|
||||||
|
structuralSharing: false,
|
||||||
|
// We don't want to retry queries by default, because in most cases we
|
||||||
|
// want to fail early and show a response to the user. There are
|
||||||
|
// exceptions, and those can be made on a per-query basis. For others, we
|
||||||
|
// should give users controls to retry.
|
||||||
|
retry: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,8 +1,46 @@
|
||||||
|
/**
|
||||||
|
* Importing these separately from `platform/detection` and `lib/app-info` to
|
||||||
|
* avoid future conflicts and/or circular deps
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {Platform} from 'react-native'
|
||||||
|
import app from 'react-native-version-number'
|
||||||
|
import * as info from 'expo-updates'
|
||||||
import {init} from 'sentry-expo'
|
import {init} from 'sentry-expo'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches the build profile `channel` props in `eas.json`
|
||||||
|
*/
|
||||||
|
const buildChannel = (info.channel || 'development') as
|
||||||
|
| 'development'
|
||||||
|
| 'preview'
|
||||||
|
| 'production'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Examples:
|
||||||
|
* - `dev`
|
||||||
|
* - `1.57.0`
|
||||||
|
*/
|
||||||
|
const release = app.appVersion ?? 'dev'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Examples:
|
||||||
|
* - `web.dev`
|
||||||
|
* - `ios.dev`
|
||||||
|
* - `android.dev`
|
||||||
|
* - `web.1.57.0`
|
||||||
|
* - `ios.1.57.0.3`
|
||||||
|
* - `android.1.57.0.46`
|
||||||
|
*/
|
||||||
|
const dist = `${Platform.OS}.${release}${
|
||||||
|
app.buildVersion ? `.${app.buildVersion}` : ''
|
||||||
|
}`
|
||||||
|
|
||||||
init({
|
init({
|
||||||
dsn: 'https://05bc3789bf994b81bd7ce20c86ccd3ae@o4505071687041024.ingest.sentry.io/4505071690514432',
|
dsn: 'https://05bc3789bf994b81bd7ce20c86ccd3ae@o4505071687041024.ingest.sentry.io/4505071690514432',
|
||||||
enableInExpoDevelopment: false, // if true, Sentry will try to send events/errors in development mode.
|
|
||||||
debug: false, // If `true`, Sentry will try to print out useful debugging information if something goes wrong with sending the event. Set it to `false` in production
|
debug: false, // If `true`, Sentry will try to print out useful debugging information if something goes wrong with sending the event. Set it to `false` in production
|
||||||
environment: __DEV__ ? 'development' : 'production', // Set the environment
|
enableInExpoDevelopment: true,
|
||||||
|
environment: buildChannel,
|
||||||
|
dist,
|
||||||
|
release,
|
||||||
})
|
})
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -21,12 +21,6 @@ msgstr ""
|
||||||
#~ msgid ". This warning is only available for posts with media attached."
|
#~ msgid ". This warning is only available for posts with media attached."
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:410
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:158
|
|
||||||
#: src/view/shell/Drawer.tsx:527
|
|
||||||
msgid "{0, plural, one {# invite code available} other {# invite codes available}}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/view/com/modals/Repost.tsx:44
|
#: src/view/com/modals/Repost.tsx:44
|
||||||
msgid "{0}"
|
msgid "{0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -35,11 +29,6 @@ msgstr ""
|
||||||
msgid "{0} {purposeLabel} List"
|
msgid "{0} {purposeLabel} List"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:141
|
|
||||||
#: src/view/shell/Drawer.tsx:504
|
|
||||||
msgid "{invitesAvailable, plural, one {Invite codes: # available} other {Invite codes: # available}}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/view/screens/Search/Search.tsx:86
|
#: src/view/screens/Search/Search.tsx:86
|
||||||
msgid "{message}"
|
msgid "{message}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -61,12 +50,12 @@ msgid "A new version of the app is available. Please update to continue using th
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/modals/EditImage.tsx:299
|
#: src/view/com/modals/EditImage.tsx:299
|
||||||
#: src/view/screens/Settings.tsx:422
|
#: src/view/screens/Settings.tsx:410
|
||||||
msgid "Accessibility"
|
msgid "Accessibility"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/login/LoginForm.tsx:161
|
#: src/view/com/auth/login/LoginForm.tsx:161
|
||||||
#: src/view/screens/Settings.tsx:289
|
#: src/view/screens/Settings.tsx:288
|
||||||
msgid "Account"
|
msgid "Account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -88,8 +77,8 @@ msgstr ""
|
||||||
msgid "Add a user to this list"
|
msgid "Add a user to this list"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:358
|
#: src/view/screens/Settings.tsx:357
|
||||||
#: src/view/screens/Settings.tsx:367
|
#: src/view/screens/Settings.tsx:366
|
||||||
msgid "Add account"
|
msgid "Add account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -140,7 +129,7 @@ msgstr ""
|
||||||
msgid "Adult Content"
|
msgid "Adult Content"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:574
|
#: src/view/screens/Settings.tsx:562
|
||||||
msgid "Advanced"
|
msgid "Advanced"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -172,7 +161,7 @@ msgstr ""
|
||||||
msgid "App Language"
|
msgid "App Language"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:594
|
#: src/view/screens/Settings.tsx:582
|
||||||
msgid "App passwords"
|
msgid "App passwords"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -180,7 +169,7 @@ msgstr ""
|
||||||
msgid "App Passwords"
|
msgid "App Passwords"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:437
|
#: src/view/screens/Settings.tsx:425
|
||||||
msgid "Appearance"
|
msgid "Appearance"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -205,7 +194,7 @@ msgid "Artistic or non-erotic nudity."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/create/CreateAccount.tsx:145
|
#: src/view/com/auth/create/CreateAccount.tsx:145
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:122
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:151
|
||||||
#: src/view/com/auth/login/ForgotPasswordForm.tsx:166
|
#: src/view/com/auth/login/ForgotPasswordForm.tsx:166
|
||||||
#: src/view/com/auth/login/LoginForm.tsx:251
|
#: src/view/com/auth/login/LoginForm.tsx:251
|
||||||
#: src/view/com/auth/login/SetNewPasswordForm.tsx:148
|
#: src/view/com/auth/login/SetNewPasswordForm.tsx:148
|
||||||
|
@ -217,7 +206,7 @@ msgstr ""
|
||||||
msgid "Back"
|
msgid "Back"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:466
|
#: src/view/screens/Settings.tsx:454
|
||||||
msgid "Basics"
|
msgid "Basics"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -226,7 +215,7 @@ msgstr ""
|
||||||
msgid "Birthday"
|
msgid "Birthday"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:315
|
#: src/view/screens/Settings.tsx:314
|
||||||
msgid "Birthday:"
|
msgid "Birthday:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -291,7 +280,7 @@ msgstr ""
|
||||||
msgid "Bluesky.Social"
|
msgid "Bluesky.Social"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:723
|
#: src/view/screens/Settings.tsx:711
|
||||||
msgid "Build version {0} {1}"
|
msgid "Build version {0} {1}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -359,12 +348,12 @@ msgstr ""
|
||||||
msgid "Cancel waitlist signup"
|
msgid "Cancel waitlist signup"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:309
|
#: src/view/screens/Settings.tsx:308
|
||||||
msgid "Change"
|
msgid "Change"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:606
|
#: src/view/screens/Settings.tsx:594
|
||||||
#: src/view/screens/Settings.tsx:615
|
#: src/view/screens/Settings.tsx:603
|
||||||
msgid "Change handle"
|
msgid "Change handle"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -408,19 +397,19 @@ msgstr ""
|
||||||
msgid "Choose your password"
|
msgid "Choose your password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:699
|
#: src/view/screens/Settings.tsx:687
|
||||||
msgid "Clear all legacy storage data"
|
msgid "Clear all legacy storage data"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:701
|
#: src/view/screens/Settings.tsx:689
|
||||||
msgid "Clear all legacy storage data (restart after this)"
|
msgid "Clear all legacy storage data (restart after this)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:711
|
#: src/view/screens/Settings.tsx:699
|
||||||
msgid "Clear all storage data"
|
msgid "Clear all storage data"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:713
|
#: src/view/screens/Settings.tsx:701
|
||||||
msgid "Clear all storage data (restart after this)"
|
msgid "Clear all storage data (restart after this)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -561,7 +550,7 @@ msgstr ""
|
||||||
msgid "Custom domain"
|
msgid "Custom domain"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:620
|
#: src/view/screens/Settings.tsx:608
|
||||||
msgid "Danger Zone"
|
msgid "Danger Zone"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -569,7 +558,7 @@ msgstr ""
|
||||||
#~ msgid "Dark"
|
#~ msgid "Dark"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:627
|
#: src/view/screens/Settings.tsx:615
|
||||||
msgid "Delete account"
|
msgid "Delete account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -591,7 +580,7 @@ msgstr ""
|
||||||
msgid "Delete my account"
|
msgid "Delete my account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:637
|
#: src/view/screens/Settings.tsx:625
|
||||||
msgid "Delete my account…"
|
msgid "Delete my account…"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -618,7 +607,7 @@ msgstr ""
|
||||||
msgid "Dev Server"
|
msgid "Dev Server"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:642
|
#: src/view/screens/Settings.tsx:630
|
||||||
msgid "Developer Tools"
|
msgid "Developer Tools"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -677,7 +666,7 @@ msgid "Edit list details"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Feeds.tsx:367
|
#: src/view/screens/Feeds.tsx:367
|
||||||
#: src/view/screens/SavedFeeds.tsx:75
|
#: src/view/screens/SavedFeeds.tsx:85
|
||||||
msgid "Edit My Feeds"
|
msgid "Edit My Feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -712,7 +701,7 @@ msgstr ""
|
||||||
msgid "Email Updated"
|
msgid "Email Updated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:293
|
#: src/view/screens/Settings.tsx:292
|
||||||
msgid "Email:"
|
msgid "Email:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -757,7 +746,7 @@ msgstr ""
|
||||||
msgid "Failed to load recommended feeds"
|
msgid "Failed to load recommended feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Feeds.tsx:558
|
#: src/view/screens/Feeds.tsx:559
|
||||||
msgid "Feed offline"
|
msgid "Feed offline"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -765,12 +754,12 @@ msgstr ""
|
||||||
msgid "Feed Preferences"
|
msgid "Feed Preferences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:64
|
#: src/view/shell/desktop/RightNav.tsx:65
|
||||||
#: src/view/shell/Drawer.tsx:411
|
#: src/view/shell/Drawer.tsx:411
|
||||||
msgid "Feedback"
|
msgid "Feedback"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Feeds.tsx:474
|
#: src/view/screens/Feeds.tsx:475
|
||||||
#: src/view/shell/bottom-bar/BottomBar.tsx:169
|
#: src/view/shell/bottom-bar/BottomBar.tsx:169
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:342
|
#: src/view/shell/desktop/LeftNav.tsx:342
|
||||||
#: src/view/shell/Drawer.tsx:328
|
#: src/view/shell/Drawer.tsx:328
|
||||||
|
@ -782,7 +771,7 @@ msgstr ""
|
||||||
msgid "Feeds are created by users to curate content. Choose some feeds that you find interesting."
|
msgid "Feeds are created by users to curate content. Choose some feeds that you find interesting."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:132
|
#: src/view/screens/SavedFeeds.tsx:156
|
||||||
msgid "Feeds are custom algorithms that users build with a little coding expertise. <0/> for more information."
|
msgid "Feeds are custom algorithms that users build with a little coding expertise. <0/> for more information."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -884,7 +873,7 @@ msgstr ""
|
||||||
msgid "Handle"
|
msgid "Handle"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:93
|
#: src/view/shell/desktop/RightNav.tsx:94
|
||||||
#: src/view/shell/Drawer.tsx:421
|
#: src/view/shell/Drawer.tsx:421
|
||||||
msgid "Help"
|
msgid "Help"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -901,6 +890,26 @@ msgstr ""
|
||||||
msgid "Hide user list"
|
msgid "Hide user list"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:101
|
||||||
|
msgid "Hmm, some kind of issue occured when contacting the feed server. Please let the feed owner know about this issue."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:89
|
||||||
|
msgid "Hmm, the feed server appears to be misconfigured. Please let the feed owner know about this issue."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:95
|
||||||
|
msgid "Hmm, the feed server appears to be offline. Please let the feed owner know about this issue."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:92
|
||||||
|
msgid "Hmm, the feed server gave a bad response. Please let the feed owner know about this issue."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:86
|
||||||
|
msgid "Hmmm, we're having trouble finding this feed. It may have been deleted."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/bottom-bar/BottomBar.tsx:125
|
#: src/view/shell/bottom-bar/BottomBar.tsx:125
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:306
|
#: src/view/shell/desktop/LeftNav.tsx:306
|
||||||
#: src/view/shell/Drawer.tsx:275
|
#: src/view/shell/Drawer.tsx:275
|
||||||
|
@ -908,9 +917,9 @@ msgstr ""
|
||||||
msgid "Home"
|
msgid "Home"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/pager/FeedsTabBarMobile.tsx:71
|
#: src/view/com/pager/FeedsTabBarMobile.tsx:99
|
||||||
#: src/view/screens/PreferencesHomeFeed.tsx:95
|
#: src/view/screens/PreferencesHomeFeed.tsx:95
|
||||||
#: src/view/screens/Settings.tsx:486
|
#: src/view/screens/Settings.tsx:474
|
||||||
msgid "Home Feed Preferences"
|
msgid "Home Feed Preferences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -953,12 +962,12 @@ msgstr ""
|
||||||
msgid "Invalid username or password"
|
msgid "Invalid username or password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:386
|
#: src/view/screens/Settings.tsx:385
|
||||||
msgid "Invite"
|
msgid "Invite"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/modals/InviteCodes.tsx:91
|
#: src/view/com/modals/InviteCodes.tsx:91
|
||||||
#: src/view/screens/Settings.tsx:374
|
#: src/view/screens/Settings.tsx:373
|
||||||
msgid "Invite a Friend"
|
msgid "Invite a Friend"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -991,7 +1000,7 @@ msgstr ""
|
||||||
msgid "Language Settings"
|
msgid "Language Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:546
|
#: src/view/screens/Settings.tsx:534
|
||||||
msgid "Languages"
|
msgid "Languages"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1031,7 +1040,7 @@ msgstr ""
|
||||||
#~ msgid "Light"
|
#~ msgid "Light"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/ProfileFeed.tsx:625
|
#: src/view/screens/ProfileFeed.tsx:626
|
||||||
msgid "Like this feed"
|
msgid "Like this feed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1059,7 +1068,7 @@ msgstr ""
|
||||||
msgid "Load more posts"
|
msgid "Load more posts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Notifications.tsx:120
|
#: src/view/screens/Notifications.tsx:130
|
||||||
msgid "Load new notifications"
|
msgid "Load new notifications"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1075,11 +1084,11 @@ msgstr ""
|
||||||
msgid "Local dev server"
|
msgid "Local dev server"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:104
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:133
|
||||||
msgid "Login to account that is not listed"
|
msgid "Login to account that is not listed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/ProfileFeed.tsx:477
|
#: src/view/screens/ProfileFeed.tsx:478
|
||||||
msgid "Looks like this feed is only available to users with a Bluesky account. Please sign up or sign in to view this feed!"
|
msgid "Looks like this feed is only available to users with a Bluesky account. Please sign up or sign in to view this feed!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1092,7 +1101,7 @@ msgid "Menu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Moderation.tsx:51
|
#: src/view/screens/Moderation.tsx:51
|
||||||
#: src/view/screens/Settings.tsx:568
|
#: src/view/screens/Settings.tsx:556
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:400
|
#: src/view/shell/desktop/LeftNav.tsx:400
|
||||||
#: src/view/shell/Drawer.tsx:346
|
#: src/view/shell/Drawer.tsx:346
|
||||||
#: src/view/shell/Drawer.tsx:347
|
#: src/view/shell/Drawer.tsx:347
|
||||||
|
@ -1108,7 +1117,7 @@ msgid "More feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/profile/ProfileHeader.tsx:506
|
#: src/view/com/profile/ProfileHeader.tsx:506
|
||||||
#: src/view/screens/ProfileFeed.tsx:367
|
#: src/view/screens/ProfileFeed.tsx:368
|
||||||
#: src/view/screens/ProfileList.tsx:506
|
#: src/view/screens/ProfileList.tsx:506
|
||||||
msgid "More options"
|
msgid "More options"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1161,7 +1170,7 @@ msgstr ""
|
||||||
msgid "My Profile"
|
msgid "My Profile"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:525
|
#: src/view/screens/Settings.tsx:513
|
||||||
msgid "My Saved Feeds"
|
msgid "My Saved Feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1179,9 +1188,9 @@ msgid "New"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/feeds/FeedPage.tsx:187
|
#: src/view/com/feeds/FeedPage.tsx:187
|
||||||
#: src/view/screens/Feeds.tsx:509
|
#: src/view/screens/Feeds.tsx:510
|
||||||
#: src/view/screens/Profile.tsx:380
|
#: src/view/screens/Profile.tsx:381
|
||||||
#: src/view/screens/ProfileFeed.tsx:447
|
#: src/view/screens/ProfileFeed.tsx:448
|
||||||
#: src/view/screens/ProfileList.tsx:199
|
#: src/view/screens/ProfileList.tsx:199
|
||||||
#: src/view/screens/ProfileList.tsx:231
|
#: src/view/screens/ProfileList.tsx:231
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:255
|
#: src/view/shell/desktop/LeftNav.tsx:255
|
||||||
|
@ -1212,7 +1221,7 @@ msgstr ""
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/ProfileFeed.tsx:618
|
#: src/view/screens/ProfileFeed.tsx:619
|
||||||
#: src/view/screens/ProfileList.tsx:632
|
#: src/view/screens/ProfileList.tsx:632
|
||||||
msgid "No description"
|
msgid "No description"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1221,7 +1230,7 @@ msgstr ""
|
||||||
msgid "No result"
|
msgid "No result"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Feeds.tsx:451
|
#: src/view/screens/Feeds.tsx:452
|
||||||
msgid "No results found for \"{query}\""
|
msgid "No results found for \"{query}\""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1246,8 +1255,8 @@ msgstr ""
|
||||||
msgid "Not Applicable."
|
msgid "Not Applicable."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Notifications.tsx:87
|
#: src/view/screens/Notifications.tsx:97
|
||||||
#: src/view/screens/Notifications.tsx:111
|
#: src/view/screens/Notifications.tsx:121
|
||||||
#: src/view/shell/bottom-bar/BottomBar.tsx:196
|
#: src/view/shell/bottom-bar/BottomBar.tsx:196
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:364
|
#: src/view/shell/desktop/LeftNav.tsx:364
|
||||||
#: src/view/shell/Drawer.tsx:299
|
#: src/view/shell/Drawer.tsx:299
|
||||||
|
@ -1267,52 +1276,47 @@ msgstr ""
|
||||||
msgid "One or more images is missing alt text."
|
msgid "One or more images is missing alt text."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/pager/FeedsTabBarMobile.tsx:51
|
#: src/view/com/pager/FeedsTabBarMobile.tsx:79
|
||||||
msgid "Open navigation"
|
msgid "Open navigation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:538
|
#: src/view/screens/Settings.tsx:526
|
||||||
msgid "Opens configurable language settings"
|
msgid "Opens configurable language settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:146
|
|
||||||
#: src/view/shell/Drawer.tsx:509
|
|
||||||
msgid "Opens list of invite codes"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/view/com/modals/ChangeHandle.tsx:279
|
#: src/view/com/modals/ChangeHandle.tsx:279
|
||||||
msgid "Opens modal for using custom domain"
|
msgid "Opens modal for using custom domain"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:563
|
#: src/view/screens/Settings.tsx:551
|
||||||
msgid "Opens moderation settings"
|
msgid "Opens moderation settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:519
|
#: src/view/screens/Settings.tsx:507
|
||||||
msgid "Opens screen with all saved feeds"
|
msgid "Opens screen with all saved feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:586
|
#: src/view/screens/Settings.tsx:574
|
||||||
msgid "Opens the app password settings page"
|
msgid "Opens the app password settings page"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:478
|
#: src/view/screens/Settings.tsx:466
|
||||||
msgid "Opens the home feed preferences"
|
msgid "Opens the home feed preferences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:669
|
#: src/view/screens/Settings.tsx:657
|
||||||
msgid "Opens the storybook page"
|
msgid "Opens the storybook page"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:649
|
#: src/view/screens/Settings.tsx:637
|
||||||
msgid "Opens the system log page"
|
msgid "Opens the system log page"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:499
|
#: src/view/screens/Settings.tsx:487
|
||||||
msgid "Opens the threads preferences"
|
msgid "Opens the threads preferences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:109
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:138
|
||||||
msgid "Other account"
|
msgid "Other account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1349,7 +1353,7 @@ msgstr ""
|
||||||
msgid "Pictures meant for adults."
|
msgid "Pictures meant for adults."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:79
|
#: src/view/screens/SavedFeeds.tsx:89
|
||||||
msgid "Pinned Feeds"
|
msgid "Pinned Feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1415,7 +1419,7 @@ msgstr ""
|
||||||
msgid "Prioritize Your Follows"
|
msgid "Prioritize Your Follows"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:75
|
#: src/view/shell/desktop/RightNav.tsx:76
|
||||||
msgid "Privacy"
|
msgid "Privacy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1434,7 +1438,7 @@ msgstr ""
|
||||||
msgid "Profile"
|
msgid "Profile"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:794
|
#: src/view/screens/Settings.tsx:782
|
||||||
msgid "Protect your account by verifying your email."
|
msgid "Protect your account by verifying your email."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1476,7 +1480,7 @@ msgstr ""
|
||||||
msgid "Remove"
|
msgid "Remove"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/feeds/FeedSourceCard.tsx:92
|
#: src/view/com/feeds/FeedSourceCard.tsx:108
|
||||||
msgid "Remove {0} from my feeds?"
|
msgid "Remove {0} from my feeds?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1484,11 +1488,11 @@ msgstr ""
|
||||||
msgid "Remove account"
|
msgid "Remove account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/posts/FeedErrorMessage.tsx:106
|
#: src/view/com/posts/FeedErrorMessage.tsx:118
|
||||||
msgid "Remove feed"
|
msgid "Remove feed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/feeds/FeedSourceCard.tsx:91
|
#: src/view/com/feeds/FeedSourceCard.tsx:107
|
||||||
#: src/view/screens/ProfileFeed.tsx:278
|
#: src/view/screens/ProfileFeed.tsx:278
|
||||||
msgid "Remove from my feeds"
|
msgid "Remove from my feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1501,7 +1505,7 @@ msgstr ""
|
||||||
msgid "Remove image preview"
|
msgid "Remove image preview"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/posts/FeedErrorMessage.tsx:107
|
#: src/view/com/posts/FeedErrorMessage.tsx:119
|
||||||
msgid "Remove this feed from your saved feeds?"
|
msgid "Remove this feed from your saved feeds?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1565,7 +1569,7 @@ msgstr ""
|
||||||
msgid "Reset code"
|
msgid "Reset code"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:691
|
#: src/view/screens/Settings.tsx:679
|
||||||
msgid "Reset onboarding state"
|
msgid "Reset onboarding state"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1573,15 +1577,15 @@ msgstr ""
|
||||||
msgid "Reset password"
|
msgid "Reset password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:681
|
#: src/view/screens/Settings.tsx:669
|
||||||
msgid "Reset preferences state"
|
msgid "Reset preferences state"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:689
|
#: src/view/screens/Settings.tsx:677
|
||||||
msgid "Resets the onboarding state"
|
msgid "Resets the onboarding state"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:679
|
#: src/view/screens/Settings.tsx:667
|
||||||
msgid "Resets the preferences state"
|
msgid "Resets the preferences state"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1628,7 +1632,7 @@ msgstr ""
|
||||||
msgid "Save image crop"
|
msgid "Save image crop"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:105
|
#: src/view/screens/SavedFeeds.tsx:122
|
||||||
msgid "Saved Feeds"
|
msgid "Saved Feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1726,7 +1730,7 @@ msgstr ""
|
||||||
msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your following feed. This is an experimental feature."
|
msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your following feed. This is an experimental feature."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:280
|
#: src/view/screens/Settings.tsx:279
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:436
|
#: src/view/shell/desktop/LeftNav.tsx:436
|
||||||
#: src/view/shell/Drawer.tsx:380
|
#: src/view/shell/Drawer.tsx:380
|
||||||
#: src/view/shell/Drawer.tsx:381
|
#: src/view/shell/Drawer.tsx:381
|
||||||
|
@ -1751,7 +1755,7 @@ msgstr ""
|
||||||
#~ msgid "Share link"
|
#~ msgid "Share link"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:319
|
#: src/view/screens/Settings.tsx:318
|
||||||
msgid "Show"
|
msgid "Show"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1795,11 +1799,11 @@ msgstr ""
|
||||||
msgid "Sign In"
|
msgid "Sign In"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:37
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:44
|
||||||
msgid "Sign in as {0}"
|
msgid "Sign in as {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:94
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:118
|
||||||
#: src/view/com/auth/login/Login.tsx:100
|
#: src/view/com/auth/login/Login.tsx:100
|
||||||
msgid "Sign in as..."
|
msgid "Sign in as..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1823,7 +1827,7 @@ msgstr ""
|
||||||
msgid "Sign up or sign in to join the conversation"
|
msgid "Sign up or sign in to join the conversation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:330
|
#: src/view/screens/Settings.tsx:329
|
||||||
msgid "Signed in as"
|
msgid "Signed in as"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1848,11 +1852,11 @@ msgstr ""
|
||||||
msgid "Staging"
|
msgid "Staging"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:735
|
#: src/view/screens/Settings.tsx:723
|
||||||
msgid "Status page"
|
msgid "Status page"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:671
|
#: src/view/screens/Settings.tsx:659
|
||||||
msgid "Storybook"
|
msgid "Storybook"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1881,7 +1885,7 @@ msgstr ""
|
||||||
#~ msgid "System"
|
#~ msgid "System"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:651
|
#: src/view/screens/Settings.tsx:639
|
||||||
msgid "System log"
|
msgid "System log"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1889,7 +1893,7 @@ msgstr ""
|
||||||
msgid "Tall"
|
msgid "Tall"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:84
|
#: src/view/shell/desktop/RightNav.tsx:85
|
||||||
msgid "Terms"
|
msgid "Terms"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1962,7 +1966,7 @@ msgid "This warning is only available for posts with media attached."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/PreferencesThreads.tsx:53
|
#: src/view/screens/PreferencesThreads.tsx:53
|
||||||
#: src/view/screens/Settings.tsx:508
|
#: src/view/screens/Settings.tsx:496
|
||||||
msgid "Thread Preferences"
|
msgid "Thread Preferences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2069,15 +2073,15 @@ msgstr ""
|
||||||
msgid "Users"
|
msgid "Users"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:755
|
#: src/view/screens/Settings.tsx:743
|
||||||
msgid "Verify email"
|
msgid "Verify email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:780
|
#: src/view/screens/Settings.tsx:768
|
||||||
msgid "Verify my email"
|
msgid "Verify my email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:789
|
#: src/view/screens/Settings.tsx:777
|
||||||
msgid "Verify My Email"
|
msgid "Verify My Email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2102,6 +2106,10 @@ msgstr ""
|
||||||
msgid "We're so excited to have you join us!"
|
msgid "We're so excited to have you join us!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:98
|
||||||
|
msgid "We're sorry, but this content is not viewable without a Bluesky account."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Search/Search.tsx:236
|
#: src/view/screens/Search/Search.tsx:236
|
||||||
msgid "We're sorry, but your search could not be completed. Please try again in a few minutes."
|
msgid "We're sorry, but your search could not be completed. Please try again in a few minutes."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -2157,7 +2165,7 @@ msgstr ""
|
||||||
msgid "You don't have any invite codes yet! We'll send you some when you've been on Bluesky for a little longer."
|
msgid "You don't have any invite codes yet! We'll send you some when you've been on Bluesky for a little longer."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:92
|
#: src/view/screens/SavedFeeds.tsx:102
|
||||||
msgid "You don't have any pinned feeds."
|
msgid "You don't have any pinned feeds."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2165,7 +2173,7 @@ msgstr ""
|
||||||
msgid "You don't have any saved feeds!"
|
msgid "You don't have any saved feeds!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:118
|
#: src/view/screens/SavedFeeds.tsx:135
|
||||||
msgid "You don't have any saved feeds."
|
msgid "You don't have any saved feeds."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2228,12 +2236,6 @@ msgstr ""
|
||||||
msgid "Your hosting provider"
|
msgid "Your hosting provider"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:405
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:127
|
|
||||||
#: src/view/shell/Drawer.tsx:523
|
|
||||||
msgid "Your invite codes are hidden when logged in using an App Password"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/view/com/auth/onboarding/WelcomeMobile.tsx:59
|
#: src/view/com/auth/onboarding/WelcomeMobile.tsx:59
|
||||||
msgid "Your posts, likes, and blocks are public. Mutes are private."
|
msgid "Your posts, likes, and blocks are public. Mutes are private."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -21,12 +21,6 @@ msgstr ""
|
||||||
#~ msgid ". This warning is only available for posts with media attached."
|
#~ msgid ". This warning is only available for posts with media attached."
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:410
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:158
|
|
||||||
#: src/view/shell/Drawer.tsx:527
|
|
||||||
msgid "{0, plural, one {# invite code available} other {# invite codes available}}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/view/com/modals/Repost.tsx:44
|
#: src/view/com/modals/Repost.tsx:44
|
||||||
msgid "{0}"
|
msgid "{0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -35,11 +29,6 @@ msgstr ""
|
||||||
msgid "{0} {purposeLabel} List"
|
msgid "{0} {purposeLabel} List"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:141
|
|
||||||
#: src/view/shell/Drawer.tsx:504
|
|
||||||
msgid "{invitesAvailable, plural, one {Invite codes: # available} other {Invite codes: # available}}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/view/screens/Search/Search.tsx:86
|
#: src/view/screens/Search/Search.tsx:86
|
||||||
msgid "{message}"
|
msgid "{message}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -61,12 +50,12 @@ msgid "A new version of the app is available. Please update to continue using th
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/modals/EditImage.tsx:299
|
#: src/view/com/modals/EditImage.tsx:299
|
||||||
#: src/view/screens/Settings.tsx:422
|
#: src/view/screens/Settings.tsx:410
|
||||||
msgid "Accessibility"
|
msgid "Accessibility"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/login/LoginForm.tsx:161
|
#: src/view/com/auth/login/LoginForm.tsx:161
|
||||||
#: src/view/screens/Settings.tsx:289
|
#: src/view/screens/Settings.tsx:288
|
||||||
msgid "Account"
|
msgid "Account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -88,8 +77,8 @@ msgstr ""
|
||||||
msgid "Add a user to this list"
|
msgid "Add a user to this list"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:358
|
#: src/view/screens/Settings.tsx:357
|
||||||
#: src/view/screens/Settings.tsx:367
|
#: src/view/screens/Settings.tsx:366
|
||||||
msgid "Add account"
|
msgid "Add account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -140,7 +129,7 @@ msgstr ""
|
||||||
msgid "Adult Content"
|
msgid "Adult Content"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:574
|
#: src/view/screens/Settings.tsx:562
|
||||||
msgid "Advanced"
|
msgid "Advanced"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -172,7 +161,7 @@ msgstr ""
|
||||||
msgid "App Language"
|
msgid "App Language"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:594
|
#: src/view/screens/Settings.tsx:582
|
||||||
msgid "App passwords"
|
msgid "App passwords"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -180,7 +169,7 @@ msgstr ""
|
||||||
msgid "App Passwords"
|
msgid "App Passwords"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:437
|
#: src/view/screens/Settings.tsx:425
|
||||||
msgid "Appearance"
|
msgid "Appearance"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -205,7 +194,7 @@ msgid "Artistic or non-erotic nudity."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/create/CreateAccount.tsx:145
|
#: src/view/com/auth/create/CreateAccount.tsx:145
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:122
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:151
|
||||||
#: src/view/com/auth/login/ForgotPasswordForm.tsx:166
|
#: src/view/com/auth/login/ForgotPasswordForm.tsx:166
|
||||||
#: src/view/com/auth/login/LoginForm.tsx:251
|
#: src/view/com/auth/login/LoginForm.tsx:251
|
||||||
#: src/view/com/auth/login/SetNewPasswordForm.tsx:148
|
#: src/view/com/auth/login/SetNewPasswordForm.tsx:148
|
||||||
|
@ -217,7 +206,7 @@ msgstr ""
|
||||||
msgid "Back"
|
msgid "Back"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:466
|
#: src/view/screens/Settings.tsx:454
|
||||||
msgid "Basics"
|
msgid "Basics"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -226,7 +215,7 @@ msgstr ""
|
||||||
msgid "Birthday"
|
msgid "Birthday"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:315
|
#: src/view/screens/Settings.tsx:314
|
||||||
msgid "Birthday:"
|
msgid "Birthday:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -291,7 +280,7 @@ msgstr ""
|
||||||
msgid "Bluesky.Social"
|
msgid "Bluesky.Social"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:723
|
#: src/view/screens/Settings.tsx:711
|
||||||
msgid "Build version {0} {1}"
|
msgid "Build version {0} {1}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -359,12 +348,12 @@ msgstr ""
|
||||||
msgid "Cancel waitlist signup"
|
msgid "Cancel waitlist signup"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:309
|
#: src/view/screens/Settings.tsx:308
|
||||||
msgid "Change"
|
msgid "Change"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:606
|
#: src/view/screens/Settings.tsx:594
|
||||||
#: src/view/screens/Settings.tsx:615
|
#: src/view/screens/Settings.tsx:603
|
||||||
msgid "Change handle"
|
msgid "Change handle"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -408,19 +397,19 @@ msgstr ""
|
||||||
msgid "Choose your password"
|
msgid "Choose your password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:699
|
#: src/view/screens/Settings.tsx:687
|
||||||
msgid "Clear all legacy storage data"
|
msgid "Clear all legacy storage data"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:701
|
#: src/view/screens/Settings.tsx:689
|
||||||
msgid "Clear all legacy storage data (restart after this)"
|
msgid "Clear all legacy storage data (restart after this)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:711
|
#: src/view/screens/Settings.tsx:699
|
||||||
msgid "Clear all storage data"
|
msgid "Clear all storage data"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:713
|
#: src/view/screens/Settings.tsx:701
|
||||||
msgid "Clear all storage data (restart after this)"
|
msgid "Clear all storage data (restart after this)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -561,7 +550,7 @@ msgstr ""
|
||||||
msgid "Custom domain"
|
msgid "Custom domain"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:620
|
#: src/view/screens/Settings.tsx:608
|
||||||
msgid "Danger Zone"
|
msgid "Danger Zone"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -569,7 +558,7 @@ msgstr ""
|
||||||
#~ msgid "Dark"
|
#~ msgid "Dark"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:627
|
#: src/view/screens/Settings.tsx:615
|
||||||
msgid "Delete account"
|
msgid "Delete account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -591,7 +580,7 @@ msgstr ""
|
||||||
msgid "Delete my account"
|
msgid "Delete my account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:637
|
#: src/view/screens/Settings.tsx:625
|
||||||
msgid "Delete my account…"
|
msgid "Delete my account…"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -618,7 +607,7 @@ msgstr ""
|
||||||
msgid "Dev Server"
|
msgid "Dev Server"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:642
|
#: src/view/screens/Settings.tsx:630
|
||||||
msgid "Developer Tools"
|
msgid "Developer Tools"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -677,7 +666,7 @@ msgid "Edit list details"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Feeds.tsx:367
|
#: src/view/screens/Feeds.tsx:367
|
||||||
#: src/view/screens/SavedFeeds.tsx:75
|
#: src/view/screens/SavedFeeds.tsx:85
|
||||||
msgid "Edit My Feeds"
|
msgid "Edit My Feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -712,7 +701,7 @@ msgstr ""
|
||||||
msgid "Email Updated"
|
msgid "Email Updated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:293
|
#: src/view/screens/Settings.tsx:292
|
||||||
msgid "Email:"
|
msgid "Email:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -757,7 +746,7 @@ msgstr ""
|
||||||
msgid "Failed to load recommended feeds"
|
msgid "Failed to load recommended feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Feeds.tsx:558
|
#: src/view/screens/Feeds.tsx:559
|
||||||
msgid "Feed offline"
|
msgid "Feed offline"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -765,12 +754,12 @@ msgstr ""
|
||||||
msgid "Feed Preferences"
|
msgid "Feed Preferences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:64
|
#: src/view/shell/desktop/RightNav.tsx:65
|
||||||
#: src/view/shell/Drawer.tsx:411
|
#: src/view/shell/Drawer.tsx:411
|
||||||
msgid "Feedback"
|
msgid "Feedback"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Feeds.tsx:474
|
#: src/view/screens/Feeds.tsx:475
|
||||||
#: src/view/shell/bottom-bar/BottomBar.tsx:169
|
#: src/view/shell/bottom-bar/BottomBar.tsx:169
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:342
|
#: src/view/shell/desktop/LeftNav.tsx:342
|
||||||
#: src/view/shell/Drawer.tsx:328
|
#: src/view/shell/Drawer.tsx:328
|
||||||
|
@ -782,7 +771,7 @@ msgstr ""
|
||||||
msgid "Feeds are created by users to curate content. Choose some feeds that you find interesting."
|
msgid "Feeds are created by users to curate content. Choose some feeds that you find interesting."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:132
|
#: src/view/screens/SavedFeeds.tsx:156
|
||||||
msgid "Feeds are custom algorithms that users build with a little coding expertise. <0/> for more information."
|
msgid "Feeds are custom algorithms that users build with a little coding expertise. <0/> for more information."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -884,7 +873,7 @@ msgstr ""
|
||||||
msgid "Handle"
|
msgid "Handle"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:93
|
#: src/view/shell/desktop/RightNav.tsx:94
|
||||||
#: src/view/shell/Drawer.tsx:421
|
#: src/view/shell/Drawer.tsx:421
|
||||||
msgid "Help"
|
msgid "Help"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -901,6 +890,26 @@ msgstr ""
|
||||||
msgid "Hide user list"
|
msgid "Hide user list"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:101
|
||||||
|
msgid "Hmm, some kind of issue occured when contacting the feed server. Please let the feed owner know about this issue."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:89
|
||||||
|
msgid "Hmm, the feed server appears to be misconfigured. Please let the feed owner know about this issue."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:95
|
||||||
|
msgid "Hmm, the feed server appears to be offline. Please let the feed owner know about this issue."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:92
|
||||||
|
msgid "Hmm, the feed server gave a bad response. Please let the feed owner know about this issue."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:86
|
||||||
|
msgid "Hmmm, we're having trouble finding this feed. It may have been deleted."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/bottom-bar/BottomBar.tsx:125
|
#: src/view/shell/bottom-bar/BottomBar.tsx:125
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:306
|
#: src/view/shell/desktop/LeftNav.tsx:306
|
||||||
#: src/view/shell/Drawer.tsx:275
|
#: src/view/shell/Drawer.tsx:275
|
||||||
|
@ -908,9 +917,9 @@ msgstr ""
|
||||||
msgid "Home"
|
msgid "Home"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/pager/FeedsTabBarMobile.tsx:71
|
#: src/view/com/pager/FeedsTabBarMobile.tsx:99
|
||||||
#: src/view/screens/PreferencesHomeFeed.tsx:95
|
#: src/view/screens/PreferencesHomeFeed.tsx:95
|
||||||
#: src/view/screens/Settings.tsx:486
|
#: src/view/screens/Settings.tsx:474
|
||||||
msgid "Home Feed Preferences"
|
msgid "Home Feed Preferences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -953,12 +962,12 @@ msgstr ""
|
||||||
msgid "Invalid username or password"
|
msgid "Invalid username or password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:386
|
#: src/view/screens/Settings.tsx:385
|
||||||
msgid "Invite"
|
msgid "Invite"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/modals/InviteCodes.tsx:91
|
#: src/view/com/modals/InviteCodes.tsx:91
|
||||||
#: src/view/screens/Settings.tsx:374
|
#: src/view/screens/Settings.tsx:373
|
||||||
msgid "Invite a Friend"
|
msgid "Invite a Friend"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -991,7 +1000,7 @@ msgstr ""
|
||||||
msgid "Language Settings"
|
msgid "Language Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:546
|
#: src/view/screens/Settings.tsx:534
|
||||||
msgid "Languages"
|
msgid "Languages"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1031,7 +1040,7 @@ msgstr ""
|
||||||
#~ msgid "Light"
|
#~ msgid "Light"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/ProfileFeed.tsx:625
|
#: src/view/screens/ProfileFeed.tsx:626
|
||||||
msgid "Like this feed"
|
msgid "Like this feed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1059,7 +1068,7 @@ msgstr ""
|
||||||
msgid "Load more posts"
|
msgid "Load more posts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Notifications.tsx:120
|
#: src/view/screens/Notifications.tsx:130
|
||||||
msgid "Load new notifications"
|
msgid "Load new notifications"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1075,11 +1084,11 @@ msgstr ""
|
||||||
msgid "Local dev server"
|
msgid "Local dev server"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:104
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:133
|
||||||
msgid "Login to account that is not listed"
|
msgid "Login to account that is not listed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/ProfileFeed.tsx:477
|
#: src/view/screens/ProfileFeed.tsx:478
|
||||||
msgid "Looks like this feed is only available to users with a Bluesky account. Please sign up or sign in to view this feed!"
|
msgid "Looks like this feed is only available to users with a Bluesky account. Please sign up or sign in to view this feed!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1092,7 +1101,7 @@ msgid "Menu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Moderation.tsx:51
|
#: src/view/screens/Moderation.tsx:51
|
||||||
#: src/view/screens/Settings.tsx:568
|
#: src/view/screens/Settings.tsx:556
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:400
|
#: src/view/shell/desktop/LeftNav.tsx:400
|
||||||
#: src/view/shell/Drawer.tsx:346
|
#: src/view/shell/Drawer.tsx:346
|
||||||
#: src/view/shell/Drawer.tsx:347
|
#: src/view/shell/Drawer.tsx:347
|
||||||
|
@ -1108,7 +1117,7 @@ msgid "More feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/profile/ProfileHeader.tsx:506
|
#: src/view/com/profile/ProfileHeader.tsx:506
|
||||||
#: src/view/screens/ProfileFeed.tsx:367
|
#: src/view/screens/ProfileFeed.tsx:368
|
||||||
#: src/view/screens/ProfileList.tsx:506
|
#: src/view/screens/ProfileList.tsx:506
|
||||||
msgid "More options"
|
msgid "More options"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1161,7 +1170,7 @@ msgstr ""
|
||||||
msgid "My Profile"
|
msgid "My Profile"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:525
|
#: src/view/screens/Settings.tsx:513
|
||||||
msgid "My Saved Feeds"
|
msgid "My Saved Feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1179,9 +1188,9 @@ msgid "New"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/feeds/FeedPage.tsx:187
|
#: src/view/com/feeds/FeedPage.tsx:187
|
||||||
#: src/view/screens/Feeds.tsx:509
|
#: src/view/screens/Feeds.tsx:510
|
||||||
#: src/view/screens/Profile.tsx:380
|
#: src/view/screens/Profile.tsx:381
|
||||||
#: src/view/screens/ProfileFeed.tsx:447
|
#: src/view/screens/ProfileFeed.tsx:448
|
||||||
#: src/view/screens/ProfileList.tsx:199
|
#: src/view/screens/ProfileList.tsx:199
|
||||||
#: src/view/screens/ProfileList.tsx:231
|
#: src/view/screens/ProfileList.tsx:231
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:255
|
#: src/view/shell/desktop/LeftNav.tsx:255
|
||||||
|
@ -1212,7 +1221,7 @@ msgstr ""
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/ProfileFeed.tsx:618
|
#: src/view/screens/ProfileFeed.tsx:619
|
||||||
#: src/view/screens/ProfileList.tsx:632
|
#: src/view/screens/ProfileList.tsx:632
|
||||||
msgid "No description"
|
msgid "No description"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1221,7 +1230,7 @@ msgstr ""
|
||||||
msgid "No result"
|
msgid "No result"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Feeds.tsx:451
|
#: src/view/screens/Feeds.tsx:452
|
||||||
msgid "No results found for \"{query}\""
|
msgid "No results found for \"{query}\""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1246,8 +1255,8 @@ msgstr ""
|
||||||
msgid "Not Applicable."
|
msgid "Not Applicable."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Notifications.tsx:87
|
#: src/view/screens/Notifications.tsx:97
|
||||||
#: src/view/screens/Notifications.tsx:111
|
#: src/view/screens/Notifications.tsx:121
|
||||||
#: src/view/shell/bottom-bar/BottomBar.tsx:196
|
#: src/view/shell/bottom-bar/BottomBar.tsx:196
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:364
|
#: src/view/shell/desktop/LeftNav.tsx:364
|
||||||
#: src/view/shell/Drawer.tsx:299
|
#: src/view/shell/Drawer.tsx:299
|
||||||
|
@ -1267,52 +1276,47 @@ msgstr ""
|
||||||
msgid "One or more images is missing alt text."
|
msgid "One or more images is missing alt text."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/pager/FeedsTabBarMobile.tsx:51
|
#: src/view/com/pager/FeedsTabBarMobile.tsx:79
|
||||||
msgid "Open navigation"
|
msgid "Open navigation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:538
|
#: src/view/screens/Settings.tsx:526
|
||||||
msgid "Opens configurable language settings"
|
msgid "Opens configurable language settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:146
|
|
||||||
#: src/view/shell/Drawer.tsx:509
|
|
||||||
msgid "Opens list of invite codes"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/view/com/modals/ChangeHandle.tsx:279
|
#: src/view/com/modals/ChangeHandle.tsx:279
|
||||||
msgid "Opens modal for using custom domain"
|
msgid "Opens modal for using custom domain"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:563
|
#: src/view/screens/Settings.tsx:551
|
||||||
msgid "Opens moderation settings"
|
msgid "Opens moderation settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:519
|
#: src/view/screens/Settings.tsx:507
|
||||||
msgid "Opens screen with all saved feeds"
|
msgid "Opens screen with all saved feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:586
|
#: src/view/screens/Settings.tsx:574
|
||||||
msgid "Opens the app password settings page"
|
msgid "Opens the app password settings page"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:478
|
#: src/view/screens/Settings.tsx:466
|
||||||
msgid "Opens the home feed preferences"
|
msgid "Opens the home feed preferences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:669
|
#: src/view/screens/Settings.tsx:657
|
||||||
msgid "Opens the storybook page"
|
msgid "Opens the storybook page"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:649
|
#: src/view/screens/Settings.tsx:637
|
||||||
msgid "Opens the system log page"
|
msgid "Opens the system log page"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:499
|
#: src/view/screens/Settings.tsx:487
|
||||||
msgid "Opens the threads preferences"
|
msgid "Opens the threads preferences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:109
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:138
|
||||||
msgid "Other account"
|
msgid "Other account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1349,7 +1353,7 @@ msgstr ""
|
||||||
msgid "Pictures meant for adults."
|
msgid "Pictures meant for adults."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:79
|
#: src/view/screens/SavedFeeds.tsx:89
|
||||||
msgid "Pinned Feeds"
|
msgid "Pinned Feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1415,7 +1419,7 @@ msgstr ""
|
||||||
msgid "Prioritize Your Follows"
|
msgid "Prioritize Your Follows"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:75
|
#: src/view/shell/desktop/RightNav.tsx:76
|
||||||
msgid "Privacy"
|
msgid "Privacy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1434,7 +1438,7 @@ msgstr ""
|
||||||
msgid "Profile"
|
msgid "Profile"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:794
|
#: src/view/screens/Settings.tsx:782
|
||||||
msgid "Protect your account by verifying your email."
|
msgid "Protect your account by verifying your email."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1476,7 +1480,7 @@ msgstr ""
|
||||||
msgid "Remove"
|
msgid "Remove"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/feeds/FeedSourceCard.tsx:92
|
#: src/view/com/feeds/FeedSourceCard.tsx:108
|
||||||
msgid "Remove {0} from my feeds?"
|
msgid "Remove {0} from my feeds?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1484,11 +1488,11 @@ msgstr ""
|
||||||
msgid "Remove account"
|
msgid "Remove account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/posts/FeedErrorMessage.tsx:106
|
#: src/view/com/posts/FeedErrorMessage.tsx:118
|
||||||
msgid "Remove feed"
|
msgid "Remove feed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/feeds/FeedSourceCard.tsx:91
|
#: src/view/com/feeds/FeedSourceCard.tsx:107
|
||||||
#: src/view/screens/ProfileFeed.tsx:278
|
#: src/view/screens/ProfileFeed.tsx:278
|
||||||
msgid "Remove from my feeds"
|
msgid "Remove from my feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1501,7 +1505,7 @@ msgstr ""
|
||||||
msgid "Remove image preview"
|
msgid "Remove image preview"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/posts/FeedErrorMessage.tsx:107
|
#: src/view/com/posts/FeedErrorMessage.tsx:119
|
||||||
msgid "Remove this feed from your saved feeds?"
|
msgid "Remove this feed from your saved feeds?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1565,7 +1569,7 @@ msgstr ""
|
||||||
msgid "Reset code"
|
msgid "Reset code"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:691
|
#: src/view/screens/Settings.tsx:679
|
||||||
msgid "Reset onboarding state"
|
msgid "Reset onboarding state"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1573,15 +1577,15 @@ msgstr ""
|
||||||
msgid "Reset password"
|
msgid "Reset password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:681
|
#: src/view/screens/Settings.tsx:669
|
||||||
msgid "Reset preferences state"
|
msgid "Reset preferences state"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:689
|
#: src/view/screens/Settings.tsx:677
|
||||||
msgid "Resets the onboarding state"
|
msgid "Resets the onboarding state"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:679
|
#: src/view/screens/Settings.tsx:667
|
||||||
msgid "Resets the preferences state"
|
msgid "Resets the preferences state"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1628,7 +1632,7 @@ msgstr ""
|
||||||
msgid "Save image crop"
|
msgid "Save image crop"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:105
|
#: src/view/screens/SavedFeeds.tsx:122
|
||||||
msgid "Saved Feeds"
|
msgid "Saved Feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1726,7 +1730,7 @@ msgstr ""
|
||||||
msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your following feed. This is an experimental feature."
|
msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your following feed. This is an experimental feature."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:280
|
#: src/view/screens/Settings.tsx:279
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:436
|
#: src/view/shell/desktop/LeftNav.tsx:436
|
||||||
#: src/view/shell/Drawer.tsx:380
|
#: src/view/shell/Drawer.tsx:380
|
||||||
#: src/view/shell/Drawer.tsx:381
|
#: src/view/shell/Drawer.tsx:381
|
||||||
|
@ -1751,7 +1755,7 @@ msgstr ""
|
||||||
#~ msgid "Share link"
|
#~ msgid "Share link"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:319
|
#: src/view/screens/Settings.tsx:318
|
||||||
msgid "Show"
|
msgid "Show"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1795,11 +1799,11 @@ msgstr ""
|
||||||
msgid "Sign In"
|
msgid "Sign In"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:37
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:44
|
||||||
msgid "Sign in as {0}"
|
msgid "Sign in as {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:94
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:118
|
||||||
#: src/view/com/auth/login/Login.tsx:100
|
#: src/view/com/auth/login/Login.tsx:100
|
||||||
msgid "Sign in as..."
|
msgid "Sign in as..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1823,7 +1827,7 @@ msgstr ""
|
||||||
msgid "Sign up or sign in to join the conversation"
|
msgid "Sign up or sign in to join the conversation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:330
|
#: src/view/screens/Settings.tsx:329
|
||||||
msgid "Signed in as"
|
msgid "Signed in as"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1848,11 +1852,11 @@ msgstr ""
|
||||||
msgid "Staging"
|
msgid "Staging"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:735
|
#: src/view/screens/Settings.tsx:723
|
||||||
msgid "Status page"
|
msgid "Status page"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:671
|
#: src/view/screens/Settings.tsx:659
|
||||||
msgid "Storybook"
|
msgid "Storybook"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1881,7 +1885,7 @@ msgstr ""
|
||||||
#~ msgid "System"
|
#~ msgid "System"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:651
|
#: src/view/screens/Settings.tsx:639
|
||||||
msgid "System log"
|
msgid "System log"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1889,7 +1893,7 @@ msgstr ""
|
||||||
msgid "Tall"
|
msgid "Tall"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:84
|
#: src/view/shell/desktop/RightNav.tsx:85
|
||||||
msgid "Terms"
|
msgid "Terms"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1962,7 +1966,7 @@ msgid "This warning is only available for posts with media attached."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/PreferencesThreads.tsx:53
|
#: src/view/screens/PreferencesThreads.tsx:53
|
||||||
#: src/view/screens/Settings.tsx:508
|
#: src/view/screens/Settings.tsx:496
|
||||||
msgid "Thread Preferences"
|
msgid "Thread Preferences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2069,15 +2073,15 @@ msgstr ""
|
||||||
msgid "Users"
|
msgid "Users"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:755
|
#: src/view/screens/Settings.tsx:743
|
||||||
msgid "Verify email"
|
msgid "Verify email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:780
|
#: src/view/screens/Settings.tsx:768
|
||||||
msgid "Verify my email"
|
msgid "Verify my email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:789
|
#: src/view/screens/Settings.tsx:777
|
||||||
msgid "Verify My Email"
|
msgid "Verify My Email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2102,6 +2106,10 @@ msgstr ""
|
||||||
msgid "We're so excited to have you join us!"
|
msgid "We're so excited to have you join us!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:98
|
||||||
|
msgid "We're sorry, but this content is not viewable without a Bluesky account."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Search/Search.tsx:236
|
#: src/view/screens/Search/Search.tsx:236
|
||||||
msgid "We're sorry, but your search could not be completed. Please try again in a few minutes."
|
msgid "We're sorry, but your search could not be completed. Please try again in a few minutes."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -2157,7 +2165,7 @@ msgstr ""
|
||||||
msgid "You don't have any invite codes yet! We'll send you some when you've been on Bluesky for a little longer."
|
msgid "You don't have any invite codes yet! We'll send you some when you've been on Bluesky for a little longer."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:92
|
#: src/view/screens/SavedFeeds.tsx:102
|
||||||
msgid "You don't have any pinned feeds."
|
msgid "You don't have any pinned feeds."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2165,7 +2173,7 @@ msgstr ""
|
||||||
msgid "You don't have any saved feeds!"
|
msgid "You don't have any saved feeds!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:118
|
#: src/view/screens/SavedFeeds.tsx:135
|
||||||
msgid "You don't have any saved feeds."
|
msgid "You don't have any saved feeds."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2228,12 +2236,6 @@ msgstr ""
|
||||||
msgid "Your hosting provider"
|
msgid "Your hosting provider"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:405
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:127
|
|
||||||
#: src/view/shell/Drawer.tsx:523
|
|
||||||
msgid "Your invite codes are hidden when logged in using an App Password"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/view/com/auth/onboarding/WelcomeMobile.tsx:59
|
#: src/view/com/auth/onboarding/WelcomeMobile.tsx:59
|
||||||
msgid "Your posts, likes, and blocks are public. Mutes are private."
|
msgid "Your posts, likes, and blocks are public. Mutes are private."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -21,12 +21,6 @@ msgstr ""
|
||||||
#~ msgid ". This warning is only available for posts with media attached."
|
#~ msgid ". This warning is only available for posts with media attached."
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:410
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:158
|
|
||||||
#: src/view/shell/Drawer.tsx:527
|
|
||||||
msgid "{0, plural, one {# invite code available} other {# invite codes available}}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/view/com/modals/Repost.tsx:44
|
#: src/view/com/modals/Repost.tsx:44
|
||||||
msgid "{0}"
|
msgid "{0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -35,11 +29,6 @@ msgstr ""
|
||||||
msgid "{0} {purposeLabel} List"
|
msgid "{0} {purposeLabel} List"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:141
|
|
||||||
#: src/view/shell/Drawer.tsx:504
|
|
||||||
msgid "{invitesAvailable, plural, one {Invite codes: # available} other {Invite codes: # available}}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/view/screens/Search/Search.tsx:86
|
#: src/view/screens/Search/Search.tsx:86
|
||||||
msgid "{message}"
|
msgid "{message}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -61,12 +50,12 @@ msgid "A new version of the app is available. Please update to continue using th
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/modals/EditImage.tsx:299
|
#: src/view/com/modals/EditImage.tsx:299
|
||||||
#: src/view/screens/Settings.tsx:422
|
#: src/view/screens/Settings.tsx:410
|
||||||
msgid "Accessibility"
|
msgid "Accessibility"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/login/LoginForm.tsx:161
|
#: src/view/com/auth/login/LoginForm.tsx:161
|
||||||
#: src/view/screens/Settings.tsx:289
|
#: src/view/screens/Settings.tsx:288
|
||||||
msgid "Account"
|
msgid "Account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -88,8 +77,8 @@ msgstr ""
|
||||||
msgid "Add a user to this list"
|
msgid "Add a user to this list"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:358
|
#: src/view/screens/Settings.tsx:357
|
||||||
#: src/view/screens/Settings.tsx:367
|
#: src/view/screens/Settings.tsx:366
|
||||||
msgid "Add account"
|
msgid "Add account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -140,7 +129,7 @@ msgstr ""
|
||||||
msgid "Adult Content"
|
msgid "Adult Content"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:574
|
#: src/view/screens/Settings.tsx:562
|
||||||
msgid "Advanced"
|
msgid "Advanced"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -172,7 +161,7 @@ msgstr ""
|
||||||
msgid "App Language"
|
msgid "App Language"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:594
|
#: src/view/screens/Settings.tsx:582
|
||||||
msgid "App passwords"
|
msgid "App passwords"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -180,7 +169,7 @@ msgstr ""
|
||||||
msgid "App Passwords"
|
msgid "App Passwords"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:437
|
#: src/view/screens/Settings.tsx:425
|
||||||
msgid "Appearance"
|
msgid "Appearance"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -205,7 +194,7 @@ msgid "Artistic or non-erotic nudity."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/create/CreateAccount.tsx:145
|
#: src/view/com/auth/create/CreateAccount.tsx:145
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:122
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:151
|
||||||
#: src/view/com/auth/login/ForgotPasswordForm.tsx:166
|
#: src/view/com/auth/login/ForgotPasswordForm.tsx:166
|
||||||
#: src/view/com/auth/login/LoginForm.tsx:251
|
#: src/view/com/auth/login/LoginForm.tsx:251
|
||||||
#: src/view/com/auth/login/SetNewPasswordForm.tsx:148
|
#: src/view/com/auth/login/SetNewPasswordForm.tsx:148
|
||||||
|
@ -217,7 +206,7 @@ msgstr ""
|
||||||
msgid "Back"
|
msgid "Back"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:466
|
#: src/view/screens/Settings.tsx:454
|
||||||
msgid "Basics"
|
msgid "Basics"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -226,7 +215,7 @@ msgstr ""
|
||||||
msgid "Birthday"
|
msgid "Birthday"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:315
|
#: src/view/screens/Settings.tsx:314
|
||||||
msgid "Birthday:"
|
msgid "Birthday:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -291,7 +280,7 @@ msgstr ""
|
||||||
msgid "Bluesky.Social"
|
msgid "Bluesky.Social"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:723
|
#: src/view/screens/Settings.tsx:711
|
||||||
msgid "Build version {0} {1}"
|
msgid "Build version {0} {1}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -359,12 +348,12 @@ msgstr ""
|
||||||
msgid "Cancel waitlist signup"
|
msgid "Cancel waitlist signup"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:309
|
#: src/view/screens/Settings.tsx:308
|
||||||
msgid "Change"
|
msgid "Change"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:606
|
#: src/view/screens/Settings.tsx:594
|
||||||
#: src/view/screens/Settings.tsx:615
|
#: src/view/screens/Settings.tsx:603
|
||||||
msgid "Change handle"
|
msgid "Change handle"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -408,19 +397,19 @@ msgstr ""
|
||||||
msgid "Choose your password"
|
msgid "Choose your password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:699
|
#: src/view/screens/Settings.tsx:687
|
||||||
msgid "Clear all legacy storage data"
|
msgid "Clear all legacy storage data"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:701
|
#: src/view/screens/Settings.tsx:689
|
||||||
msgid "Clear all legacy storage data (restart after this)"
|
msgid "Clear all legacy storage data (restart after this)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:711
|
#: src/view/screens/Settings.tsx:699
|
||||||
msgid "Clear all storage data"
|
msgid "Clear all storage data"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:713
|
#: src/view/screens/Settings.tsx:701
|
||||||
msgid "Clear all storage data (restart after this)"
|
msgid "Clear all storage data (restart after this)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -561,7 +550,7 @@ msgstr ""
|
||||||
msgid "Custom domain"
|
msgid "Custom domain"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:620
|
#: src/view/screens/Settings.tsx:608
|
||||||
msgid "Danger Zone"
|
msgid "Danger Zone"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -569,7 +558,7 @@ msgstr ""
|
||||||
#~ msgid "Dark"
|
#~ msgid "Dark"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:627
|
#: src/view/screens/Settings.tsx:615
|
||||||
msgid "Delete account"
|
msgid "Delete account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -591,7 +580,7 @@ msgstr ""
|
||||||
msgid "Delete my account"
|
msgid "Delete my account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:637
|
#: src/view/screens/Settings.tsx:625
|
||||||
msgid "Delete my account…"
|
msgid "Delete my account…"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -618,7 +607,7 @@ msgstr ""
|
||||||
msgid "Dev Server"
|
msgid "Dev Server"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:642
|
#: src/view/screens/Settings.tsx:630
|
||||||
msgid "Developer Tools"
|
msgid "Developer Tools"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -677,7 +666,7 @@ msgid "Edit list details"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Feeds.tsx:367
|
#: src/view/screens/Feeds.tsx:367
|
||||||
#: src/view/screens/SavedFeeds.tsx:75
|
#: src/view/screens/SavedFeeds.tsx:85
|
||||||
msgid "Edit My Feeds"
|
msgid "Edit My Feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -712,7 +701,7 @@ msgstr ""
|
||||||
msgid "Email Updated"
|
msgid "Email Updated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:293
|
#: src/view/screens/Settings.tsx:292
|
||||||
msgid "Email:"
|
msgid "Email:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -757,7 +746,7 @@ msgstr ""
|
||||||
msgid "Failed to load recommended feeds"
|
msgid "Failed to load recommended feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Feeds.tsx:558
|
#: src/view/screens/Feeds.tsx:559
|
||||||
msgid "Feed offline"
|
msgid "Feed offline"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -765,12 +754,12 @@ msgstr ""
|
||||||
msgid "Feed Preferences"
|
msgid "Feed Preferences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:64
|
#: src/view/shell/desktop/RightNav.tsx:65
|
||||||
#: src/view/shell/Drawer.tsx:411
|
#: src/view/shell/Drawer.tsx:411
|
||||||
msgid "Feedback"
|
msgid "Feedback"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Feeds.tsx:474
|
#: src/view/screens/Feeds.tsx:475
|
||||||
#: src/view/shell/bottom-bar/BottomBar.tsx:169
|
#: src/view/shell/bottom-bar/BottomBar.tsx:169
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:342
|
#: src/view/shell/desktop/LeftNav.tsx:342
|
||||||
#: src/view/shell/Drawer.tsx:328
|
#: src/view/shell/Drawer.tsx:328
|
||||||
|
@ -782,7 +771,7 @@ msgstr ""
|
||||||
msgid "Feeds are created by users to curate content. Choose some feeds that you find interesting."
|
msgid "Feeds are created by users to curate content. Choose some feeds that you find interesting."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:132
|
#: src/view/screens/SavedFeeds.tsx:156
|
||||||
msgid "Feeds are custom algorithms that users build with a little coding expertise. <0/> for more information."
|
msgid "Feeds are custom algorithms that users build with a little coding expertise. <0/> for more information."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -884,7 +873,7 @@ msgstr ""
|
||||||
msgid "Handle"
|
msgid "Handle"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:93
|
#: src/view/shell/desktop/RightNav.tsx:94
|
||||||
#: src/view/shell/Drawer.tsx:421
|
#: src/view/shell/Drawer.tsx:421
|
||||||
msgid "Help"
|
msgid "Help"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -901,6 +890,26 @@ msgstr ""
|
||||||
msgid "Hide user list"
|
msgid "Hide user list"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:101
|
||||||
|
msgid "Hmm, some kind of issue occured when contacting the feed server. Please let the feed owner know about this issue."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:89
|
||||||
|
msgid "Hmm, the feed server appears to be misconfigured. Please let the feed owner know about this issue."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:95
|
||||||
|
msgid "Hmm, the feed server appears to be offline. Please let the feed owner know about this issue."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:92
|
||||||
|
msgid "Hmm, the feed server gave a bad response. Please let the feed owner know about this issue."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:86
|
||||||
|
msgid "Hmmm, we're having trouble finding this feed. It may have been deleted."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/bottom-bar/BottomBar.tsx:125
|
#: src/view/shell/bottom-bar/BottomBar.tsx:125
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:306
|
#: src/view/shell/desktop/LeftNav.tsx:306
|
||||||
#: src/view/shell/Drawer.tsx:275
|
#: src/view/shell/Drawer.tsx:275
|
||||||
|
@ -908,9 +917,9 @@ msgstr ""
|
||||||
msgid "Home"
|
msgid "Home"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/pager/FeedsTabBarMobile.tsx:71
|
#: src/view/com/pager/FeedsTabBarMobile.tsx:99
|
||||||
#: src/view/screens/PreferencesHomeFeed.tsx:95
|
#: src/view/screens/PreferencesHomeFeed.tsx:95
|
||||||
#: src/view/screens/Settings.tsx:486
|
#: src/view/screens/Settings.tsx:474
|
||||||
msgid "Home Feed Preferences"
|
msgid "Home Feed Preferences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -953,12 +962,12 @@ msgstr ""
|
||||||
msgid "Invalid username or password"
|
msgid "Invalid username or password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:386
|
#: src/view/screens/Settings.tsx:385
|
||||||
msgid "Invite"
|
msgid "Invite"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/modals/InviteCodes.tsx:91
|
#: src/view/com/modals/InviteCodes.tsx:91
|
||||||
#: src/view/screens/Settings.tsx:374
|
#: src/view/screens/Settings.tsx:373
|
||||||
msgid "Invite a Friend"
|
msgid "Invite a Friend"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -991,7 +1000,7 @@ msgstr ""
|
||||||
msgid "Language Settings"
|
msgid "Language Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:546
|
#: src/view/screens/Settings.tsx:534
|
||||||
msgid "Languages"
|
msgid "Languages"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1031,7 +1040,7 @@ msgstr ""
|
||||||
#~ msgid "Light"
|
#~ msgid "Light"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/ProfileFeed.tsx:625
|
#: src/view/screens/ProfileFeed.tsx:626
|
||||||
msgid "Like this feed"
|
msgid "Like this feed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1059,7 +1068,7 @@ msgstr ""
|
||||||
msgid "Load more posts"
|
msgid "Load more posts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Notifications.tsx:120
|
#: src/view/screens/Notifications.tsx:130
|
||||||
msgid "Load new notifications"
|
msgid "Load new notifications"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1075,11 +1084,11 @@ msgstr ""
|
||||||
msgid "Local dev server"
|
msgid "Local dev server"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:104
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:133
|
||||||
msgid "Login to account that is not listed"
|
msgid "Login to account that is not listed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/ProfileFeed.tsx:477
|
#: src/view/screens/ProfileFeed.tsx:478
|
||||||
msgid "Looks like this feed is only available to users with a Bluesky account. Please sign up or sign in to view this feed!"
|
msgid "Looks like this feed is only available to users with a Bluesky account. Please sign up or sign in to view this feed!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1092,7 +1101,7 @@ msgid "Menu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Moderation.tsx:51
|
#: src/view/screens/Moderation.tsx:51
|
||||||
#: src/view/screens/Settings.tsx:568
|
#: src/view/screens/Settings.tsx:556
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:400
|
#: src/view/shell/desktop/LeftNav.tsx:400
|
||||||
#: src/view/shell/Drawer.tsx:346
|
#: src/view/shell/Drawer.tsx:346
|
||||||
#: src/view/shell/Drawer.tsx:347
|
#: src/view/shell/Drawer.tsx:347
|
||||||
|
@ -1108,7 +1117,7 @@ msgid "More feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/profile/ProfileHeader.tsx:506
|
#: src/view/com/profile/ProfileHeader.tsx:506
|
||||||
#: src/view/screens/ProfileFeed.tsx:367
|
#: src/view/screens/ProfileFeed.tsx:368
|
||||||
#: src/view/screens/ProfileList.tsx:506
|
#: src/view/screens/ProfileList.tsx:506
|
||||||
msgid "More options"
|
msgid "More options"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1161,7 +1170,7 @@ msgstr ""
|
||||||
msgid "My Profile"
|
msgid "My Profile"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:525
|
#: src/view/screens/Settings.tsx:513
|
||||||
msgid "My Saved Feeds"
|
msgid "My Saved Feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1179,9 +1188,9 @@ msgid "New"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/feeds/FeedPage.tsx:187
|
#: src/view/com/feeds/FeedPage.tsx:187
|
||||||
#: src/view/screens/Feeds.tsx:509
|
#: src/view/screens/Feeds.tsx:510
|
||||||
#: src/view/screens/Profile.tsx:380
|
#: src/view/screens/Profile.tsx:381
|
||||||
#: src/view/screens/ProfileFeed.tsx:447
|
#: src/view/screens/ProfileFeed.tsx:448
|
||||||
#: src/view/screens/ProfileList.tsx:199
|
#: src/view/screens/ProfileList.tsx:199
|
||||||
#: src/view/screens/ProfileList.tsx:231
|
#: src/view/screens/ProfileList.tsx:231
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:255
|
#: src/view/shell/desktop/LeftNav.tsx:255
|
||||||
|
@ -1212,7 +1221,7 @@ msgstr ""
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/ProfileFeed.tsx:618
|
#: src/view/screens/ProfileFeed.tsx:619
|
||||||
#: src/view/screens/ProfileList.tsx:632
|
#: src/view/screens/ProfileList.tsx:632
|
||||||
msgid "No description"
|
msgid "No description"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1221,7 +1230,7 @@ msgstr ""
|
||||||
msgid "No result"
|
msgid "No result"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Feeds.tsx:451
|
#: src/view/screens/Feeds.tsx:452
|
||||||
msgid "No results found for \"{query}\""
|
msgid "No results found for \"{query}\""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1246,8 +1255,8 @@ msgstr ""
|
||||||
msgid "Not Applicable."
|
msgid "Not Applicable."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Notifications.tsx:87
|
#: src/view/screens/Notifications.tsx:97
|
||||||
#: src/view/screens/Notifications.tsx:111
|
#: src/view/screens/Notifications.tsx:121
|
||||||
#: src/view/shell/bottom-bar/BottomBar.tsx:196
|
#: src/view/shell/bottom-bar/BottomBar.tsx:196
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:364
|
#: src/view/shell/desktop/LeftNav.tsx:364
|
||||||
#: src/view/shell/Drawer.tsx:299
|
#: src/view/shell/Drawer.tsx:299
|
||||||
|
@ -1267,52 +1276,47 @@ msgstr ""
|
||||||
msgid "One or more images is missing alt text."
|
msgid "One or more images is missing alt text."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/pager/FeedsTabBarMobile.tsx:51
|
#: src/view/com/pager/FeedsTabBarMobile.tsx:79
|
||||||
msgid "Open navigation"
|
msgid "Open navigation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:538
|
#: src/view/screens/Settings.tsx:526
|
||||||
msgid "Opens configurable language settings"
|
msgid "Opens configurable language settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:146
|
|
||||||
#: src/view/shell/Drawer.tsx:509
|
|
||||||
msgid "Opens list of invite codes"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/view/com/modals/ChangeHandle.tsx:279
|
#: src/view/com/modals/ChangeHandle.tsx:279
|
||||||
msgid "Opens modal for using custom domain"
|
msgid "Opens modal for using custom domain"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:563
|
#: src/view/screens/Settings.tsx:551
|
||||||
msgid "Opens moderation settings"
|
msgid "Opens moderation settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:519
|
#: src/view/screens/Settings.tsx:507
|
||||||
msgid "Opens screen with all saved feeds"
|
msgid "Opens screen with all saved feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:586
|
#: src/view/screens/Settings.tsx:574
|
||||||
msgid "Opens the app password settings page"
|
msgid "Opens the app password settings page"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:478
|
#: src/view/screens/Settings.tsx:466
|
||||||
msgid "Opens the home feed preferences"
|
msgid "Opens the home feed preferences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:669
|
#: src/view/screens/Settings.tsx:657
|
||||||
msgid "Opens the storybook page"
|
msgid "Opens the storybook page"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:649
|
#: src/view/screens/Settings.tsx:637
|
||||||
msgid "Opens the system log page"
|
msgid "Opens the system log page"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:499
|
#: src/view/screens/Settings.tsx:487
|
||||||
msgid "Opens the threads preferences"
|
msgid "Opens the threads preferences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:109
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:138
|
||||||
msgid "Other account"
|
msgid "Other account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1349,7 +1353,7 @@ msgstr ""
|
||||||
msgid "Pictures meant for adults."
|
msgid "Pictures meant for adults."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:79
|
#: src/view/screens/SavedFeeds.tsx:89
|
||||||
msgid "Pinned Feeds"
|
msgid "Pinned Feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1415,7 +1419,7 @@ msgstr ""
|
||||||
msgid "Prioritize Your Follows"
|
msgid "Prioritize Your Follows"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:75
|
#: src/view/shell/desktop/RightNav.tsx:76
|
||||||
msgid "Privacy"
|
msgid "Privacy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1434,7 +1438,7 @@ msgstr ""
|
||||||
msgid "Profile"
|
msgid "Profile"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:794
|
#: src/view/screens/Settings.tsx:782
|
||||||
msgid "Protect your account by verifying your email."
|
msgid "Protect your account by verifying your email."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1476,7 +1480,7 @@ msgstr ""
|
||||||
msgid "Remove"
|
msgid "Remove"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/feeds/FeedSourceCard.tsx:92
|
#: src/view/com/feeds/FeedSourceCard.tsx:108
|
||||||
msgid "Remove {0} from my feeds?"
|
msgid "Remove {0} from my feeds?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1484,11 +1488,11 @@ msgstr ""
|
||||||
msgid "Remove account"
|
msgid "Remove account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/posts/FeedErrorMessage.tsx:106
|
#: src/view/com/posts/FeedErrorMessage.tsx:118
|
||||||
msgid "Remove feed"
|
msgid "Remove feed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/feeds/FeedSourceCard.tsx:91
|
#: src/view/com/feeds/FeedSourceCard.tsx:107
|
||||||
#: src/view/screens/ProfileFeed.tsx:278
|
#: src/view/screens/ProfileFeed.tsx:278
|
||||||
msgid "Remove from my feeds"
|
msgid "Remove from my feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1501,7 +1505,7 @@ msgstr ""
|
||||||
msgid "Remove image preview"
|
msgid "Remove image preview"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/posts/FeedErrorMessage.tsx:107
|
#: src/view/com/posts/FeedErrorMessage.tsx:119
|
||||||
msgid "Remove this feed from your saved feeds?"
|
msgid "Remove this feed from your saved feeds?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1565,7 +1569,7 @@ msgstr ""
|
||||||
msgid "Reset code"
|
msgid "Reset code"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:691
|
#: src/view/screens/Settings.tsx:679
|
||||||
msgid "Reset onboarding state"
|
msgid "Reset onboarding state"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1573,15 +1577,15 @@ msgstr ""
|
||||||
msgid "Reset password"
|
msgid "Reset password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:681
|
#: src/view/screens/Settings.tsx:669
|
||||||
msgid "Reset preferences state"
|
msgid "Reset preferences state"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:689
|
#: src/view/screens/Settings.tsx:677
|
||||||
msgid "Resets the onboarding state"
|
msgid "Resets the onboarding state"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:679
|
#: src/view/screens/Settings.tsx:667
|
||||||
msgid "Resets the preferences state"
|
msgid "Resets the preferences state"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1628,7 +1632,7 @@ msgstr ""
|
||||||
msgid "Save image crop"
|
msgid "Save image crop"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:105
|
#: src/view/screens/SavedFeeds.tsx:122
|
||||||
msgid "Saved Feeds"
|
msgid "Saved Feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1726,7 +1730,7 @@ msgstr ""
|
||||||
msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your following feed. This is an experimental feature."
|
msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your following feed. This is an experimental feature."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:280
|
#: src/view/screens/Settings.tsx:279
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:436
|
#: src/view/shell/desktop/LeftNav.tsx:436
|
||||||
#: src/view/shell/Drawer.tsx:380
|
#: src/view/shell/Drawer.tsx:380
|
||||||
#: src/view/shell/Drawer.tsx:381
|
#: src/view/shell/Drawer.tsx:381
|
||||||
|
@ -1751,7 +1755,7 @@ msgstr ""
|
||||||
#~ msgid "Share link"
|
#~ msgid "Share link"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:319
|
#: src/view/screens/Settings.tsx:318
|
||||||
msgid "Show"
|
msgid "Show"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1795,11 +1799,11 @@ msgstr ""
|
||||||
msgid "Sign In"
|
msgid "Sign In"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:37
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:44
|
||||||
msgid "Sign in as {0}"
|
msgid "Sign in as {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:94
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:118
|
||||||
#: src/view/com/auth/login/Login.tsx:100
|
#: src/view/com/auth/login/Login.tsx:100
|
||||||
msgid "Sign in as..."
|
msgid "Sign in as..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1823,7 +1827,7 @@ msgstr ""
|
||||||
msgid "Sign up or sign in to join the conversation"
|
msgid "Sign up or sign in to join the conversation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:330
|
#: src/view/screens/Settings.tsx:329
|
||||||
msgid "Signed in as"
|
msgid "Signed in as"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1848,11 +1852,11 @@ msgstr ""
|
||||||
msgid "Staging"
|
msgid "Staging"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:735
|
#: src/view/screens/Settings.tsx:723
|
||||||
msgid "Status page"
|
msgid "Status page"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:671
|
#: src/view/screens/Settings.tsx:659
|
||||||
msgid "Storybook"
|
msgid "Storybook"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1881,7 +1885,7 @@ msgstr ""
|
||||||
#~ msgid "System"
|
#~ msgid "System"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:651
|
#: src/view/screens/Settings.tsx:639
|
||||||
msgid "System log"
|
msgid "System log"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1889,7 +1893,7 @@ msgstr ""
|
||||||
msgid "Tall"
|
msgid "Tall"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:84
|
#: src/view/shell/desktop/RightNav.tsx:85
|
||||||
msgid "Terms"
|
msgid "Terms"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1962,7 +1966,7 @@ msgid "This warning is only available for posts with media attached."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/PreferencesThreads.tsx:53
|
#: src/view/screens/PreferencesThreads.tsx:53
|
||||||
#: src/view/screens/Settings.tsx:508
|
#: src/view/screens/Settings.tsx:496
|
||||||
msgid "Thread Preferences"
|
msgid "Thread Preferences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2069,15 +2073,15 @@ msgstr ""
|
||||||
msgid "Users"
|
msgid "Users"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:755
|
#: src/view/screens/Settings.tsx:743
|
||||||
msgid "Verify email"
|
msgid "Verify email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:780
|
#: src/view/screens/Settings.tsx:768
|
||||||
msgid "Verify my email"
|
msgid "Verify my email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:789
|
#: src/view/screens/Settings.tsx:777
|
||||||
msgid "Verify My Email"
|
msgid "Verify My Email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2102,6 +2106,10 @@ msgstr ""
|
||||||
msgid "We're so excited to have you join us!"
|
msgid "We're so excited to have you join us!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:98
|
||||||
|
msgid "We're sorry, but this content is not viewable without a Bluesky account."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Search/Search.tsx:236
|
#: src/view/screens/Search/Search.tsx:236
|
||||||
msgid "We're sorry, but your search could not be completed. Please try again in a few minutes."
|
msgid "We're sorry, but your search could not be completed. Please try again in a few minutes."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -2157,7 +2165,7 @@ msgstr ""
|
||||||
msgid "You don't have any invite codes yet! We'll send you some when you've been on Bluesky for a little longer."
|
msgid "You don't have any invite codes yet! We'll send you some when you've been on Bluesky for a little longer."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:92
|
#: src/view/screens/SavedFeeds.tsx:102
|
||||||
msgid "You don't have any pinned feeds."
|
msgid "You don't have any pinned feeds."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2165,7 +2173,7 @@ msgstr ""
|
||||||
msgid "You don't have any saved feeds!"
|
msgid "You don't have any saved feeds!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:118
|
#: src/view/screens/SavedFeeds.tsx:135
|
||||||
msgid "You don't have any saved feeds."
|
msgid "You don't have any saved feeds."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2228,12 +2236,6 @@ msgstr ""
|
||||||
msgid "Your hosting provider"
|
msgid "Your hosting provider"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:405
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:127
|
|
||||||
#: src/view/shell/Drawer.tsx:523
|
|
||||||
msgid "Your invite codes are hidden when logged in using an App Password"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/view/com/auth/onboarding/WelcomeMobile.tsx:59
|
#: src/view/com/auth/onboarding/WelcomeMobile.tsx:59
|
||||||
msgid "Your posts, likes, and blocks are public. Mutes are private."
|
msgid "Your posts, likes, and blocks are public. Mutes are private."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -21,12 +21,6 @@ msgstr ""
|
||||||
#~ msgid ". This warning is only available for posts with media attached."
|
#~ msgid ". This warning is only available for posts with media attached."
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:410
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:158
|
|
||||||
#: src/view/shell/Drawer.tsx:527
|
|
||||||
msgid "{0, plural, one {# invite code available} other {# invite codes available}}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/view/com/modals/Repost.tsx:44
|
#: src/view/com/modals/Repost.tsx:44
|
||||||
msgid "{0}"
|
msgid "{0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -35,11 +29,6 @@ msgstr ""
|
||||||
msgid "{0} {purposeLabel} List"
|
msgid "{0} {purposeLabel} List"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:141
|
|
||||||
#: src/view/shell/Drawer.tsx:504
|
|
||||||
msgid "{invitesAvailable, plural, one {Invite codes: # available} other {Invite codes: # available}}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/view/screens/Search/Search.tsx:86
|
#: src/view/screens/Search/Search.tsx:86
|
||||||
msgid "{message}"
|
msgid "{message}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -61,12 +50,12 @@ msgid "A new version of the app is available. Please update to continue using th
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/modals/EditImage.tsx:299
|
#: src/view/com/modals/EditImage.tsx:299
|
||||||
#: src/view/screens/Settings.tsx:422
|
#: src/view/screens/Settings.tsx:410
|
||||||
msgid "Accessibility"
|
msgid "Accessibility"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/login/LoginForm.tsx:161
|
#: src/view/com/auth/login/LoginForm.tsx:161
|
||||||
#: src/view/screens/Settings.tsx:289
|
#: src/view/screens/Settings.tsx:288
|
||||||
msgid "Account"
|
msgid "Account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -88,8 +77,8 @@ msgstr ""
|
||||||
msgid "Add a user to this list"
|
msgid "Add a user to this list"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:358
|
#: src/view/screens/Settings.tsx:357
|
||||||
#: src/view/screens/Settings.tsx:367
|
#: src/view/screens/Settings.tsx:366
|
||||||
msgid "Add account"
|
msgid "Add account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -140,7 +129,7 @@ msgstr ""
|
||||||
msgid "Adult Content"
|
msgid "Adult Content"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:574
|
#: src/view/screens/Settings.tsx:562
|
||||||
msgid "Advanced"
|
msgid "Advanced"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -172,7 +161,7 @@ msgstr ""
|
||||||
msgid "App Language"
|
msgid "App Language"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:594
|
#: src/view/screens/Settings.tsx:582
|
||||||
msgid "App passwords"
|
msgid "App passwords"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -180,7 +169,7 @@ msgstr ""
|
||||||
msgid "App Passwords"
|
msgid "App Passwords"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:437
|
#: src/view/screens/Settings.tsx:425
|
||||||
msgid "Appearance"
|
msgid "Appearance"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -205,7 +194,7 @@ msgid "Artistic or non-erotic nudity."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/create/CreateAccount.tsx:145
|
#: src/view/com/auth/create/CreateAccount.tsx:145
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:122
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:151
|
||||||
#: src/view/com/auth/login/ForgotPasswordForm.tsx:166
|
#: src/view/com/auth/login/ForgotPasswordForm.tsx:166
|
||||||
#: src/view/com/auth/login/LoginForm.tsx:251
|
#: src/view/com/auth/login/LoginForm.tsx:251
|
||||||
#: src/view/com/auth/login/SetNewPasswordForm.tsx:148
|
#: src/view/com/auth/login/SetNewPasswordForm.tsx:148
|
||||||
|
@ -217,7 +206,7 @@ msgstr ""
|
||||||
msgid "Back"
|
msgid "Back"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:466
|
#: src/view/screens/Settings.tsx:454
|
||||||
msgid "Basics"
|
msgid "Basics"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -226,7 +215,7 @@ msgstr ""
|
||||||
msgid "Birthday"
|
msgid "Birthday"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:315
|
#: src/view/screens/Settings.tsx:314
|
||||||
msgid "Birthday:"
|
msgid "Birthday:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -291,7 +280,7 @@ msgstr ""
|
||||||
msgid "Bluesky.Social"
|
msgid "Bluesky.Social"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:723
|
#: src/view/screens/Settings.tsx:711
|
||||||
msgid "Build version {0} {1}"
|
msgid "Build version {0} {1}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -359,12 +348,12 @@ msgstr ""
|
||||||
msgid "Cancel waitlist signup"
|
msgid "Cancel waitlist signup"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:309
|
#: src/view/screens/Settings.tsx:308
|
||||||
msgid "Change"
|
msgid "Change"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:606
|
#: src/view/screens/Settings.tsx:594
|
||||||
#: src/view/screens/Settings.tsx:615
|
#: src/view/screens/Settings.tsx:603
|
||||||
msgid "Change handle"
|
msgid "Change handle"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -408,19 +397,19 @@ msgstr ""
|
||||||
msgid "Choose your password"
|
msgid "Choose your password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:699
|
#: src/view/screens/Settings.tsx:687
|
||||||
msgid "Clear all legacy storage data"
|
msgid "Clear all legacy storage data"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:701
|
#: src/view/screens/Settings.tsx:689
|
||||||
msgid "Clear all legacy storage data (restart after this)"
|
msgid "Clear all legacy storage data (restart after this)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:711
|
#: src/view/screens/Settings.tsx:699
|
||||||
msgid "Clear all storage data"
|
msgid "Clear all storage data"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:713
|
#: src/view/screens/Settings.tsx:701
|
||||||
msgid "Clear all storage data (restart after this)"
|
msgid "Clear all storage data (restart after this)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -561,7 +550,7 @@ msgstr ""
|
||||||
msgid "Custom domain"
|
msgid "Custom domain"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:620
|
#: src/view/screens/Settings.tsx:608
|
||||||
msgid "Danger Zone"
|
msgid "Danger Zone"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -569,7 +558,7 @@ msgstr ""
|
||||||
#~ msgid "Dark"
|
#~ msgid "Dark"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:627
|
#: src/view/screens/Settings.tsx:615
|
||||||
msgid "Delete account"
|
msgid "Delete account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -591,7 +580,7 @@ msgstr ""
|
||||||
msgid "Delete my account"
|
msgid "Delete my account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:637
|
#: src/view/screens/Settings.tsx:625
|
||||||
msgid "Delete my account…"
|
msgid "Delete my account…"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -618,7 +607,7 @@ msgstr ""
|
||||||
msgid "Dev Server"
|
msgid "Dev Server"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:642
|
#: src/view/screens/Settings.tsx:630
|
||||||
msgid "Developer Tools"
|
msgid "Developer Tools"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -677,7 +666,7 @@ msgid "Edit list details"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Feeds.tsx:367
|
#: src/view/screens/Feeds.tsx:367
|
||||||
#: src/view/screens/SavedFeeds.tsx:75
|
#: src/view/screens/SavedFeeds.tsx:85
|
||||||
msgid "Edit My Feeds"
|
msgid "Edit My Feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -712,7 +701,7 @@ msgstr ""
|
||||||
msgid "Email Updated"
|
msgid "Email Updated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:293
|
#: src/view/screens/Settings.tsx:292
|
||||||
msgid "Email:"
|
msgid "Email:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -757,7 +746,7 @@ msgstr ""
|
||||||
msgid "Failed to load recommended feeds"
|
msgid "Failed to load recommended feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Feeds.tsx:558
|
#: src/view/screens/Feeds.tsx:559
|
||||||
msgid "Feed offline"
|
msgid "Feed offline"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -765,12 +754,12 @@ msgstr ""
|
||||||
msgid "Feed Preferences"
|
msgid "Feed Preferences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:64
|
#: src/view/shell/desktop/RightNav.tsx:65
|
||||||
#: src/view/shell/Drawer.tsx:411
|
#: src/view/shell/Drawer.tsx:411
|
||||||
msgid "Feedback"
|
msgid "Feedback"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Feeds.tsx:474
|
#: src/view/screens/Feeds.tsx:475
|
||||||
#: src/view/shell/bottom-bar/BottomBar.tsx:169
|
#: src/view/shell/bottom-bar/BottomBar.tsx:169
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:342
|
#: src/view/shell/desktop/LeftNav.tsx:342
|
||||||
#: src/view/shell/Drawer.tsx:328
|
#: src/view/shell/Drawer.tsx:328
|
||||||
|
@ -782,7 +771,7 @@ msgstr ""
|
||||||
msgid "Feeds are created by users to curate content. Choose some feeds that you find interesting."
|
msgid "Feeds are created by users to curate content. Choose some feeds that you find interesting."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:132
|
#: src/view/screens/SavedFeeds.tsx:156
|
||||||
msgid "Feeds are custom algorithms that users build with a little coding expertise. <0/> for more information."
|
msgid "Feeds are custom algorithms that users build with a little coding expertise. <0/> for more information."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -884,7 +873,7 @@ msgstr ""
|
||||||
msgid "Handle"
|
msgid "Handle"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:93
|
#: src/view/shell/desktop/RightNav.tsx:94
|
||||||
#: src/view/shell/Drawer.tsx:421
|
#: src/view/shell/Drawer.tsx:421
|
||||||
msgid "Help"
|
msgid "Help"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -901,6 +890,26 @@ msgstr ""
|
||||||
msgid "Hide user list"
|
msgid "Hide user list"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:101
|
||||||
|
msgid "Hmm, some kind of issue occured when contacting the feed server. Please let the feed owner know about this issue."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:89
|
||||||
|
msgid "Hmm, the feed server appears to be misconfigured. Please let the feed owner know about this issue."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:95
|
||||||
|
msgid "Hmm, the feed server appears to be offline. Please let the feed owner know about this issue."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:92
|
||||||
|
msgid "Hmm, the feed server gave a bad response. Please let the feed owner know about this issue."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:86
|
||||||
|
msgid "Hmmm, we're having trouble finding this feed. It may have been deleted."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/bottom-bar/BottomBar.tsx:125
|
#: src/view/shell/bottom-bar/BottomBar.tsx:125
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:306
|
#: src/view/shell/desktop/LeftNav.tsx:306
|
||||||
#: src/view/shell/Drawer.tsx:275
|
#: src/view/shell/Drawer.tsx:275
|
||||||
|
@ -908,9 +917,9 @@ msgstr ""
|
||||||
msgid "Home"
|
msgid "Home"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/pager/FeedsTabBarMobile.tsx:71
|
#: src/view/com/pager/FeedsTabBarMobile.tsx:99
|
||||||
#: src/view/screens/PreferencesHomeFeed.tsx:95
|
#: src/view/screens/PreferencesHomeFeed.tsx:95
|
||||||
#: src/view/screens/Settings.tsx:486
|
#: src/view/screens/Settings.tsx:474
|
||||||
msgid "Home Feed Preferences"
|
msgid "Home Feed Preferences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -953,12 +962,12 @@ msgstr ""
|
||||||
msgid "Invalid username or password"
|
msgid "Invalid username or password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:386
|
#: src/view/screens/Settings.tsx:385
|
||||||
msgid "Invite"
|
msgid "Invite"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/modals/InviteCodes.tsx:91
|
#: src/view/com/modals/InviteCodes.tsx:91
|
||||||
#: src/view/screens/Settings.tsx:374
|
#: src/view/screens/Settings.tsx:373
|
||||||
msgid "Invite a Friend"
|
msgid "Invite a Friend"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -991,7 +1000,7 @@ msgstr ""
|
||||||
msgid "Language Settings"
|
msgid "Language Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:546
|
#: src/view/screens/Settings.tsx:534
|
||||||
msgid "Languages"
|
msgid "Languages"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1031,7 +1040,7 @@ msgstr ""
|
||||||
#~ msgid "Light"
|
#~ msgid "Light"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/ProfileFeed.tsx:625
|
#: src/view/screens/ProfileFeed.tsx:626
|
||||||
msgid "Like this feed"
|
msgid "Like this feed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1059,7 +1068,7 @@ msgstr ""
|
||||||
msgid "Load more posts"
|
msgid "Load more posts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Notifications.tsx:120
|
#: src/view/screens/Notifications.tsx:130
|
||||||
msgid "Load new notifications"
|
msgid "Load new notifications"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1075,11 +1084,11 @@ msgstr ""
|
||||||
msgid "Local dev server"
|
msgid "Local dev server"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:104
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:133
|
||||||
msgid "Login to account that is not listed"
|
msgid "Login to account that is not listed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/ProfileFeed.tsx:477
|
#: src/view/screens/ProfileFeed.tsx:478
|
||||||
msgid "Looks like this feed is only available to users with a Bluesky account. Please sign up or sign in to view this feed!"
|
msgid "Looks like this feed is only available to users with a Bluesky account. Please sign up or sign in to view this feed!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1092,7 +1101,7 @@ msgid "Menu"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Moderation.tsx:51
|
#: src/view/screens/Moderation.tsx:51
|
||||||
#: src/view/screens/Settings.tsx:568
|
#: src/view/screens/Settings.tsx:556
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:400
|
#: src/view/shell/desktop/LeftNav.tsx:400
|
||||||
#: src/view/shell/Drawer.tsx:346
|
#: src/view/shell/Drawer.tsx:346
|
||||||
#: src/view/shell/Drawer.tsx:347
|
#: src/view/shell/Drawer.tsx:347
|
||||||
|
@ -1108,7 +1117,7 @@ msgid "More feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/profile/ProfileHeader.tsx:506
|
#: src/view/com/profile/ProfileHeader.tsx:506
|
||||||
#: src/view/screens/ProfileFeed.tsx:367
|
#: src/view/screens/ProfileFeed.tsx:368
|
||||||
#: src/view/screens/ProfileList.tsx:506
|
#: src/view/screens/ProfileList.tsx:506
|
||||||
msgid "More options"
|
msgid "More options"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1161,7 +1170,7 @@ msgstr ""
|
||||||
msgid "My Profile"
|
msgid "My Profile"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:525
|
#: src/view/screens/Settings.tsx:513
|
||||||
msgid "My Saved Feeds"
|
msgid "My Saved Feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1179,9 +1188,9 @@ msgid "New"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/feeds/FeedPage.tsx:187
|
#: src/view/com/feeds/FeedPage.tsx:187
|
||||||
#: src/view/screens/Feeds.tsx:509
|
#: src/view/screens/Feeds.tsx:510
|
||||||
#: src/view/screens/Profile.tsx:380
|
#: src/view/screens/Profile.tsx:381
|
||||||
#: src/view/screens/ProfileFeed.tsx:447
|
#: src/view/screens/ProfileFeed.tsx:448
|
||||||
#: src/view/screens/ProfileList.tsx:199
|
#: src/view/screens/ProfileList.tsx:199
|
||||||
#: src/view/screens/ProfileList.tsx:231
|
#: src/view/screens/ProfileList.tsx:231
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:255
|
#: src/view/shell/desktop/LeftNav.tsx:255
|
||||||
|
@ -1212,7 +1221,7 @@ msgstr ""
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/ProfileFeed.tsx:618
|
#: src/view/screens/ProfileFeed.tsx:619
|
||||||
#: src/view/screens/ProfileList.tsx:632
|
#: src/view/screens/ProfileList.tsx:632
|
||||||
msgid "No description"
|
msgid "No description"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1221,7 +1230,7 @@ msgstr ""
|
||||||
msgid "No result"
|
msgid "No result"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Feeds.tsx:451
|
#: src/view/screens/Feeds.tsx:452
|
||||||
msgid "No results found for \"{query}\""
|
msgid "No results found for \"{query}\""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1246,8 +1255,8 @@ msgstr ""
|
||||||
msgid "Not Applicable."
|
msgid "Not Applicable."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Notifications.tsx:87
|
#: src/view/screens/Notifications.tsx:97
|
||||||
#: src/view/screens/Notifications.tsx:111
|
#: src/view/screens/Notifications.tsx:121
|
||||||
#: src/view/shell/bottom-bar/BottomBar.tsx:196
|
#: src/view/shell/bottom-bar/BottomBar.tsx:196
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:364
|
#: src/view/shell/desktop/LeftNav.tsx:364
|
||||||
#: src/view/shell/Drawer.tsx:299
|
#: src/view/shell/Drawer.tsx:299
|
||||||
|
@ -1267,52 +1276,47 @@ msgstr ""
|
||||||
msgid "One or more images is missing alt text."
|
msgid "One or more images is missing alt text."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/pager/FeedsTabBarMobile.tsx:51
|
#: src/view/com/pager/FeedsTabBarMobile.tsx:79
|
||||||
msgid "Open navigation"
|
msgid "Open navigation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:538
|
#: src/view/screens/Settings.tsx:526
|
||||||
msgid "Opens configurable language settings"
|
msgid "Opens configurable language settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:146
|
|
||||||
#: src/view/shell/Drawer.tsx:509
|
|
||||||
msgid "Opens list of invite codes"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/view/com/modals/ChangeHandle.tsx:279
|
#: src/view/com/modals/ChangeHandle.tsx:279
|
||||||
msgid "Opens modal for using custom domain"
|
msgid "Opens modal for using custom domain"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:563
|
#: src/view/screens/Settings.tsx:551
|
||||||
msgid "Opens moderation settings"
|
msgid "Opens moderation settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:519
|
#: src/view/screens/Settings.tsx:507
|
||||||
msgid "Opens screen with all saved feeds"
|
msgid "Opens screen with all saved feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:586
|
#: src/view/screens/Settings.tsx:574
|
||||||
msgid "Opens the app password settings page"
|
msgid "Opens the app password settings page"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:478
|
#: src/view/screens/Settings.tsx:466
|
||||||
msgid "Opens the home feed preferences"
|
msgid "Opens the home feed preferences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:669
|
#: src/view/screens/Settings.tsx:657
|
||||||
msgid "Opens the storybook page"
|
msgid "Opens the storybook page"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:649
|
#: src/view/screens/Settings.tsx:637
|
||||||
msgid "Opens the system log page"
|
msgid "Opens the system log page"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:499
|
#: src/view/screens/Settings.tsx:487
|
||||||
msgid "Opens the threads preferences"
|
msgid "Opens the threads preferences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:109
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:138
|
||||||
msgid "Other account"
|
msgid "Other account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1349,7 +1353,7 @@ msgstr ""
|
||||||
msgid "Pictures meant for adults."
|
msgid "Pictures meant for adults."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:79
|
#: src/view/screens/SavedFeeds.tsx:89
|
||||||
msgid "Pinned Feeds"
|
msgid "Pinned Feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1415,7 +1419,7 @@ msgstr ""
|
||||||
msgid "Prioritize Your Follows"
|
msgid "Prioritize Your Follows"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:75
|
#: src/view/shell/desktop/RightNav.tsx:76
|
||||||
msgid "Privacy"
|
msgid "Privacy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1434,7 +1438,7 @@ msgstr ""
|
||||||
msgid "Profile"
|
msgid "Profile"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:794
|
#: src/view/screens/Settings.tsx:782
|
||||||
msgid "Protect your account by verifying your email."
|
msgid "Protect your account by verifying your email."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1476,7 +1480,7 @@ msgstr ""
|
||||||
msgid "Remove"
|
msgid "Remove"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/feeds/FeedSourceCard.tsx:92
|
#: src/view/com/feeds/FeedSourceCard.tsx:108
|
||||||
msgid "Remove {0} from my feeds?"
|
msgid "Remove {0} from my feeds?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1484,11 +1488,11 @@ msgstr ""
|
||||||
msgid "Remove account"
|
msgid "Remove account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/posts/FeedErrorMessage.tsx:106
|
#: src/view/com/posts/FeedErrorMessage.tsx:118
|
||||||
msgid "Remove feed"
|
msgid "Remove feed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/feeds/FeedSourceCard.tsx:91
|
#: src/view/com/feeds/FeedSourceCard.tsx:107
|
||||||
#: src/view/screens/ProfileFeed.tsx:278
|
#: src/view/screens/ProfileFeed.tsx:278
|
||||||
msgid "Remove from my feeds"
|
msgid "Remove from my feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1501,7 +1505,7 @@ msgstr ""
|
||||||
msgid "Remove image preview"
|
msgid "Remove image preview"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/posts/FeedErrorMessage.tsx:107
|
#: src/view/com/posts/FeedErrorMessage.tsx:119
|
||||||
msgid "Remove this feed from your saved feeds?"
|
msgid "Remove this feed from your saved feeds?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1565,7 +1569,7 @@ msgstr ""
|
||||||
msgid "Reset code"
|
msgid "Reset code"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:691
|
#: src/view/screens/Settings.tsx:679
|
||||||
msgid "Reset onboarding state"
|
msgid "Reset onboarding state"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1573,15 +1577,15 @@ msgstr ""
|
||||||
msgid "Reset password"
|
msgid "Reset password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:681
|
#: src/view/screens/Settings.tsx:669
|
||||||
msgid "Reset preferences state"
|
msgid "Reset preferences state"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:689
|
#: src/view/screens/Settings.tsx:677
|
||||||
msgid "Resets the onboarding state"
|
msgid "Resets the onboarding state"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:679
|
#: src/view/screens/Settings.tsx:667
|
||||||
msgid "Resets the preferences state"
|
msgid "Resets the preferences state"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1628,7 +1632,7 @@ msgstr ""
|
||||||
msgid "Save image crop"
|
msgid "Save image crop"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:105
|
#: src/view/screens/SavedFeeds.tsx:122
|
||||||
msgid "Saved Feeds"
|
msgid "Saved Feeds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1726,7 +1730,7 @@ msgstr ""
|
||||||
msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your following feed. This is an experimental feature."
|
msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your following feed. This is an experimental feature."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:280
|
#: src/view/screens/Settings.tsx:279
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:436
|
#: src/view/shell/desktop/LeftNav.tsx:436
|
||||||
#: src/view/shell/Drawer.tsx:380
|
#: src/view/shell/Drawer.tsx:380
|
||||||
#: src/view/shell/Drawer.tsx:381
|
#: src/view/shell/Drawer.tsx:381
|
||||||
|
@ -1751,7 +1755,7 @@ msgstr ""
|
||||||
#~ msgid "Share link"
|
#~ msgid "Share link"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:319
|
#: src/view/screens/Settings.tsx:318
|
||||||
msgid "Show"
|
msgid "Show"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1795,11 +1799,11 @@ msgstr ""
|
||||||
msgid "Sign In"
|
msgid "Sign In"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:37
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:44
|
||||||
msgid "Sign in as {0}"
|
msgid "Sign in as {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:94
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:118
|
||||||
#: src/view/com/auth/login/Login.tsx:100
|
#: src/view/com/auth/login/Login.tsx:100
|
||||||
msgid "Sign in as..."
|
msgid "Sign in as..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1823,7 +1827,7 @@ msgstr ""
|
||||||
msgid "Sign up or sign in to join the conversation"
|
msgid "Sign up or sign in to join the conversation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:330
|
#: src/view/screens/Settings.tsx:329
|
||||||
msgid "Signed in as"
|
msgid "Signed in as"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1848,11 +1852,11 @@ msgstr ""
|
||||||
msgid "Staging"
|
msgid "Staging"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:735
|
#: src/view/screens/Settings.tsx:723
|
||||||
msgid "Status page"
|
msgid "Status page"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:671
|
#: src/view/screens/Settings.tsx:659
|
||||||
msgid "Storybook"
|
msgid "Storybook"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1881,7 +1885,7 @@ msgstr ""
|
||||||
#~ msgid "System"
|
#~ msgid "System"
|
||||||
#~ msgstr ""
|
#~ msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:651
|
#: src/view/screens/Settings.tsx:639
|
||||||
msgid "System log"
|
msgid "System log"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1889,7 +1893,7 @@ msgstr ""
|
||||||
msgid "Tall"
|
msgid "Tall"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:84
|
#: src/view/shell/desktop/RightNav.tsx:85
|
||||||
msgid "Terms"
|
msgid "Terms"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1962,7 +1966,7 @@ msgid "This warning is only available for posts with media attached."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/PreferencesThreads.tsx:53
|
#: src/view/screens/PreferencesThreads.tsx:53
|
||||||
#: src/view/screens/Settings.tsx:508
|
#: src/view/screens/Settings.tsx:496
|
||||||
msgid "Thread Preferences"
|
msgid "Thread Preferences"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2069,15 +2073,15 @@ msgstr ""
|
||||||
msgid "Users"
|
msgid "Users"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:755
|
#: src/view/screens/Settings.tsx:743
|
||||||
msgid "Verify email"
|
msgid "Verify email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:780
|
#: src/view/screens/Settings.tsx:768
|
||||||
msgid "Verify my email"
|
msgid "Verify my email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:789
|
#: src/view/screens/Settings.tsx:777
|
||||||
msgid "Verify My Email"
|
msgid "Verify My Email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2102,6 +2106,10 @@ msgstr ""
|
||||||
msgid "We're so excited to have you join us!"
|
msgid "We're so excited to have you join us!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:98
|
||||||
|
msgid "We're sorry, but this content is not viewable without a Bluesky account."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Search/Search.tsx:236
|
#: src/view/screens/Search/Search.tsx:236
|
||||||
msgid "We're sorry, but your search could not be completed. Please try again in a few minutes."
|
msgid "We're sorry, but your search could not be completed. Please try again in a few minutes."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -2157,7 +2165,7 @@ msgstr ""
|
||||||
msgid "You don't have any invite codes yet! We'll send you some when you've been on Bluesky for a little longer."
|
msgid "You don't have any invite codes yet! We'll send you some when you've been on Bluesky for a little longer."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:92
|
#: src/view/screens/SavedFeeds.tsx:102
|
||||||
msgid "You don't have any pinned feeds."
|
msgid "You don't have any pinned feeds."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2165,7 +2173,7 @@ msgstr ""
|
||||||
msgid "You don't have any saved feeds!"
|
msgid "You don't have any saved feeds!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:118
|
#: src/view/screens/SavedFeeds.tsx:135
|
||||||
msgid "You don't have any saved feeds."
|
msgid "You don't have any saved feeds."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2228,12 +2236,6 @@ msgstr ""
|
||||||
msgid "Your hosting provider"
|
msgid "Your hosting provider"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:405
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:127
|
|
||||||
#: src/view/shell/Drawer.tsx:523
|
|
||||||
msgid "Your invite codes are hidden when logged in using an App Password"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/view/com/auth/onboarding/WelcomeMobile.tsx:59
|
#: src/view/com/auth/onboarding/WelcomeMobile.tsx:59
|
||||||
msgid "Your posts, likes, and blocks are public. Mutes are private."
|
msgid "Your posts, likes, and blocks are public. Mutes are private."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -21,12 +21,6 @@ msgstr ""
|
||||||
#~ msgid ". This warning is only available for posts with media attached."
|
#~ msgid ". This warning is only available for posts with media attached."
|
||||||
#~ msgstr "यह चेतावनी केवल मीडिया वाले पोस्ट के लिए उपलब्ध है।"
|
#~ msgstr "यह चेतावनी केवल मीडिया वाले पोस्ट के लिए उपलब्ध है।"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:410
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:158
|
|
||||||
#: src/view/shell/Drawer.tsx:527
|
|
||||||
msgid "{0, plural, one {# invite code available} other {# invite codes available}}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/view/com/modals/Repost.tsx:44
|
#: src/view/com/modals/Repost.tsx:44
|
||||||
msgid "{0}"
|
msgid "{0}"
|
||||||
msgstr "{0}"
|
msgstr "{0}"
|
||||||
|
@ -35,11 +29,6 @@ msgstr "{0}"
|
||||||
msgid "{0} {purposeLabel} List"
|
msgid "{0} {purposeLabel} List"
|
||||||
msgstr "{0} {purposeLabel} सूची"
|
msgstr "{0} {purposeLabel} सूची"
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:141
|
|
||||||
#: src/view/shell/Drawer.tsx:504
|
|
||||||
msgid "{invitesAvailable, plural, one {Invite codes: # available} other {Invite codes: # available}}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/view/screens/Search/Search.tsx:86
|
#: src/view/screens/Search/Search.tsx:86
|
||||||
msgid "{message}"
|
msgid "{message}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -61,12 +50,12 @@ msgid "A new version of the app is available. Please update to continue using th
|
||||||
msgstr "ऐप का एक नया संस्करण उपलब्ध है. कृपया ऐप का उपयोग जारी रखने के लिए अपडेट करें।"
|
msgstr "ऐप का एक नया संस्करण उपलब्ध है. कृपया ऐप का उपयोग जारी रखने के लिए अपडेट करें।"
|
||||||
|
|
||||||
#: src/view/com/modals/EditImage.tsx:299
|
#: src/view/com/modals/EditImage.tsx:299
|
||||||
#: src/view/screens/Settings.tsx:422
|
#: src/view/screens/Settings.tsx:410
|
||||||
msgid "Accessibility"
|
msgid "Accessibility"
|
||||||
msgstr "प्रवेर्शयोग्यता"
|
msgstr "प्रवेर्शयोग्यता"
|
||||||
|
|
||||||
#: src/view/com/auth/login/LoginForm.tsx:161
|
#: src/view/com/auth/login/LoginForm.tsx:161
|
||||||
#: src/view/screens/Settings.tsx:289
|
#: src/view/screens/Settings.tsx:288
|
||||||
msgid "Account"
|
msgid "Account"
|
||||||
msgstr "अकाउंट"
|
msgstr "अकाउंट"
|
||||||
|
|
||||||
|
@ -88,8 +77,8 @@ msgstr "सामग्री चेतावनी जोड़ें"
|
||||||
msgid "Add a user to this list"
|
msgid "Add a user to this list"
|
||||||
msgstr "इस सूची में किसी को जोड़ें"
|
msgstr "इस सूची में किसी को जोड़ें"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:358
|
#: src/view/screens/Settings.tsx:357
|
||||||
#: src/view/screens/Settings.tsx:367
|
#: src/view/screens/Settings.tsx:366
|
||||||
msgid "Add account"
|
msgid "Add account"
|
||||||
msgstr "अकाउंट जोड़ें"
|
msgstr "अकाउंट जोड़ें"
|
||||||
|
|
||||||
|
@ -140,7 +129,7 @@ msgstr "पसंद की संख्या को समायोजित
|
||||||
msgid "Adult Content"
|
msgid "Adult Content"
|
||||||
msgstr "वयस्क सामग्री"
|
msgstr "वयस्क सामग्री"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:574
|
#: src/view/screens/Settings.tsx:562
|
||||||
msgid "Advanced"
|
msgid "Advanced"
|
||||||
msgstr "विकसित"
|
msgstr "विकसित"
|
||||||
|
|
||||||
|
@ -172,7 +161,7 @@ msgstr "और"
|
||||||
msgid "App Language"
|
msgid "App Language"
|
||||||
msgstr "ऐप भाषा"
|
msgstr "ऐप भाषा"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:594
|
#: src/view/screens/Settings.tsx:582
|
||||||
msgid "App passwords"
|
msgid "App passwords"
|
||||||
msgstr "ऐप पासवर्ड"
|
msgstr "ऐप पासवर्ड"
|
||||||
|
|
||||||
|
@ -180,7 +169,7 @@ msgstr "ऐप पासवर्ड"
|
||||||
msgid "App Passwords"
|
msgid "App Passwords"
|
||||||
msgstr "ऐप पासवर्ड"
|
msgstr "ऐप पासवर्ड"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:437
|
#: src/view/screens/Settings.tsx:425
|
||||||
msgid "Appearance"
|
msgid "Appearance"
|
||||||
msgstr "दिखावट"
|
msgstr "दिखावट"
|
||||||
|
|
||||||
|
@ -205,7 +194,7 @@ msgid "Artistic or non-erotic nudity."
|
||||||
msgstr "कलात्मक या गैर-कामुक नग्नता।।"
|
msgstr "कलात्मक या गैर-कामुक नग्नता।।"
|
||||||
|
|
||||||
#: src/view/com/auth/create/CreateAccount.tsx:145
|
#: src/view/com/auth/create/CreateAccount.tsx:145
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:122
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:151
|
||||||
#: src/view/com/auth/login/ForgotPasswordForm.tsx:166
|
#: src/view/com/auth/login/ForgotPasswordForm.tsx:166
|
||||||
#: src/view/com/auth/login/LoginForm.tsx:251
|
#: src/view/com/auth/login/LoginForm.tsx:251
|
||||||
#: src/view/com/auth/login/SetNewPasswordForm.tsx:148
|
#: src/view/com/auth/login/SetNewPasswordForm.tsx:148
|
||||||
|
@ -217,7 +206,7 @@ msgstr "कलात्मक या गैर-कामुक नग्नत
|
||||||
msgid "Back"
|
msgid "Back"
|
||||||
msgstr "वापस"
|
msgstr "वापस"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:466
|
#: src/view/screens/Settings.tsx:454
|
||||||
msgid "Basics"
|
msgid "Basics"
|
||||||
msgstr "मूल बातें"
|
msgstr "मूल बातें"
|
||||||
|
|
||||||
|
@ -226,7 +215,7 @@ msgstr "मूल बातें"
|
||||||
msgid "Birthday"
|
msgid "Birthday"
|
||||||
msgstr "जन्मदिन"
|
msgstr "जन्मदिन"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:315
|
#: src/view/screens/Settings.tsx:314
|
||||||
msgid "Birthday:"
|
msgid "Birthday:"
|
||||||
msgstr "जन्मदिन:"
|
msgstr "जन्मदिन:"
|
||||||
|
|
||||||
|
@ -291,7 +280,7 @@ msgstr "ब्लूस्की एक स्वस्थ समुदाय
|
||||||
msgid "Bluesky.Social"
|
msgid "Bluesky.Social"
|
||||||
msgstr "Bluesky.Social"
|
msgstr "Bluesky.Social"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:723
|
#: src/view/screens/Settings.tsx:711
|
||||||
msgid "Build version {0} {1}"
|
msgid "Build version {0} {1}"
|
||||||
msgstr "Build version {0} {1}"
|
msgstr "Build version {0} {1}"
|
||||||
|
|
||||||
|
@ -359,12 +348,12 @@ msgstr "खोज मत करो"
|
||||||
msgid "Cancel waitlist signup"
|
msgid "Cancel waitlist signup"
|
||||||
msgstr "प्रतीक्षा सूची पंजीकरण मत करो"
|
msgstr "प्रतीक्षा सूची पंजीकरण मत करो"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:309
|
#: src/view/screens/Settings.tsx:308
|
||||||
msgid "Change"
|
msgid "Change"
|
||||||
msgstr "परिवर्तन"
|
msgstr "परिवर्तन"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:606
|
#: src/view/screens/Settings.tsx:594
|
||||||
#: src/view/screens/Settings.tsx:615
|
#: src/view/screens/Settings.tsx:603
|
||||||
msgid "Change handle"
|
msgid "Change handle"
|
||||||
msgstr "हैंडल बदलें"
|
msgstr "हैंडल बदलें"
|
||||||
|
|
||||||
|
@ -404,19 +393,19 @@ msgstr "उन एल्गोरिदम का चयन करें जो
|
||||||
msgid "Choose your password"
|
msgid "Choose your password"
|
||||||
msgstr "अपना पासवर्ड चुनें"
|
msgstr "अपना पासवर्ड चुनें"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:699
|
#: src/view/screens/Settings.tsx:687
|
||||||
msgid "Clear all legacy storage data"
|
msgid "Clear all legacy storage data"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:701
|
#: src/view/screens/Settings.tsx:689
|
||||||
msgid "Clear all legacy storage data (restart after this)"
|
msgid "Clear all legacy storage data (restart after this)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:711
|
#: src/view/screens/Settings.tsx:699
|
||||||
msgid "Clear all storage data"
|
msgid "Clear all storage data"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:713
|
#: src/view/screens/Settings.tsx:701
|
||||||
msgid "Clear all storage data (restart after this)"
|
msgid "Clear all storage data (restart after this)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -557,7 +546,7 @@ msgstr "बनाया गया {0}"
|
||||||
msgid "Custom domain"
|
msgid "Custom domain"
|
||||||
msgstr "कस्टम डोमेन"
|
msgstr "कस्टम डोमेन"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:620
|
#: src/view/screens/Settings.tsx:608
|
||||||
msgid "Danger Zone"
|
msgid "Danger Zone"
|
||||||
msgstr "खतरा क्षेत्र"
|
msgstr "खतरा क्षेत्र"
|
||||||
|
|
||||||
|
@ -565,7 +554,7 @@ msgstr "खतरा क्षेत्र"
|
||||||
#~ msgid "Dark"
|
#~ msgid "Dark"
|
||||||
#~ msgstr "डार्क मोड"
|
#~ msgstr "डार्क मोड"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:627
|
#: src/view/screens/Settings.tsx:615
|
||||||
msgid "Delete account"
|
msgid "Delete account"
|
||||||
msgstr "खाता हटाएं"
|
msgstr "खाता हटाएं"
|
||||||
|
|
||||||
|
@ -587,7 +576,7 @@ msgstr "सूची हटाएँ"
|
||||||
msgid "Delete my account"
|
msgid "Delete my account"
|
||||||
msgstr "मेरा खाता हटाएं"
|
msgstr "मेरा खाता हटाएं"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:637
|
#: src/view/screens/Settings.tsx:625
|
||||||
msgid "Delete my account…"
|
msgid "Delete my account…"
|
||||||
msgstr "मेरा खाता हटाएं…"
|
msgstr "मेरा खाता हटाएं…"
|
||||||
|
|
||||||
|
@ -614,7 +603,7 @@ msgstr "विवरण"
|
||||||
msgid "Dev Server"
|
msgid "Dev Server"
|
||||||
msgstr "देव सर्वर"
|
msgstr "देव सर्वर"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:642
|
#: src/view/screens/Settings.tsx:630
|
||||||
msgid "Developer Tools"
|
msgid "Developer Tools"
|
||||||
msgstr "डेवलपर उपकरण"
|
msgstr "डेवलपर उपकरण"
|
||||||
|
|
||||||
|
@ -673,7 +662,7 @@ msgid "Edit list details"
|
||||||
msgstr "सूची विवरण संपादित करें"
|
msgstr "सूची विवरण संपादित करें"
|
||||||
|
|
||||||
#: src/view/screens/Feeds.tsx:367
|
#: src/view/screens/Feeds.tsx:367
|
||||||
#: src/view/screens/SavedFeeds.tsx:75
|
#: src/view/screens/SavedFeeds.tsx:85
|
||||||
msgid "Edit My Feeds"
|
msgid "Edit My Feeds"
|
||||||
msgstr "मेरी फ़ीड संपादित करें"
|
msgstr "मेरी फ़ीड संपादित करें"
|
||||||
|
|
||||||
|
@ -708,7 +697,7 @@ msgstr "ईमेल"
|
||||||
msgid "Email Updated"
|
msgid "Email Updated"
|
||||||
msgstr "ईमेल अपडेट किया गया"
|
msgstr "ईमेल अपडेट किया गया"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:293
|
#: src/view/screens/Settings.tsx:292
|
||||||
msgid "Email:"
|
msgid "Email:"
|
||||||
msgstr "ईमेल:"
|
msgstr "ईमेल:"
|
||||||
|
|
||||||
|
@ -753,7 +742,7 @@ msgstr "ऑल्ट टेक्स्ट"
|
||||||
msgid "Failed to load recommended feeds"
|
msgid "Failed to load recommended feeds"
|
||||||
msgstr "अनुशंसित फ़ीड लोड करने में विफल"
|
msgstr "अनुशंसित फ़ीड लोड करने में विफल"
|
||||||
|
|
||||||
#: src/view/screens/Feeds.tsx:558
|
#: src/view/screens/Feeds.tsx:559
|
||||||
msgid "Feed offline"
|
msgid "Feed offline"
|
||||||
msgstr "फ़ीड ऑफ़लाइन है"
|
msgstr "फ़ीड ऑफ़लाइन है"
|
||||||
|
|
||||||
|
@ -761,12 +750,12 @@ msgstr "फ़ीड ऑफ़लाइन है"
|
||||||
msgid "Feed Preferences"
|
msgid "Feed Preferences"
|
||||||
msgstr "फ़ीड प्राथमिकता"
|
msgstr "फ़ीड प्राथमिकता"
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:64
|
#: src/view/shell/desktop/RightNav.tsx:65
|
||||||
#: src/view/shell/Drawer.tsx:411
|
#: src/view/shell/Drawer.tsx:411
|
||||||
msgid "Feedback"
|
msgid "Feedback"
|
||||||
msgstr "प्रतिक्रिया"
|
msgstr "प्रतिक्रिया"
|
||||||
|
|
||||||
#: src/view/screens/Feeds.tsx:474
|
#: src/view/screens/Feeds.tsx:475
|
||||||
#: src/view/shell/bottom-bar/BottomBar.tsx:169
|
#: src/view/shell/bottom-bar/BottomBar.tsx:169
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:342
|
#: src/view/shell/desktop/LeftNav.tsx:342
|
||||||
#: src/view/shell/Drawer.tsx:328
|
#: src/view/shell/Drawer.tsx:328
|
||||||
|
@ -778,7 +767,7 @@ msgstr "सभी फ़ीड"
|
||||||
msgid "Feeds are created by users to curate content. Choose some feeds that you find interesting."
|
msgid "Feeds are created by users to curate content. Choose some feeds that you find interesting."
|
||||||
msgstr "सामग्री को व्यवस्थित करने के लिए उपयोगकर्ताओं द्वारा फ़ीड बनाए जाते हैं। कुछ फ़ीड चुनें जो आपको दिलचस्प लगें।"
|
msgstr "सामग्री को व्यवस्थित करने के लिए उपयोगकर्ताओं द्वारा फ़ीड बनाए जाते हैं। कुछ फ़ीड चुनें जो आपको दिलचस्प लगें।"
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:132
|
#: src/view/screens/SavedFeeds.tsx:156
|
||||||
msgid "Feeds are custom algorithms that users build with a little coding expertise. <0/> for more information."
|
msgid "Feeds are custom algorithms that users build with a little coding expertise. <0/> for more information."
|
||||||
msgstr "फ़ीड कस्टम एल्गोरिदम हैं जिन्हें उपयोगकर्ता थोड़ी कोडिंग विशेषज्ञता के साथ बनाते हैं। <0/> अधिक जानकारी के लिए."
|
msgstr "फ़ीड कस्टम एल्गोरिदम हैं जिन्हें उपयोगकर्ता थोड़ी कोडिंग विशेषज्ञता के साथ बनाते हैं। <0/> अधिक जानकारी के लिए."
|
||||||
|
|
||||||
|
@ -876,7 +865,7 @@ msgstr "अगला"
|
||||||
msgid "Handle"
|
msgid "Handle"
|
||||||
msgstr "हैंडल"
|
msgstr "हैंडल"
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:93
|
#: src/view/shell/desktop/RightNav.tsx:94
|
||||||
#: src/view/shell/Drawer.tsx:421
|
#: src/view/shell/Drawer.tsx:421
|
||||||
msgid "Help"
|
msgid "Help"
|
||||||
msgstr "सहायता"
|
msgstr "सहायता"
|
||||||
|
@ -893,6 +882,26 @@ msgstr "इसे छिपाएं"
|
||||||
msgid "Hide user list"
|
msgid "Hide user list"
|
||||||
msgstr "उपयोगकर्ता सूची छुपाएँ"
|
msgstr "उपयोगकर्ता सूची छुपाएँ"
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:101
|
||||||
|
msgid "Hmm, some kind of issue occured when contacting the feed server. Please let the feed owner know about this issue."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:89
|
||||||
|
msgid "Hmm, the feed server appears to be misconfigured. Please let the feed owner know about this issue."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:95
|
||||||
|
msgid "Hmm, the feed server appears to be offline. Please let the feed owner know about this issue."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:92
|
||||||
|
msgid "Hmm, the feed server gave a bad response. Please let the feed owner know about this issue."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:86
|
||||||
|
msgid "Hmmm, we're having trouble finding this feed. It may have been deleted."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/shell/bottom-bar/BottomBar.tsx:125
|
#: src/view/shell/bottom-bar/BottomBar.tsx:125
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:306
|
#: src/view/shell/desktop/LeftNav.tsx:306
|
||||||
#: src/view/shell/Drawer.tsx:275
|
#: src/view/shell/Drawer.tsx:275
|
||||||
|
@ -900,9 +909,9 @@ msgstr "उपयोगकर्ता सूची छुपाएँ"
|
||||||
msgid "Home"
|
msgid "Home"
|
||||||
msgstr "होम फीड"
|
msgstr "होम फीड"
|
||||||
|
|
||||||
#: src/view/com/pager/FeedsTabBarMobile.tsx:71
|
#: src/view/com/pager/FeedsTabBarMobile.tsx:99
|
||||||
#: src/view/screens/PreferencesHomeFeed.tsx:95
|
#: src/view/screens/PreferencesHomeFeed.tsx:95
|
||||||
#: src/view/screens/Settings.tsx:486
|
#: src/view/screens/Settings.tsx:474
|
||||||
msgid "Home Feed Preferences"
|
msgid "Home Feed Preferences"
|
||||||
msgstr "होम फ़ीड प्राथमिकताएं"
|
msgstr "होम फ़ीड प्राथमिकताएं"
|
||||||
|
|
||||||
|
@ -945,12 +954,12 @@ msgstr "छवि विकल्प"
|
||||||
msgid "Invalid username or password"
|
msgid "Invalid username or password"
|
||||||
msgstr "अवैध उपयोगकर्ता नाम या पासवर्ड"
|
msgstr "अवैध उपयोगकर्ता नाम या पासवर्ड"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:386
|
#: src/view/screens/Settings.tsx:385
|
||||||
msgid "Invite"
|
msgid "Invite"
|
||||||
msgstr "आमंत्रण भेजो"
|
msgstr "आमंत्रण भेजो"
|
||||||
|
|
||||||
#: src/view/com/modals/InviteCodes.tsx:91
|
#: src/view/com/modals/InviteCodes.tsx:91
|
||||||
#: src/view/screens/Settings.tsx:374
|
#: src/view/screens/Settings.tsx:373
|
||||||
msgid "Invite a Friend"
|
msgid "Invite a Friend"
|
||||||
msgstr "एक दोस्त को आमंत्रित करें"
|
msgstr "एक दोस्त को आमंत्रित करें"
|
||||||
|
|
||||||
|
@ -983,7 +992,7 @@ msgstr "अपनी भाषा चुने"
|
||||||
msgid "Language Settings"
|
msgid "Language Settings"
|
||||||
msgstr "भाषा सेटिंग्स"
|
msgstr "भाषा सेटिंग्स"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:546
|
#: src/view/screens/Settings.tsx:534
|
||||||
msgid "Languages"
|
msgid "Languages"
|
||||||
msgstr "भाषा"
|
msgstr "भाषा"
|
||||||
|
|
||||||
|
@ -1023,7 +1032,7 @@ msgstr "चित्र पुस्तकालय"
|
||||||
#~ msgid "Light"
|
#~ msgid "Light"
|
||||||
#~ msgstr "लाइट मोड"
|
#~ msgstr "लाइट मोड"
|
||||||
|
|
||||||
#: src/view/screens/ProfileFeed.tsx:625
|
#: src/view/screens/ProfileFeed.tsx:626
|
||||||
msgid "Like this feed"
|
msgid "Like this feed"
|
||||||
msgstr "इस फ़ीड को लाइक करो"
|
msgstr "इस फ़ीड को लाइक करो"
|
||||||
|
|
||||||
|
@ -1051,7 +1060,7 @@ msgstr "सूची"
|
||||||
msgid "Load more posts"
|
msgid "Load more posts"
|
||||||
msgstr "अधिक पोस्ट लोड करें"
|
msgstr "अधिक पोस्ट लोड करें"
|
||||||
|
|
||||||
#: src/view/screens/Notifications.tsx:120
|
#: src/view/screens/Notifications.tsx:130
|
||||||
msgid "Load new notifications"
|
msgid "Load new notifications"
|
||||||
msgstr "नई सूचनाएं लोड करें"
|
msgstr "नई सूचनाएं लोड करें"
|
||||||
|
|
||||||
|
@ -1067,11 +1076,11 @@ msgstr ""
|
||||||
msgid "Local dev server"
|
msgid "Local dev server"
|
||||||
msgstr "स्थानीय देव सर्वर"
|
msgstr "स्थानीय देव सर्वर"
|
||||||
|
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:104
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:133
|
||||||
msgid "Login to account that is not listed"
|
msgid "Login to account that is not listed"
|
||||||
msgstr "उस खाते में लॉग इन करें जो सूचीबद्ध नहीं है"
|
msgstr "उस खाते में लॉग इन करें जो सूचीबद्ध नहीं है"
|
||||||
|
|
||||||
#: src/view/screens/ProfileFeed.tsx:477
|
#: src/view/screens/ProfileFeed.tsx:478
|
||||||
msgid "Looks like this feed is only available to users with a Bluesky account. Please sign up or sign in to view this feed!"
|
msgid "Looks like this feed is only available to users with a Bluesky account. Please sign up or sign in to view this feed!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1084,7 +1093,7 @@ msgid "Menu"
|
||||||
msgstr "मेनू"
|
msgstr "मेनू"
|
||||||
|
|
||||||
#: src/view/screens/Moderation.tsx:51
|
#: src/view/screens/Moderation.tsx:51
|
||||||
#: src/view/screens/Settings.tsx:568
|
#: src/view/screens/Settings.tsx:556
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:400
|
#: src/view/shell/desktop/LeftNav.tsx:400
|
||||||
#: src/view/shell/Drawer.tsx:346
|
#: src/view/shell/Drawer.tsx:346
|
||||||
#: src/view/shell/Drawer.tsx:347
|
#: src/view/shell/Drawer.tsx:347
|
||||||
|
@ -1100,7 +1109,7 @@ msgid "More feeds"
|
||||||
msgstr "अधिक फ़ीड"
|
msgstr "अधिक फ़ीड"
|
||||||
|
|
||||||
#: src/view/com/profile/ProfileHeader.tsx:506
|
#: src/view/com/profile/ProfileHeader.tsx:506
|
||||||
#: src/view/screens/ProfileFeed.tsx:367
|
#: src/view/screens/ProfileFeed.tsx:368
|
||||||
#: src/view/screens/ProfileList.tsx:506
|
#: src/view/screens/ProfileList.tsx:506
|
||||||
msgid "More options"
|
msgid "More options"
|
||||||
msgstr "अधिक विकल्प"
|
msgstr "अधिक विकल्प"
|
||||||
|
@ -1153,7 +1162,7 @@ msgstr "मेरी फ़ीड"
|
||||||
msgid "My Profile"
|
msgid "My Profile"
|
||||||
msgstr "मेरी प्रोफाइल"
|
msgstr "मेरी प्रोफाइल"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:525
|
#: src/view/screens/Settings.tsx:513
|
||||||
msgid "My Saved Feeds"
|
msgid "My Saved Feeds"
|
||||||
msgstr "मेरी फ़ीड"
|
msgstr "मेरी फ़ीड"
|
||||||
|
|
||||||
|
@ -1171,9 +1180,9 @@ msgid "New"
|
||||||
msgstr "नया"
|
msgstr "नया"
|
||||||
|
|
||||||
#: src/view/com/feeds/FeedPage.tsx:187
|
#: src/view/com/feeds/FeedPage.tsx:187
|
||||||
#: src/view/screens/Feeds.tsx:509
|
#: src/view/screens/Feeds.tsx:510
|
||||||
#: src/view/screens/Profile.tsx:380
|
#: src/view/screens/Profile.tsx:381
|
||||||
#: src/view/screens/ProfileFeed.tsx:447
|
#: src/view/screens/ProfileFeed.tsx:448
|
||||||
#: src/view/screens/ProfileList.tsx:199
|
#: src/view/screens/ProfileList.tsx:199
|
||||||
#: src/view/screens/ProfileList.tsx:231
|
#: src/view/screens/ProfileList.tsx:231
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:255
|
#: src/view/shell/desktop/LeftNav.tsx:255
|
||||||
|
@ -1204,7 +1213,7 @@ msgstr "अगली फोटो"
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr "नहीं"
|
msgstr "नहीं"
|
||||||
|
|
||||||
#: src/view/screens/ProfileFeed.tsx:618
|
#: src/view/screens/ProfileFeed.tsx:619
|
||||||
#: src/view/screens/ProfileList.tsx:632
|
#: src/view/screens/ProfileList.tsx:632
|
||||||
msgid "No description"
|
msgid "No description"
|
||||||
msgstr "कोई विवरण नहीं"
|
msgstr "कोई विवरण नहीं"
|
||||||
|
@ -1213,7 +1222,7 @@ msgstr "कोई विवरण नहीं"
|
||||||
msgid "No result"
|
msgid "No result"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Feeds.tsx:451
|
#: src/view/screens/Feeds.tsx:452
|
||||||
msgid "No results found for \"{query}\""
|
msgid "No results found for \"{query}\""
|
||||||
msgstr "\"{query}\" के लिए कोई परिणाम नहीं मिला"
|
msgstr "\"{query}\" के लिए कोई परिणाम नहीं मिला"
|
||||||
|
|
||||||
|
@ -1238,8 +1247,8 @@ msgstr ""
|
||||||
msgid "Not Applicable."
|
msgid "Not Applicable."
|
||||||
msgstr "लागू नहीं।"
|
msgstr "लागू नहीं।"
|
||||||
|
|
||||||
#: src/view/screens/Notifications.tsx:87
|
#: src/view/screens/Notifications.tsx:97
|
||||||
#: src/view/screens/Notifications.tsx:111
|
#: src/view/screens/Notifications.tsx:121
|
||||||
#: src/view/shell/bottom-bar/BottomBar.tsx:196
|
#: src/view/shell/bottom-bar/BottomBar.tsx:196
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:364
|
#: src/view/shell/desktop/LeftNav.tsx:364
|
||||||
#: src/view/shell/Drawer.tsx:299
|
#: src/view/shell/Drawer.tsx:299
|
||||||
|
@ -1259,52 +1268,47 @@ msgstr "ठीक है"
|
||||||
msgid "One or more images is missing alt text."
|
msgid "One or more images is missing alt text."
|
||||||
msgstr "एक या अधिक छवियाँ alt पाठ याद आती हैं।।"
|
msgstr "एक या अधिक छवियाँ alt पाठ याद आती हैं।।"
|
||||||
|
|
||||||
#: src/view/com/pager/FeedsTabBarMobile.tsx:51
|
#: src/view/com/pager/FeedsTabBarMobile.tsx:79
|
||||||
msgid "Open navigation"
|
msgid "Open navigation"
|
||||||
msgstr "ओपन नेविगेशन"
|
msgstr "ओपन नेविगेशन"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:538
|
#: src/view/screens/Settings.tsx:526
|
||||||
msgid "Opens configurable language settings"
|
msgid "Opens configurable language settings"
|
||||||
msgstr "भाषा सेटिंग्स खोलें"
|
msgstr "भाषा सेटिंग्स खोलें"
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:146
|
|
||||||
#: src/view/shell/Drawer.tsx:509
|
|
||||||
msgid "Opens list of invite codes"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/view/com/modals/ChangeHandle.tsx:279
|
#: src/view/com/modals/ChangeHandle.tsx:279
|
||||||
msgid "Opens modal for using custom domain"
|
msgid "Opens modal for using custom domain"
|
||||||
msgstr "कस्टम डोमेन का उपयोग करने के लिए मोडल खोलें"
|
msgstr "कस्टम डोमेन का उपयोग करने के लिए मोडल खोलें"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:563
|
#: src/view/screens/Settings.tsx:551
|
||||||
msgid "Opens moderation settings"
|
msgid "Opens moderation settings"
|
||||||
msgstr "मॉडरेशन सेटिंग्स खोलें"
|
msgstr "मॉडरेशन सेटिंग्स खोलें"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:519
|
#: src/view/screens/Settings.tsx:507
|
||||||
msgid "Opens screen with all saved feeds"
|
msgid "Opens screen with all saved feeds"
|
||||||
msgstr "सभी बचाया फ़ीड के साथ स्क्रीन खोलें"
|
msgstr "सभी बचाया फ़ीड के साथ स्क्रीन खोलें"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:586
|
#: src/view/screens/Settings.tsx:574
|
||||||
msgid "Opens the app password settings page"
|
msgid "Opens the app password settings page"
|
||||||
msgstr "ऐप पासवर्ड सेटिंग पेज खोलें"
|
msgstr "ऐप पासवर्ड सेटिंग पेज खोलें"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:478
|
#: src/view/screens/Settings.tsx:466
|
||||||
msgid "Opens the home feed preferences"
|
msgid "Opens the home feed preferences"
|
||||||
msgstr "होम फीड वरीयताओं को खोलता है"
|
msgstr "होम फीड वरीयताओं को खोलता है"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:669
|
#: src/view/screens/Settings.tsx:657
|
||||||
msgid "Opens the storybook page"
|
msgid "Opens the storybook page"
|
||||||
msgstr "स्टोरीबुक पेज खोलें"
|
msgstr "स्टोरीबुक पेज खोलें"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:649
|
#: src/view/screens/Settings.tsx:637
|
||||||
msgid "Opens the system log page"
|
msgid "Opens the system log page"
|
||||||
msgstr "सिस्टम लॉग पेज खोलें"
|
msgstr "सिस्टम लॉग पेज खोलें"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:499
|
#: src/view/screens/Settings.tsx:487
|
||||||
msgid "Opens the threads preferences"
|
msgid "Opens the threads preferences"
|
||||||
msgstr "धागे वरीयताओं को खोलता है"
|
msgstr "धागे वरीयताओं को खोलता है"
|
||||||
|
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:109
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:138
|
||||||
msgid "Other account"
|
msgid "Other account"
|
||||||
msgstr "अन्य खाता"
|
msgstr "अन्य खाता"
|
||||||
|
|
||||||
|
@ -1341,7 +1345,7 @@ msgstr "पासवर्ड अद्यतन!"
|
||||||
msgid "Pictures meant for adults."
|
msgid "Pictures meant for adults."
|
||||||
msgstr "चित्र वयस्कों के लिए थे।।"
|
msgstr "चित्र वयस्कों के लिए थे।।"
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:79
|
#: src/view/screens/SavedFeeds.tsx:89
|
||||||
msgid "Pinned Feeds"
|
msgid "Pinned Feeds"
|
||||||
msgstr "पिन किया गया फ़ीड"
|
msgstr "पिन किया गया फ़ीड"
|
||||||
|
|
||||||
|
@ -1407,7 +1411,7 @@ msgstr "प्राथमिक भाषा"
|
||||||
msgid "Prioritize Your Follows"
|
msgid "Prioritize Your Follows"
|
||||||
msgstr "अपने फ़ॉलोअर्स को प्राथमिकता दें"
|
msgstr "अपने फ़ॉलोअर्स को प्राथमिकता दें"
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:75
|
#: src/view/shell/desktop/RightNav.tsx:76
|
||||||
msgid "Privacy"
|
msgid "Privacy"
|
||||||
msgstr "गोपनीयता"
|
msgstr "गोपनीयता"
|
||||||
|
|
||||||
|
@ -1426,7 +1430,7 @@ msgstr "प्रसंस्करण..."
|
||||||
msgid "Profile"
|
msgid "Profile"
|
||||||
msgstr "प्रोफ़ाइल"
|
msgstr "प्रोफ़ाइल"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:794
|
#: src/view/screens/Settings.tsx:782
|
||||||
msgid "Protect your account by verifying your email."
|
msgid "Protect your account by verifying your email."
|
||||||
msgstr "अपने ईमेल को सत्यापित करके अपने खाते को सुरक्षित रखें।।"
|
msgstr "अपने ईमेल को सत्यापित करके अपने खाते को सुरक्षित रखें।।"
|
||||||
|
|
||||||
|
@ -1468,7 +1472,7 @@ msgstr "अनुशंसित लोग"
|
||||||
msgid "Remove"
|
msgid "Remove"
|
||||||
msgstr "निकालें"
|
msgstr "निकालें"
|
||||||
|
|
||||||
#: src/view/com/feeds/FeedSourceCard.tsx:92
|
#: src/view/com/feeds/FeedSourceCard.tsx:108
|
||||||
msgid "Remove {0} from my feeds?"
|
msgid "Remove {0} from my feeds?"
|
||||||
msgstr "मेरे फ़ीड से {0} हटाएं?"
|
msgstr "मेरे फ़ीड से {0} हटाएं?"
|
||||||
|
|
||||||
|
@ -1476,11 +1480,11 @@ msgstr "मेरे फ़ीड से {0} हटाएं?"
|
||||||
msgid "Remove account"
|
msgid "Remove account"
|
||||||
msgstr "खाता हटाएं"
|
msgstr "खाता हटाएं"
|
||||||
|
|
||||||
#: src/view/com/posts/FeedErrorMessage.tsx:106
|
#: src/view/com/posts/FeedErrorMessage.tsx:118
|
||||||
msgid "Remove feed"
|
msgid "Remove feed"
|
||||||
msgstr "फ़ीड हटाएँ"
|
msgstr "फ़ीड हटाएँ"
|
||||||
|
|
||||||
#: src/view/com/feeds/FeedSourceCard.tsx:91
|
#: src/view/com/feeds/FeedSourceCard.tsx:107
|
||||||
#: src/view/screens/ProfileFeed.tsx:278
|
#: src/view/screens/ProfileFeed.tsx:278
|
||||||
msgid "Remove from my feeds"
|
msgid "Remove from my feeds"
|
||||||
msgstr "मेरे फ़ीड से हटाएँ"
|
msgstr "मेरे फ़ीड से हटाएँ"
|
||||||
|
@ -1493,7 +1497,7 @@ msgstr "छवि निकालें"
|
||||||
msgid "Remove image preview"
|
msgid "Remove image preview"
|
||||||
msgstr "छवि पूर्वावलोकन निकालें"
|
msgstr "छवि पूर्वावलोकन निकालें"
|
||||||
|
|
||||||
#: src/view/com/posts/FeedErrorMessage.tsx:107
|
#: src/view/com/posts/FeedErrorMessage.tsx:119
|
||||||
msgid "Remove this feed from your saved feeds?"
|
msgid "Remove this feed from your saved feeds?"
|
||||||
msgstr "इस फ़ीड को सहेजे गए फ़ीड से हटा दें?"
|
msgstr "इस फ़ीड को सहेजे गए फ़ीड से हटा दें?"
|
||||||
|
|
||||||
|
@ -1557,7 +1561,7 @@ msgstr "इस प्रदाता के लिए आवश्यक"
|
||||||
msgid "Reset code"
|
msgid "Reset code"
|
||||||
msgstr "कोड रीसेट करें"
|
msgstr "कोड रीसेट करें"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:691
|
#: src/view/screens/Settings.tsx:679
|
||||||
msgid "Reset onboarding state"
|
msgid "Reset onboarding state"
|
||||||
msgstr "ऑनबोर्डिंग स्टेट को रीसेट करें"
|
msgstr "ऑनबोर्डिंग स्टेट को रीसेट करें"
|
||||||
|
|
||||||
|
@ -1565,15 +1569,15 @@ msgstr "ऑनबोर्डिंग स्टेट को रीसेट
|
||||||
msgid "Reset password"
|
msgid "Reset password"
|
||||||
msgstr "पासवर्ड रीसेट"
|
msgstr "पासवर्ड रीसेट"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:681
|
#: src/view/screens/Settings.tsx:669
|
||||||
msgid "Reset preferences state"
|
msgid "Reset preferences state"
|
||||||
msgstr "प्राथमिकताओं को रीसेट करें"
|
msgstr "प्राथमिकताओं को रीसेट करें"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:689
|
#: src/view/screens/Settings.tsx:677
|
||||||
msgid "Resets the onboarding state"
|
msgid "Resets the onboarding state"
|
||||||
msgstr "ऑनबोर्डिंग स्टेट को रीसेट करें"
|
msgstr "ऑनबोर्डिंग स्टेट को रीसेट करें"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:679
|
#: src/view/screens/Settings.tsx:667
|
||||||
msgid "Resets the preferences state"
|
msgid "Resets the preferences state"
|
||||||
msgstr "प्राथमिकताओं की स्थिति को रीसेट करें"
|
msgstr "प्राथमिकताओं की स्थिति को रीसेट करें"
|
||||||
|
|
||||||
|
@ -1620,7 +1624,7 @@ msgstr "बदलाव सेव करो"
|
||||||
msgid "Save image crop"
|
msgid "Save image crop"
|
||||||
msgstr "फोटो बदलाव सेव करो"
|
msgstr "फोटो बदलाव सेव करो"
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:105
|
#: src/view/screens/SavedFeeds.tsx:122
|
||||||
msgid "Saved Feeds"
|
msgid "Saved Feeds"
|
||||||
msgstr "सहेजे गए फ़ीड"
|
msgstr "सहेजे गए फ़ीड"
|
||||||
|
|
||||||
|
@ -1718,7 +1722,7 @@ msgstr "इस सेटिंग को \"हाँ\" में सेट क
|
||||||
msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your following feed. This is an experimental feature."
|
msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your following feed. This is an experimental feature."
|
||||||
msgstr "इस सेटिंग को अपने निम्नलिखित फ़ीड में अपने सहेजे गए फ़ीड के नमूने दिखाने के लिए \"हाँ\" पर सेट करें। यह एक प्रयोगात्मक विशेषता है।।"
|
msgstr "इस सेटिंग को अपने निम्नलिखित फ़ीड में अपने सहेजे गए फ़ीड के नमूने दिखाने के लिए \"हाँ\" पर सेट करें। यह एक प्रयोगात्मक विशेषता है।।"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:280
|
#: src/view/screens/Settings.tsx:279
|
||||||
#: src/view/shell/desktop/LeftNav.tsx:436
|
#: src/view/shell/desktop/LeftNav.tsx:436
|
||||||
#: src/view/shell/Drawer.tsx:380
|
#: src/view/shell/Drawer.tsx:380
|
||||||
#: src/view/shell/Drawer.tsx:381
|
#: src/view/shell/Drawer.tsx:381
|
||||||
|
@ -1743,7 +1747,7 @@ msgstr ""
|
||||||
#~ msgid "Share link"
|
#~ msgid "Share link"
|
||||||
#~ msgstr "लिंक शेयर करें"
|
#~ msgstr "लिंक शेयर करें"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:319
|
#: src/view/screens/Settings.tsx:318
|
||||||
msgid "Show"
|
msgid "Show"
|
||||||
msgstr "दिखाओ"
|
msgstr "दिखाओ"
|
||||||
|
|
||||||
|
@ -1787,11 +1791,11 @@ msgstr "साइन इन करें"
|
||||||
msgid "Sign In"
|
msgid "Sign In"
|
||||||
msgstr "साइन इन करें"
|
msgstr "साइन इन करें"
|
||||||
|
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:37
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:44
|
||||||
msgid "Sign in as {0}"
|
msgid "Sign in as {0}"
|
||||||
msgstr "{0} के रूप में साइन इन करें"
|
msgstr "{0} के रूप में साइन इन करें"
|
||||||
|
|
||||||
#: src/view/com/auth/login/ChooseAccountForm.tsx:94
|
#: src/view/com/auth/login/ChooseAccountForm.tsx:118
|
||||||
#: src/view/com/auth/login/Login.tsx:100
|
#: src/view/com/auth/login/Login.tsx:100
|
||||||
msgid "Sign in as..."
|
msgid "Sign in as..."
|
||||||
msgstr "... के रूप में साइन इन करें"
|
msgstr "... के रूप में साइन इन करें"
|
||||||
|
@ -1815,7 +1819,7 @@ msgstr ""
|
||||||
msgid "Sign up or sign in to join the conversation"
|
msgid "Sign up or sign in to join the conversation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:330
|
#: src/view/screens/Settings.tsx:329
|
||||||
msgid "Signed in as"
|
msgid "Signed in as"
|
||||||
msgstr "आपने इस रूप में साइन इन करा है:"
|
msgstr "आपने इस रूप में साइन इन करा है:"
|
||||||
|
|
||||||
|
@ -1840,11 +1844,11 @@ msgstr "स्क्वायर"
|
||||||
msgid "Staging"
|
msgid "Staging"
|
||||||
msgstr "स्टेजिंग"
|
msgstr "स्टेजिंग"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:735
|
#: src/view/screens/Settings.tsx:723
|
||||||
msgid "Status page"
|
msgid "Status page"
|
||||||
msgstr "स्थिति पृष्ठ"
|
msgstr "स्थिति पृष्ठ"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:671
|
#: src/view/screens/Settings.tsx:659
|
||||||
msgid "Storybook"
|
msgid "Storybook"
|
||||||
msgstr "Storybook"
|
msgstr "Storybook"
|
||||||
|
|
||||||
|
@ -1873,7 +1877,7 @@ msgstr "खाते बदलें"
|
||||||
#~ msgid "System"
|
#~ msgid "System"
|
||||||
#~ msgstr "प्रणाली"
|
#~ msgstr "प्रणाली"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:651
|
#: src/view/screens/Settings.tsx:639
|
||||||
msgid "System log"
|
msgid "System log"
|
||||||
msgstr "सिस्टम लॉग"
|
msgstr "सिस्टम लॉग"
|
||||||
|
|
||||||
|
@ -1881,7 +1885,7 @@ msgstr "सिस्टम लॉग"
|
||||||
msgid "Tall"
|
msgid "Tall"
|
||||||
msgstr "लंबा"
|
msgstr "लंबा"
|
||||||
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:84
|
#: src/view/shell/desktop/RightNav.tsx:85
|
||||||
msgid "Terms"
|
msgid "Terms"
|
||||||
msgstr "शर्तें"
|
msgstr "शर्तें"
|
||||||
|
|
||||||
|
@ -1954,7 +1958,7 @@ msgid "This warning is only available for posts with media attached."
|
||||||
msgstr "यह चेतावनी केवल मीडिया संलग्न पोस्ट के लिए उपलब्ध है।"
|
msgstr "यह चेतावनी केवल मीडिया संलग्न पोस्ट के लिए उपलब्ध है।"
|
||||||
|
|
||||||
#: src/view/screens/PreferencesThreads.tsx:53
|
#: src/view/screens/PreferencesThreads.tsx:53
|
||||||
#: src/view/screens/Settings.tsx:508
|
#: src/view/screens/Settings.tsx:496
|
||||||
msgid "Thread Preferences"
|
msgid "Thread Preferences"
|
||||||
msgstr "थ्रेड प्राथमिकता"
|
msgstr "थ्रेड प्राथमिकता"
|
||||||
|
|
||||||
|
@ -2061,15 +2065,15 @@ msgstr "यूजर नाम या ईमेल पता"
|
||||||
msgid "Users"
|
msgid "Users"
|
||||||
msgstr "यूजर लोग"
|
msgstr "यूजर लोग"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:755
|
#: src/view/screens/Settings.tsx:743
|
||||||
msgid "Verify email"
|
msgid "Verify email"
|
||||||
msgstr "ईमेल सत्यापित करें"
|
msgstr "ईमेल सत्यापित करें"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:780
|
#: src/view/screens/Settings.tsx:768
|
||||||
msgid "Verify my email"
|
msgid "Verify my email"
|
||||||
msgstr "मेरी ईमेल सत्यापित करें"
|
msgstr "मेरी ईमेल सत्यापित करें"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:789
|
#: src/view/screens/Settings.tsx:777
|
||||||
msgid "Verify My Email"
|
msgid "Verify My Email"
|
||||||
msgstr "मेरी ईमेल सत्यापित करें"
|
msgstr "मेरी ईमेल सत्यापित करें"
|
||||||
|
|
||||||
|
@ -2094,6 +2098,10 @@ msgstr "साइट पर जाएं"
|
||||||
msgid "We're so excited to have you join us!"
|
msgid "We're so excited to have you join us!"
|
||||||
msgstr "हम आपके हमारी सेवा में शामिल होने को लेकर बहुत उत्साहित हैं!"
|
msgstr "हम आपके हमारी सेवा में शामिल होने को लेकर बहुत उत्साहित हैं!"
|
||||||
|
|
||||||
|
#: src/view/com/posts/FeedErrorMessage.tsx:98
|
||||||
|
msgid "We're sorry, but this content is not viewable without a Bluesky account."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/Search/Search.tsx:236
|
#: src/view/screens/Search/Search.tsx:236
|
||||||
msgid "We're sorry, but your search could not be completed. Please try again in a few minutes."
|
msgid "We're sorry, but your search could not be completed. Please try again in a few minutes."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -2149,7 +2157,7 @@ msgstr "अब आप अपने नए पासवर्ड के साथ
|
||||||
msgid "You don't have any invite codes yet! We'll send you some when you've been on Bluesky for a little longer."
|
msgid "You don't have any invite codes yet! We'll send you some when you've been on Bluesky for a little longer."
|
||||||
msgstr "आपके पास अभी तक कोई आमंत्रण कोड नहीं है! जब आप कुछ अधिक समय के लिए Bluesky पर रहेंगे तो हम आपको कुछ भेजेंगे।"
|
msgstr "आपके पास अभी तक कोई आमंत्रण कोड नहीं है! जब आप कुछ अधिक समय के लिए Bluesky पर रहेंगे तो हम आपको कुछ भेजेंगे।"
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:92
|
#: src/view/screens/SavedFeeds.tsx:102
|
||||||
msgid "You don't have any pinned feeds."
|
msgid "You don't have any pinned feeds."
|
||||||
msgstr "आपके पास कोई पिन किया हुआ फ़ीड नहीं है."
|
msgstr "आपके पास कोई पिन किया हुआ फ़ीड नहीं है."
|
||||||
|
|
||||||
|
@ -2157,7 +2165,7 @@ msgstr "आपके पास कोई पिन किया हुआ फ़
|
||||||
msgid "You don't have any saved feeds!"
|
msgid "You don't have any saved feeds!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/view/screens/SavedFeeds.tsx:118
|
#: src/view/screens/SavedFeeds.tsx:135
|
||||||
msgid "You don't have any saved feeds."
|
msgid "You don't have any saved feeds."
|
||||||
msgstr "आपके पास कोई सहेजी गई फ़ीड नहीं है."
|
msgstr "आपके पास कोई सहेजी गई फ़ीड नहीं है."
|
||||||
|
|
||||||
|
@ -2220,12 +2228,6 @@ msgstr "आपका पूरा हैंडल होगा"
|
||||||
msgid "Your hosting provider"
|
msgid "Your hosting provider"
|
||||||
msgstr "आपका होस्टिंग प्रदाता"
|
msgstr "आपका होस्टिंग प्रदाता"
|
||||||
|
|
||||||
#: src/view/screens/Settings.tsx:405
|
|
||||||
#: src/view/shell/desktop/RightNav.tsx:127
|
|
||||||
#: src/view/shell/Drawer.tsx:523
|
|
||||||
msgid "Your invite codes are hidden when logged in using an App Password"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/view/com/auth/onboarding/WelcomeMobile.tsx:59
|
#: src/view/com/auth/onboarding/WelcomeMobile.tsx:59
|
||||||
msgid "Your posts, likes, and blocks are public. Mutes are private."
|
msgid "Your posts, likes, and blocks are public. Mutes are private."
|
||||||
msgstr "आपकी पोस्ट, पसंद और ब्लॉक सार्वजनिक हैं। म्यूट निजी हैं।।"
|
msgstr "आपकी पोस्ट, पसंद और ब्लॉक सार्वजनिक हैं। म्यूट निजी हैं।।"
|
||||||
|
|
|
@ -288,16 +288,13 @@ export class Logger {
|
||||||
*/
|
*/
|
||||||
export const logger = new Logger()
|
export const logger = new Logger()
|
||||||
|
|
||||||
/**
|
|
||||||
* Report to console in dev, Sentry in prod, nothing in test.
|
|
||||||
*/
|
|
||||||
if (env.IS_DEV && !env.IS_TEST) {
|
if (env.IS_DEV && !env.IS_TEST) {
|
||||||
logger.addTransport(consoleTransport)
|
logger.addTransport(consoleTransport)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uncomment this to test Sentry in dev
|
* Comment this out to disable Sentry transport in dev
|
||||||
*/
|
*/
|
||||||
// logger.addTransport(sentryTransport);
|
logger.addTransport(sentryTransport)
|
||||||
} else if (env.IS_PROD) {
|
} else if (env.IS_PROD) {
|
||||||
// logger.addTransport(sentryTransport)
|
logger.addTransport(sentryTransport)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,13 @@ import {useMemo} from 'react'
|
||||||
import {FeedTuner} from '#/lib/api/feed-manip'
|
import {FeedTuner} from '#/lib/api/feed-manip'
|
||||||
import {FeedDescriptor} from '../queries/post-feed'
|
import {FeedDescriptor} from '../queries/post-feed'
|
||||||
import {useLanguagePrefs} from './languages'
|
import {useLanguagePrefs} from './languages'
|
||||||
|
import {usePreferencesQuery} from '../queries/preferences'
|
||||||
|
import {useSession} from '../session'
|
||||||
|
|
||||||
export function useFeedTuners(feedDesc: FeedDescriptor) {
|
export function useFeedTuners(feedDesc: FeedDescriptor) {
|
||||||
const langPrefs = useLanguagePrefs()
|
const langPrefs = useLanguagePrefs()
|
||||||
|
const {data: preferences} = usePreferencesQuery()
|
||||||
|
const {currentAccount} = useSession()
|
||||||
|
|
||||||
return useMemo(() => {
|
return useMemo(() => {
|
||||||
if (feedDesc.startsWith('feedgen')) {
|
if (feedDesc.startsWith('feedgen')) {
|
||||||
|
@ -19,30 +23,30 @@ export function useFeedTuners(feedDesc: FeedDescriptor) {
|
||||||
if (feedDesc === 'home' || feedDesc === 'following') {
|
if (feedDesc === 'home' || feedDesc === 'following') {
|
||||||
const feedTuners = []
|
const feedTuners = []
|
||||||
|
|
||||||
if (false /*TODOthis.homeFeed.hideReposts*/) {
|
if (preferences?.feedViewPrefs.hideReposts) {
|
||||||
feedTuners.push(FeedTuner.removeReposts)
|
feedTuners.push(FeedTuner.removeReposts)
|
||||||
} else {
|
} else {
|
||||||
feedTuners.push(FeedTuner.dedupReposts)
|
feedTuners.push(FeedTuner.dedupReposts)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (true /*TODOthis.homeFeed.hideReplies*/) {
|
if (preferences?.feedViewPrefs.hideReplies) {
|
||||||
feedTuners.push(FeedTuner.removeReplies)
|
feedTuners.push(FeedTuner.removeReplies)
|
||||||
} /* TODO else {
|
} else {
|
||||||
feedTuners.push(
|
feedTuners.push(
|
||||||
FeedTuner.thresholdRepliesOnly({
|
FeedTuner.thresholdRepliesOnly({
|
||||||
userDid: this.rootStore.session.data?.did || '',
|
userDid: currentAccount?.did || '',
|
||||||
minLikes: this.homeFeed.hideRepliesByLikeCount,
|
minLikes: preferences?.feedViewPrefs.hideRepliesByLikeCount || 0,
|
||||||
followedOnly: !!this.homeFeed.hideRepliesByUnfollowed,
|
followedOnly: !!preferences?.feedViewPrefs.hideRepliesByUnfollowed,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}*/
|
}
|
||||||
|
|
||||||
if (false /*TODOthis.homeFeed.hideQuotePosts*/) {
|
if (preferences?.feedViewPrefs.hideQuotePosts) {
|
||||||
feedTuners.push(FeedTuner.removeQuotePosts)
|
feedTuners.push(FeedTuner.removeQuotePosts)
|
||||||
}
|
}
|
||||||
|
|
||||||
return feedTuners
|
return feedTuners
|
||||||
}
|
}
|
||||||
return []
|
return []
|
||||||
}, [feedDesc, langPrefs])
|
}, [feedDesc, currentAccount, preferences, langPrefs])
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,6 +181,9 @@ export function useIsFeedPublicQuery({uri}: {uri: string}) {
|
||||||
|
|
||||||
if (msg.includes('missing jwt')) {
|
if (msg.includes('missing jwt')) {
|
||||||
return false
|
return false
|
||||||
|
} else if (msg.includes('This feed requires being logged-in')) {
|
||||||
|
// e.g. https://github.com/bluesky-social/atproto/blob/99ab1ae55c463e8d5321a1eaad07a175bdd56fea/packages/bsky/src/feed-gen/best-of-follows.ts#L13
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
@ -243,13 +246,19 @@ const FOLLOWING_FEED_STUB: FeedSourceInfo = {
|
||||||
likeUri: '',
|
likeUri: '',
|
||||||
}
|
}
|
||||||
|
|
||||||
export function usePinnedFeedsInfos(): FeedSourceInfo[] {
|
export function usePinnedFeedsInfos(): {
|
||||||
|
feeds: FeedSourceInfo[]
|
||||||
|
hasPinnedCustom: boolean
|
||||||
|
} {
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const [tabs, setTabs] = React.useState<FeedSourceInfo[]>([
|
const [tabs, setTabs] = React.useState<FeedSourceInfo[]>([
|
||||||
FOLLOWING_FEED_STUB,
|
FOLLOWING_FEED_STUB,
|
||||||
])
|
])
|
||||||
const {data: preferences} = usePreferencesQuery()
|
const {data: preferences} = usePreferencesQuery()
|
||||||
const pinnedFeedsKey = JSON.stringify(preferences?.feeds?.pinned)
|
|
||||||
|
const hasPinnedCustom = React.useMemo<boolean>(() => {
|
||||||
|
return tabs.some(tab => tab !== FOLLOWING_FEED_STUB)
|
||||||
|
}, [tabs])
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!preferences?.feeds?.pinned) return
|
if (!preferences?.feeds?.pinned) return
|
||||||
|
@ -296,13 +305,7 @@ export function usePinnedFeedsInfos(): FeedSourceInfo[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchFeedInfo()
|
fetchFeedInfo()
|
||||||
}, [
|
}, [queryClient, setTabs, preferences?.feeds?.pinned])
|
||||||
queryClient,
|
|
||||||
setTabs,
|
|
||||||
preferences?.feeds?.pinned,
|
|
||||||
// ensure we react to re-ordering
|
|
||||||
pinnedFeedsKey,
|
|
||||||
])
|
|
||||||
|
|
||||||
return tabs
|
return {feeds: tabs, hasPinnedCustom}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ import {
|
||||||
AppBskyGraphGetList,
|
AppBskyGraphGetList,
|
||||||
AppBskyGraphList,
|
AppBskyGraphList,
|
||||||
AppBskyGraphDefs,
|
AppBskyGraphDefs,
|
||||||
BskyAgent,
|
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
import {Image as RNImage} from 'react-native-image-crop-picker'
|
import {Image as RNImage} from 'react-native-image-crop-picker'
|
||||||
import {useQuery, useMutation, useQueryClient} from '@tanstack/react-query'
|
import {useQuery, useMutation, useQueryClient} from '@tanstack/react-query'
|
||||||
|
@ -75,13 +74,9 @@ export function useListCreateMutation() {
|
||||||
)
|
)
|
||||||
|
|
||||||
// wait for the appview to update
|
// wait for the appview to update
|
||||||
await whenAppViewReady(
|
await whenAppViewReady(res.uri, (v: AppBskyGraphGetList.Response) => {
|
||||||
getAgent(),
|
|
||||||
res.uri,
|
|
||||||
(v: AppBskyGraphGetList.Response) => {
|
|
||||||
return typeof v?.data?.list.uri === 'string'
|
return typeof v?.data?.list.uri === 'string'
|
||||||
},
|
})
|
||||||
)
|
|
||||||
return res
|
return res
|
||||||
},
|
},
|
||||||
onSuccess() {
|
onSuccess() {
|
||||||
|
@ -142,16 +137,12 @@ export function useListMetadataMutation() {
|
||||||
).data
|
).data
|
||||||
|
|
||||||
// wait for the appview to update
|
// wait for the appview to update
|
||||||
await whenAppViewReady(
|
await whenAppViewReady(res.uri, (v: AppBskyGraphGetList.Response) => {
|
||||||
getAgent(),
|
|
||||||
res.uri,
|
|
||||||
(v: AppBskyGraphGetList.Response) => {
|
|
||||||
const list = v.data.list
|
const list = v.data.list
|
||||||
return (
|
return (
|
||||||
list.name === record.name && list.description === record.description
|
list.name === record.name && list.description === record.description
|
||||||
)
|
)
|
||||||
},
|
})
|
||||||
)
|
|
||||||
return res
|
return res
|
||||||
},
|
},
|
||||||
onSuccess(data, variables) {
|
onSuccess(data, variables) {
|
||||||
|
@ -216,13 +207,9 @@ export function useListDeleteMutation() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait for the appview to update
|
// wait for the appview to update
|
||||||
await whenAppViewReady(
|
await whenAppViewReady(uri, (v: AppBskyGraphGetList.Response) => {
|
||||||
getAgent(),
|
|
||||||
uri,
|
|
||||||
(v: AppBskyGraphGetList.Response) => {
|
|
||||||
return !v?.success
|
return !v?.success
|
||||||
},
|
})
|
||||||
)
|
|
||||||
},
|
},
|
||||||
onSuccess() {
|
onSuccess() {
|
||||||
invalidateMyLists(queryClient)
|
invalidateMyLists(queryClient)
|
||||||
|
@ -271,7 +258,6 @@ export function useListBlockMutation() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function whenAppViewReady(
|
async function whenAppViewReady(
|
||||||
agent: BskyAgent,
|
|
||||||
uri: string,
|
uri: string,
|
||||||
fn: (res: AppBskyGraphGetList.Response) => boolean,
|
fn: (res: AppBskyGraphGetList.Response) => boolean,
|
||||||
) {
|
) {
|
||||||
|
@ -280,7 +266,7 @@ async function whenAppViewReady(
|
||||||
1e3, // 1s delay between tries
|
1e3, // 1s delay between tries
|
||||||
fn,
|
fn,
|
||||||
() =>
|
() =>
|
||||||
agent.app.bsky.graph.getList({
|
getAgent().app.bsky.graph.getList({
|
||||||
list: uri,
|
list: uri,
|
||||||
limit: 1,
|
limit: 1,
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -2,7 +2,6 @@ import {AppBskyGraphGetBlocks} from '@atproto/api'
|
||||||
import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
|
import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
|
||||||
|
|
||||||
import {getAgent} from '#/state/session'
|
import {getAgent} from '#/state/session'
|
||||||
import {STALE} from '#/state/queries'
|
|
||||||
|
|
||||||
export const RQKEY = () => ['my-blocked-accounts']
|
export const RQKEY = () => ['my-blocked-accounts']
|
||||||
type RQPageParam = string | undefined
|
type RQPageParam = string | undefined
|
||||||
|
@ -15,7 +14,6 @@ export function useMyBlockedAccountsQuery() {
|
||||||
QueryKey,
|
QueryKey,
|
||||||
RQPageParam
|
RQPageParam
|
||||||
>({
|
>({
|
||||||
staleTime: STALE.MINUTES.ONE,
|
|
||||||
queryKey: RQKEY(),
|
queryKey: RQKEY(),
|
||||||
async queryFn({pageParam}: {pageParam: RQPageParam}) {
|
async queryFn({pageParam}: {pageParam: RQPageParam}) {
|
||||||
const res = await getAgent().app.bsky.graph.getBlocks({
|
const res = await getAgent().app.bsky.graph.getBlocks({
|
||||||
|
|
|
@ -2,7 +2,6 @@ import {AppBskyGraphGetMutes} from '@atproto/api'
|
||||||
import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
|
import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
|
||||||
|
|
||||||
import {getAgent} from '#/state/session'
|
import {getAgent} from '#/state/session'
|
||||||
import {STALE} from '#/state/queries'
|
|
||||||
|
|
||||||
export const RQKEY = () => ['my-muted-accounts']
|
export const RQKEY = () => ['my-muted-accounts']
|
||||||
type RQPageParam = string | undefined
|
type RQPageParam = string | undefined
|
||||||
|
@ -15,7 +14,6 @@ export function useMyMutedAccountsQuery() {
|
||||||
QueryKey,
|
QueryKey,
|
||||||
RQPageParam
|
RQPageParam
|
||||||
>({
|
>({
|
||||||
staleTime: STALE.MINUTES.ONE,
|
|
||||||
queryKey: RQKEY(),
|
queryKey: RQKEY(),
|
||||||
async queryFn({pageParam}: {pageParam: RQPageParam}) {
|
async queryFn({pageParam}: {pageParam: RQPageParam}) {
|
||||||
const res = await getAgent().app.bsky.graph.getMutes({
|
const res = await getAgent().app.bsky.graph.getMutes({
|
||||||
|
|
|
@ -1,12 +1,22 @@
|
||||||
import {
|
/**
|
||||||
AppBskyFeedDefs,
|
* NOTE
|
||||||
AppBskyFeedPost,
|
* The ./unread.ts API:
|
||||||
AppBskyFeedRepost,
|
*
|
||||||
AppBskyFeedLike,
|
* - Provides a `checkUnread()` function to sync with the server,
|
||||||
AppBskyNotificationListNotifications,
|
* - Periodically calls `checkUnread()`, and
|
||||||
BskyAgent,
|
* - Caches the first page of notifications.
|
||||||
} from '@atproto/api'
|
*
|
||||||
import chunk from 'lodash.chunk'
|
* IMPORTANT: This query uses ./unread.ts's cache as its first page,
|
||||||
|
* IMPORTANT: which means the cache-freshness of this query is driven by the unread API.
|
||||||
|
*
|
||||||
|
* Follow these rules:
|
||||||
|
*
|
||||||
|
* 1. Call `checkUnread()` if you want to fetch latest in the background.
|
||||||
|
* 2. Call `checkUnread({invalidate: true})` if you want latest to sync into this query's results immediately.
|
||||||
|
* 3. Don't call this query's `refetch()` if you're trying to sync latest; call `checkUnread()` instead.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {AppBskyFeedDefs} from '@atproto/api'
|
||||||
import {
|
import {
|
||||||
useInfiniteQuery,
|
useInfiniteQuery,
|
||||||
InfiniteData,
|
InfiniteData,
|
||||||
|
@ -14,50 +24,27 @@ import {
|
||||||
useQueryClient,
|
useQueryClient,
|
||||||
QueryClient,
|
QueryClient,
|
||||||
} from '@tanstack/react-query'
|
} from '@tanstack/react-query'
|
||||||
import {getAgent} from '../../session'
|
|
||||||
import {useModerationOpts} from '../preferences'
|
import {useModerationOpts} from '../preferences'
|
||||||
import {shouldFilterNotif} from './util'
|
import {useUnreadNotificationsApi} from './unread'
|
||||||
|
import {fetchPage} from './util'
|
||||||
|
import {FeedPage} from './types'
|
||||||
import {useMutedThreads} from '#/state/muted-threads'
|
import {useMutedThreads} from '#/state/muted-threads'
|
||||||
import {precacheProfile as precacheResolvedUri} from '../resolve-uri'
|
|
||||||
|
|
||||||
const GROUPABLE_REASONS = ['like', 'repost', 'follow']
|
export type {NotificationType, FeedNotification, FeedPage} from './types'
|
||||||
|
|
||||||
const PAGE_SIZE = 30
|
const PAGE_SIZE = 30
|
||||||
const MS_1HR = 1e3 * 60 * 60
|
|
||||||
const MS_2DAY = MS_1HR * 48
|
|
||||||
|
|
||||||
type RQPageParam = string | undefined
|
type RQPageParam = string | undefined
|
||||||
type NotificationType =
|
|
||||||
| 'post-like'
|
|
||||||
| 'feedgen-like'
|
|
||||||
| 'repost'
|
|
||||||
| 'mention'
|
|
||||||
| 'reply'
|
|
||||||
| 'quote'
|
|
||||||
| 'follow'
|
|
||||||
| 'unknown'
|
|
||||||
|
|
||||||
export function RQKEY() {
|
export function RQKEY() {
|
||||||
return ['notification-feed']
|
return ['notification-feed']
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FeedNotification {
|
|
||||||
_reactKey: string
|
|
||||||
type: NotificationType
|
|
||||||
notification: AppBskyNotificationListNotifications.Notification
|
|
||||||
additional?: AppBskyNotificationListNotifications.Notification[]
|
|
||||||
subjectUri?: string
|
|
||||||
subject?: AppBskyFeedDefs.PostView
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FeedPage {
|
|
||||||
cursor: string | undefined
|
|
||||||
items: FeedNotification[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useNotificationFeedQuery(opts?: {enabled?: boolean}) {
|
export function useNotificationFeedQuery(opts?: {enabled?: boolean}) {
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const moderationOpts = useModerationOpts()
|
const moderationOpts = useModerationOpts()
|
||||||
const threadMutes = useMutedThreads()
|
const threadMutes = useMutedThreads()
|
||||||
|
const unreads = useUnreadNotificationsApi()
|
||||||
const enabled = opts?.enabled !== false
|
const enabled = opts?.enabled !== false
|
||||||
|
|
||||||
return useInfiniteQuery<
|
return useInfiniteQuery<
|
||||||
|
@ -69,40 +56,21 @@ export function useNotificationFeedQuery(opts?: {enabled?: boolean}) {
|
||||||
>({
|
>({
|
||||||
queryKey: RQKEY(),
|
queryKey: RQKEY(),
|
||||||
async queryFn({pageParam}: {pageParam: RQPageParam}) {
|
async queryFn({pageParam}: {pageParam: RQPageParam}) {
|
||||||
const res = await getAgent().listNotifications({
|
// for the first page, we check the cached page held by the unread-checker first
|
||||||
|
if (!pageParam) {
|
||||||
|
const cachedPage = unreads.getCachedUnreadPage()
|
||||||
|
if (cachedPage) {
|
||||||
|
return cachedPage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// do a normal fetch
|
||||||
|
return fetchPage({
|
||||||
limit: PAGE_SIZE,
|
limit: PAGE_SIZE,
|
||||||
cursor: pageParam,
|
cursor: pageParam,
|
||||||
|
queryClient,
|
||||||
|
moderationOpts,
|
||||||
|
threadMutes,
|
||||||
})
|
})
|
||||||
|
|
||||||
// filter out notifs by mod rules
|
|
||||||
const notifs = res.data.notifications.filter(
|
|
||||||
notif => !shouldFilterNotif(notif, moderationOpts),
|
|
||||||
)
|
|
||||||
|
|
||||||
// group notifications which are essentially similar (follows, likes on a post)
|
|
||||||
let notifsGrouped = groupNotifications(notifs)
|
|
||||||
|
|
||||||
// we fetch subjects of notifications (usually posts) now instead of lazily
|
|
||||||
// in the UI to avoid relayouts
|
|
||||||
const subjects = await fetchSubjects(getAgent(), notifsGrouped)
|
|
||||||
for (const notif of notifsGrouped) {
|
|
||||||
if (notif.subjectUri) {
|
|
||||||
notif.subject = subjects.get(notif.subjectUri)
|
|
||||||
if (notif.subject) {
|
|
||||||
precacheResolvedUri(queryClient, notif.subject.author) // precache the handle->did resolution
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// apply thread muting
|
|
||||||
notifsGrouped = notifsGrouped.filter(
|
|
||||||
notif => !isThreadMuted(notif, threadMutes),
|
|
||||||
)
|
|
||||||
|
|
||||||
return {
|
|
||||||
cursor: res.data.cursor,
|
|
||||||
items: notifsGrouped,
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
initialPageParam: undefined,
|
initialPageParam: undefined,
|
||||||
getNextPageParam: lastPage => lastPage.cursor,
|
getNextPageParam: lastPage => lastPage.cursor,
|
||||||
|
@ -135,114 +103,3 @@ export function findPostInQueryData(
|
||||||
}
|
}
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
function groupNotifications(
|
|
||||||
notifs: AppBskyNotificationListNotifications.Notification[],
|
|
||||||
): FeedNotification[] {
|
|
||||||
const groupedNotifs: FeedNotification[] = []
|
|
||||||
for (const notif of notifs) {
|
|
||||||
const ts = +new Date(notif.indexedAt)
|
|
||||||
let grouped = false
|
|
||||||
if (GROUPABLE_REASONS.includes(notif.reason)) {
|
|
||||||
for (const groupedNotif of groupedNotifs) {
|
|
||||||
const ts2 = +new Date(groupedNotif.notification.indexedAt)
|
|
||||||
if (
|
|
||||||
Math.abs(ts2 - ts) < MS_2DAY &&
|
|
||||||
notif.reason === groupedNotif.notification.reason &&
|
|
||||||
notif.reasonSubject === groupedNotif.notification.reasonSubject &&
|
|
||||||
notif.author.did !== groupedNotif.notification.author.did
|
|
||||||
) {
|
|
||||||
groupedNotif.additional = groupedNotif.additional || []
|
|
||||||
groupedNotif.additional.push(notif)
|
|
||||||
grouped = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!grouped) {
|
|
||||||
const type = toKnownType(notif)
|
|
||||||
groupedNotifs.push({
|
|
||||||
_reactKey: `notif-${notif.uri}`,
|
|
||||||
type,
|
|
||||||
notification: notif,
|
|
||||||
subjectUri: getSubjectUri(type, notif),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return groupedNotifs
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchSubjects(
|
|
||||||
agent: BskyAgent,
|
|
||||||
groupedNotifs: FeedNotification[],
|
|
||||||
): Promise<Map<string, AppBskyFeedDefs.PostView>> {
|
|
||||||
const uris = new Set<string>()
|
|
||||||
for (const notif of groupedNotifs) {
|
|
||||||
if (notif.subjectUri) {
|
|
||||||
uris.add(notif.subjectUri)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const uriChunks = chunk(Array.from(uris), 25)
|
|
||||||
const postsChunks = await Promise.all(
|
|
||||||
uriChunks.map(uris =>
|
|
||||||
agent.app.bsky.feed.getPosts({uris}).then(res => res.data.posts),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
const map = new Map<string, AppBskyFeedDefs.PostView>()
|
|
||||||
for (const post of postsChunks.flat()) {
|
|
||||||
if (
|
|
||||||
AppBskyFeedPost.isRecord(post.record) &&
|
|
||||||
AppBskyFeedPost.validateRecord(post.record).success
|
|
||||||
) {
|
|
||||||
map.set(post.uri, post)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return map
|
|
||||||
}
|
|
||||||
|
|
||||||
function toKnownType(
|
|
||||||
notif: AppBskyNotificationListNotifications.Notification,
|
|
||||||
): NotificationType {
|
|
||||||
if (notif.reason === 'like') {
|
|
||||||
if (notif.reasonSubject?.includes('feed.generator')) {
|
|
||||||
return 'feedgen-like'
|
|
||||||
}
|
|
||||||
return 'post-like'
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
notif.reason === 'repost' ||
|
|
||||||
notif.reason === 'mention' ||
|
|
||||||
notif.reason === 'reply' ||
|
|
||||||
notif.reason === 'quote' ||
|
|
||||||
notif.reason === 'follow'
|
|
||||||
) {
|
|
||||||
return notif.reason as NotificationType
|
|
||||||
}
|
|
||||||
return 'unknown'
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSubjectUri(
|
|
||||||
type: NotificationType,
|
|
||||||
notif: AppBskyNotificationListNotifications.Notification,
|
|
||||||
): string | undefined {
|
|
||||||
if (type === 'reply' || type === 'quote' || type === 'mention') {
|
|
||||||
return notif.uri
|
|
||||||
} else if (type === 'post-like' || type === 'repost') {
|
|
||||||
if (
|
|
||||||
AppBskyFeedRepost.isRecord(notif.record) ||
|
|
||||||
AppBskyFeedLike.isRecord(notif.record)
|
|
||||||
) {
|
|
||||||
return typeof notif.record.subject?.uri === 'string'
|
|
||||||
? notif.record.subject?.uri
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isThreadMuted(notif: FeedNotification, mutes: string[]): boolean {
|
|
||||||
if (!notif.subject) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
const record = notif.subject.record as AppBskyFeedPost.Record // assured in fetchSubjects()
|
|
||||||
return mutes.includes(record.reply?.root.uri || notif.subject.uri)
|
|
||||||
}
|
|
||||||
|
|
34
src/state/queries/notifications/types.ts
Normal file
34
src/state/queries/notifications/types.ts
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import {
|
||||||
|
AppBskyNotificationListNotifications,
|
||||||
|
AppBskyFeedDefs,
|
||||||
|
} from '@atproto/api'
|
||||||
|
|
||||||
|
export type NotificationType =
|
||||||
|
| 'post-like'
|
||||||
|
| 'feedgen-like'
|
||||||
|
| 'repost'
|
||||||
|
| 'mention'
|
||||||
|
| 'reply'
|
||||||
|
| 'quote'
|
||||||
|
| 'follow'
|
||||||
|
| 'unknown'
|
||||||
|
|
||||||
|
export interface FeedNotification {
|
||||||
|
_reactKey: string
|
||||||
|
type: NotificationType
|
||||||
|
notification: AppBskyNotificationListNotifications.Notification
|
||||||
|
additional?: AppBskyNotificationListNotifications.Notification[]
|
||||||
|
subjectUri?: string
|
||||||
|
subject?: AppBskyFeedDefs.PostView
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FeedPage {
|
||||||
|
cursor: string | undefined
|
||||||
|
items: FeedNotification[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CachedFeedPage {
|
||||||
|
sessDid: string // used to invalidate on session changes
|
||||||
|
syncedAt: Date
|
||||||
|
data: FeedPage | undefined
|
||||||
|
}
|
|
@ -1,10 +1,19 @@
|
||||||
|
/**
|
||||||
|
* A kind of companion API to ./feed.ts. See that file for more info.
|
||||||
|
*/
|
||||||
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import * as Notifications from 'expo-notifications'
|
import * as Notifications from 'expo-notifications'
|
||||||
|
import {useQueryClient} from '@tanstack/react-query'
|
||||||
import BroadcastChannel from '#/lib/broadcast'
|
import BroadcastChannel from '#/lib/broadcast'
|
||||||
import {useSession, getAgent} from '#/state/session'
|
import {useSession, getAgent} from '#/state/session'
|
||||||
import {useModerationOpts} from '../preferences'
|
import {useModerationOpts} from '../preferences'
|
||||||
import {shouldFilterNotif} from './util'
|
import {fetchPage} from './util'
|
||||||
|
import {CachedFeedPage, FeedPage} from './types'
|
||||||
import {isNative} from '#/platform/detection'
|
import {isNative} from '#/platform/detection'
|
||||||
|
import {useMutedThreads} from '#/state/muted-threads'
|
||||||
|
import {RQKEY as RQKEY_NOTIFS} from './feed'
|
||||||
|
import {logger} from '#/logger'
|
||||||
|
|
||||||
const UPDATE_INTERVAL = 30 * 1e3 // 30sec
|
const UPDATE_INTERVAL = 30 * 1e3 // 30sec
|
||||||
|
|
||||||
|
@ -14,7 +23,8 @@ type StateContext = string
|
||||||
|
|
||||||
interface ApiContext {
|
interface ApiContext {
|
||||||
markAllRead: () => Promise<void>
|
markAllRead: () => Promise<void>
|
||||||
checkUnread: () => Promise<void>
|
checkUnread: (opts?: {invalidate?: boolean}) => Promise<void>
|
||||||
|
getCachedUnreadPage: () => FeedPage | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
const stateContext = React.createContext<StateContext>('')
|
const stateContext = React.createContext<StateContext>('')
|
||||||
|
@ -22,16 +32,23 @@ const stateContext = React.createContext<StateContext>('')
|
||||||
const apiContext = React.createContext<ApiContext>({
|
const apiContext = React.createContext<ApiContext>({
|
||||||
async markAllRead() {},
|
async markAllRead() {},
|
||||||
async checkUnread() {},
|
async checkUnread() {},
|
||||||
|
getCachedUnreadPage: () => undefined,
|
||||||
})
|
})
|
||||||
|
|
||||||
export function Provider({children}: React.PropsWithChildren<{}>) {
|
export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||||
const {hasSession} = useSession()
|
const {hasSession, currentAccount} = useSession()
|
||||||
|
const queryClient = useQueryClient()
|
||||||
const moderationOpts = useModerationOpts()
|
const moderationOpts = useModerationOpts()
|
||||||
|
const threadMutes = useMutedThreads()
|
||||||
|
|
||||||
const [numUnread, setNumUnread] = React.useState('')
|
const [numUnread, setNumUnread] = React.useState('')
|
||||||
|
|
||||||
const checkUnreadRef = React.useRef<(() => Promise<void>) | null>(null)
|
const checkUnreadRef = React.useRef<ApiContext['checkUnread'] | null>(null)
|
||||||
const lastSyncRef = React.useRef<Date>(new Date())
|
const cacheRef = React.useRef<CachedFeedPage>({
|
||||||
|
sessDid: currentAccount?.did || '',
|
||||||
|
syncedAt: new Date(),
|
||||||
|
data: undefined,
|
||||||
|
})
|
||||||
|
|
||||||
// periodic sync
|
// periodic sync
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
@ -46,14 +63,18 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||||
// listen for broadcasts
|
// listen for broadcasts
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const listener = ({data}: MessageEvent) => {
|
const listener = ({data}: MessageEvent) => {
|
||||||
lastSyncRef.current = new Date()
|
cacheRef.current = {
|
||||||
|
sessDid: currentAccount?.did || '',
|
||||||
|
syncedAt: new Date(),
|
||||||
|
data: undefined,
|
||||||
|
}
|
||||||
setNumUnread(data.event)
|
setNumUnread(data.event)
|
||||||
}
|
}
|
||||||
broadcast.addEventListener('message', listener)
|
broadcast.addEventListener('message', listener)
|
||||||
return () => {
|
return () => {
|
||||||
broadcast.removeEventListener('message', listener)
|
broadcast.removeEventListener('message', listener)
|
||||||
}
|
}
|
||||||
}, [setNumUnread])
|
}, [setNumUnread, currentAccount])
|
||||||
|
|
||||||
// create API
|
// create API
|
||||||
const api = React.useMemo<ApiContext>(() => {
|
const api = React.useMemo<ApiContext>(() => {
|
||||||
|
@ -61,7 +82,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||||
async markAllRead() {
|
async markAllRead() {
|
||||||
// update server
|
// update server
|
||||||
await getAgent().updateSeenNotifications(
|
await getAgent().updateSeenNotifications(
|
||||||
lastSyncRef.current.toISOString(),
|
cacheRef.current.syncedAt.toISOString(),
|
||||||
)
|
)
|
||||||
|
|
||||||
// update & broadcast
|
// update & broadcast
|
||||||
|
@ -69,38 +90,59 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||||
broadcast.postMessage({event: ''})
|
broadcast.postMessage({event: ''})
|
||||||
},
|
},
|
||||||
|
|
||||||
async checkUnread() {
|
async checkUnread({invalidate}: {invalidate?: boolean} = {}) {
|
||||||
const agent = getAgent()
|
try {
|
||||||
|
if (!getAgent().session) return
|
||||||
if (!agent.session) return
|
|
||||||
|
|
||||||
// count
|
// count
|
||||||
const res = await agent.listNotifications({limit: 40})
|
const page = await fetchPage({
|
||||||
const filtered = res.data.notifications.filter(
|
cursor: undefined,
|
||||||
notif => !notif.isRead && !shouldFilterNotif(notif, moderationOpts),
|
limit: 40,
|
||||||
)
|
queryClient,
|
||||||
const num =
|
moderationOpts,
|
||||||
filtered.length >= 30
|
threadMutes,
|
||||||
|
})
|
||||||
|
const unreadCount = countUnread(page)
|
||||||
|
const unreadCountStr =
|
||||||
|
unreadCount >= 30
|
||||||
? '30+'
|
? '30+'
|
||||||
: filtered.length === 0
|
: unreadCount === 0
|
||||||
? ''
|
? ''
|
||||||
: String(filtered.length)
|
: String(unreadCount)
|
||||||
if (isNative) {
|
if (isNative) {
|
||||||
Notifications.setBadgeCountAsync(Math.min(filtered.length, 30))
|
Notifications.setBadgeCountAsync(Math.min(unreadCount, 30))
|
||||||
}
|
}
|
||||||
|
|
||||||
// track last sync
|
// track last sync
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
const lastIndexed = filtered[0] && new Date(filtered[0].indexedAt)
|
const lastIndexed =
|
||||||
lastSyncRef.current =
|
page.items[0] && new Date(page.items[0].notification.indexedAt)
|
||||||
!lastIndexed || now > lastIndexed ? now : lastIndexed
|
cacheRef.current = {
|
||||||
|
sessDid: currentAccount?.did || '',
|
||||||
|
data: page,
|
||||||
|
syncedAt: !lastIndexed || now > lastIndexed ? now : lastIndexed,
|
||||||
|
}
|
||||||
|
|
||||||
// update & broadcast
|
// update & broadcast
|
||||||
setNumUnread(num)
|
setNumUnread(unreadCountStr)
|
||||||
broadcast.postMessage({event: num})
|
if (invalidate) {
|
||||||
|
queryClient.resetQueries({queryKey: RQKEY_NOTIFS()})
|
||||||
|
}
|
||||||
|
broadcast.postMessage({event: unreadCountStr})
|
||||||
|
} catch (e) {
|
||||||
|
logger.error('Failed to check unread notifications', {error: e})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getCachedUnreadPage() {
|
||||||
|
// return cached page if was for the current user
|
||||||
|
// (protects against session changes serving data from the past session)
|
||||||
|
if (cacheRef.current.sessDid === currentAccount?.did) {
|
||||||
|
return cacheRef.current.data
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}, [setNumUnread, moderationOpts])
|
}, [setNumUnread, queryClient, moderationOpts, threadMutes, currentAccount])
|
||||||
checkUnreadRef.current = api.checkUnread
|
checkUnreadRef.current = api.checkUnread
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -117,3 +159,20 @@ export function useUnreadNotifications() {
|
||||||
export function useUnreadNotificationsApi() {
|
export function useUnreadNotificationsApi() {
|
||||||
return React.useContext(apiContext)
|
return React.useContext(apiContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function countUnread(page: FeedPage) {
|
||||||
|
let num = 0
|
||||||
|
for (const item of page.items) {
|
||||||
|
if (!item.notification.isRead) {
|
||||||
|
num++
|
||||||
|
}
|
||||||
|
if (item.additional) {
|
||||||
|
for (const item2 of item.additional) {
|
||||||
|
if (!item2.isRead) {
|
||||||
|
num++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return num
|
||||||
|
}
|
||||||
|
|
|
@ -3,10 +3,78 @@ import {
|
||||||
ModerationOpts,
|
ModerationOpts,
|
||||||
moderateProfile,
|
moderateProfile,
|
||||||
moderatePost,
|
moderatePost,
|
||||||
|
AppBskyFeedDefs,
|
||||||
|
AppBskyFeedPost,
|
||||||
|
AppBskyFeedRepost,
|
||||||
|
AppBskyFeedLike,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
|
import chunk from 'lodash.chunk'
|
||||||
|
import {QueryClient} from '@tanstack/react-query'
|
||||||
|
import {getAgent} from '../../session'
|
||||||
|
import {precacheProfile as precacheResolvedUri} from '../resolve-uri'
|
||||||
|
import {NotificationType, FeedNotification, FeedPage} from './types'
|
||||||
|
|
||||||
|
const GROUPABLE_REASONS = ['like', 'repost', 'follow']
|
||||||
|
const MS_1HR = 1e3 * 60 * 60
|
||||||
|
const MS_2DAY = MS_1HR * 48
|
||||||
|
|
||||||
|
// exported api
|
||||||
|
// =
|
||||||
|
|
||||||
|
export async function fetchPage({
|
||||||
|
cursor,
|
||||||
|
limit,
|
||||||
|
queryClient,
|
||||||
|
moderationOpts,
|
||||||
|
threadMutes,
|
||||||
|
}: {
|
||||||
|
cursor: string | undefined
|
||||||
|
limit: number
|
||||||
|
queryClient: QueryClient
|
||||||
|
moderationOpts: ModerationOpts | undefined
|
||||||
|
threadMutes: string[]
|
||||||
|
}): Promise<FeedPage> {
|
||||||
|
const res = await getAgent().listNotifications({
|
||||||
|
limit,
|
||||||
|
cursor,
|
||||||
|
})
|
||||||
|
|
||||||
|
// filter out notifs by mod rules
|
||||||
|
const notifs = res.data.notifications.filter(
|
||||||
|
notif => !shouldFilterNotif(notif, moderationOpts),
|
||||||
|
)
|
||||||
|
|
||||||
|
// group notifications which are essentially similar (follows, likes on a post)
|
||||||
|
let notifsGrouped = groupNotifications(notifs)
|
||||||
|
|
||||||
|
// we fetch subjects of notifications (usually posts) now instead of lazily
|
||||||
|
// in the UI to avoid relayouts
|
||||||
|
const subjects = await fetchSubjects(notifsGrouped)
|
||||||
|
for (const notif of notifsGrouped) {
|
||||||
|
if (notif.subjectUri) {
|
||||||
|
notif.subject = subjects.get(notif.subjectUri)
|
||||||
|
if (notif.subject) {
|
||||||
|
precacheResolvedUri(queryClient, notif.subject.author) // precache the handle->did resolution
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// apply thread muting
|
||||||
|
notifsGrouped = notifsGrouped.filter(
|
||||||
|
notif => !isThreadMuted(notif, threadMutes),
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
cursor: res.data.cursor,
|
||||||
|
items: notifsGrouped,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// internal methods
|
||||||
|
// =
|
||||||
|
|
||||||
// TODO this should be in the sdk as moderateNotification -prf
|
// TODO this should be in the sdk as moderateNotification -prf
|
||||||
export function shouldFilterNotif(
|
function shouldFilterNotif(
|
||||||
notif: AppBskyNotificationListNotifications.Notification,
|
notif: AppBskyNotificationListNotifications.Notification,
|
||||||
moderationOpts: ModerationOpts | undefined,
|
moderationOpts: ModerationOpts | undefined,
|
||||||
): boolean {
|
): boolean {
|
||||||
|
@ -36,3 +104,116 @@ export function shouldFilterNotif(
|
||||||
// (this requires fetching the post)
|
// (this requires fetching the post)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function groupNotifications(
|
||||||
|
notifs: AppBskyNotificationListNotifications.Notification[],
|
||||||
|
): FeedNotification[] {
|
||||||
|
const groupedNotifs: FeedNotification[] = []
|
||||||
|
for (const notif of notifs) {
|
||||||
|
const ts = +new Date(notif.indexedAt)
|
||||||
|
let grouped = false
|
||||||
|
if (GROUPABLE_REASONS.includes(notif.reason)) {
|
||||||
|
for (const groupedNotif of groupedNotifs) {
|
||||||
|
const ts2 = +new Date(groupedNotif.notification.indexedAt)
|
||||||
|
if (
|
||||||
|
Math.abs(ts2 - ts) < MS_2DAY &&
|
||||||
|
notif.reason === groupedNotif.notification.reason &&
|
||||||
|
notif.reasonSubject === groupedNotif.notification.reasonSubject &&
|
||||||
|
notif.author.did !== groupedNotif.notification.author.did &&
|
||||||
|
notif.isRead === groupedNotif.notification.isRead
|
||||||
|
) {
|
||||||
|
groupedNotif.additional = groupedNotif.additional || []
|
||||||
|
groupedNotif.additional.push(notif)
|
||||||
|
grouped = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!grouped) {
|
||||||
|
const type = toKnownType(notif)
|
||||||
|
groupedNotifs.push({
|
||||||
|
_reactKey: `notif-${notif.uri}`,
|
||||||
|
type,
|
||||||
|
notification: notif,
|
||||||
|
subjectUri: getSubjectUri(type, notif),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return groupedNotifs
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchSubjects(
|
||||||
|
groupedNotifs: FeedNotification[],
|
||||||
|
): Promise<Map<string, AppBskyFeedDefs.PostView>> {
|
||||||
|
const uris = new Set<string>()
|
||||||
|
for (const notif of groupedNotifs) {
|
||||||
|
if (notif.subjectUri) {
|
||||||
|
uris.add(notif.subjectUri)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const uriChunks = chunk(Array.from(uris), 25)
|
||||||
|
const postsChunks = await Promise.all(
|
||||||
|
uriChunks.map(uris =>
|
||||||
|
getAgent()
|
||||||
|
.app.bsky.feed.getPosts({uris})
|
||||||
|
.then(res => res.data.posts),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
const map = new Map<string, AppBskyFeedDefs.PostView>()
|
||||||
|
for (const post of postsChunks.flat()) {
|
||||||
|
if (
|
||||||
|
AppBskyFeedPost.isRecord(post.record) &&
|
||||||
|
AppBskyFeedPost.validateRecord(post.record).success
|
||||||
|
) {
|
||||||
|
map.set(post.uri, post)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map
|
||||||
|
}
|
||||||
|
|
||||||
|
function toKnownType(
|
||||||
|
notif: AppBskyNotificationListNotifications.Notification,
|
||||||
|
): NotificationType {
|
||||||
|
if (notif.reason === 'like') {
|
||||||
|
if (notif.reasonSubject?.includes('feed.generator')) {
|
||||||
|
return 'feedgen-like'
|
||||||
|
}
|
||||||
|
return 'post-like'
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
notif.reason === 'repost' ||
|
||||||
|
notif.reason === 'mention' ||
|
||||||
|
notif.reason === 'reply' ||
|
||||||
|
notif.reason === 'quote' ||
|
||||||
|
notif.reason === 'follow'
|
||||||
|
) {
|
||||||
|
return notif.reason as NotificationType
|
||||||
|
}
|
||||||
|
return 'unknown'
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSubjectUri(
|
||||||
|
type: NotificationType,
|
||||||
|
notif: AppBskyNotificationListNotifications.Notification,
|
||||||
|
): string | undefined {
|
||||||
|
if (type === 'reply' || type === 'quote' || type === 'mention') {
|
||||||
|
return notif.uri
|
||||||
|
} else if (type === 'post-like' || type === 'repost') {
|
||||||
|
if (
|
||||||
|
AppBskyFeedRepost.isRecord(notif.record) ||
|
||||||
|
AppBskyFeedLike.isRecord(notif.record)
|
||||||
|
) {
|
||||||
|
return typeof notif.record.subject?.uri === 'string'
|
||||||
|
? notif.record.subject?.uri
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isThreadMuted(notif: FeedNotification, mutes: string[]): boolean {
|
||||||
|
if (!notif.subject) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const record = notif.subject.record as AppBskyFeedPost.Record // assured in fetchSubjects()
|
||||||
|
return mutes.includes(record.reply?.root.uri || notif.subject.uri)
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import {useCallback, useMemo} from 'react'
|
|
||||||
import {AppBskyFeedDefs, AppBskyFeedPost, moderatePost} from '@atproto/api'
|
import {AppBskyFeedDefs, AppBskyFeedPost, moderatePost} from '@atproto/api'
|
||||||
import {
|
import {
|
||||||
useInfiniteQuery,
|
useInfiniteQuery,
|
||||||
|
@ -7,9 +6,8 @@ import {
|
||||||
QueryClient,
|
QueryClient,
|
||||||
useQueryClient,
|
useQueryClient,
|
||||||
} from '@tanstack/react-query'
|
} from '@tanstack/react-query'
|
||||||
import {getAgent} from '../session'
|
|
||||||
import {useFeedTuners} from '../preferences/feed-tuners'
|
import {useFeedTuners} from '../preferences/feed-tuners'
|
||||||
import {FeedTuner, NoopFeedTuner} from 'lib/api/feed-manip'
|
import {FeedTuner, FeedTunerFn, NoopFeedTuner} from 'lib/api/feed-manip'
|
||||||
import {FeedAPI, ReasonFeedSource} from 'lib/api/feed/types'
|
import {FeedAPI, ReasonFeedSource} from 'lib/api/feed/types'
|
||||||
import {FollowingFeedAPI} from 'lib/api/feed/following'
|
import {FollowingFeedAPI} from 'lib/api/feed/following'
|
||||||
import {AuthorFeedAPI} from 'lib/api/feed/author'
|
import {AuthorFeedAPI} from 'lib/api/feed/author'
|
||||||
|
@ -17,10 +15,13 @@ import {LikesFeedAPI} from 'lib/api/feed/likes'
|
||||||
import {CustomFeedAPI} from 'lib/api/feed/custom'
|
import {CustomFeedAPI} from 'lib/api/feed/custom'
|
||||||
import {ListFeedAPI} from 'lib/api/feed/list'
|
import {ListFeedAPI} from 'lib/api/feed/list'
|
||||||
import {MergeFeedAPI} from 'lib/api/feed/merge'
|
import {MergeFeedAPI} from 'lib/api/feed/merge'
|
||||||
import {useModerationOpts} from '#/state/queries/preferences'
|
|
||||||
import {logger} from '#/logger'
|
import {logger} from '#/logger'
|
||||||
import {STALE} from '#/state/queries'
|
import {STALE} from '#/state/queries'
|
||||||
import {precacheFeedPosts as precacheResolvedUris} from './resolve-uri'
|
import {precacheFeedPosts as precacheResolvedUris} from './resolve-uri'
|
||||||
|
import {getAgent} from '#/state/session'
|
||||||
|
import {DEFAULT_LOGGED_OUT_PREFERENCES} from '#/state/queries/preferences/const'
|
||||||
|
import {getModerationOpts} from '#/state/queries/preferences/moderation'
|
||||||
|
import {KnownError} from '#/view/com/posts/FeedErrorMessage'
|
||||||
|
|
||||||
type ActorDid = string
|
type ActorDid = string
|
||||||
type AuthorFilter =
|
type AuthorFilter =
|
||||||
|
@ -42,7 +43,7 @@ export interface FeedParams {
|
||||||
mergeFeedSources?: string[]
|
mergeFeedSources?: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
type RQPageParam = string | undefined
|
type RQPageParam = {cursor: string | undefined; api: FeedAPI} | undefined
|
||||||
|
|
||||||
export function RQKEY(feedDesc: FeedDescriptor, params?: FeedParams) {
|
export function RQKEY(feedDesc: FeedDescriptor, params?: FeedParams) {
|
||||||
return ['post-feed', feedDesc, params || {}]
|
return ['post-feed', feedDesc, params || {}]
|
||||||
|
@ -63,7 +64,15 @@ export interface FeedPostSlice {
|
||||||
items: FeedPostSliceItem[]
|
items: FeedPostSliceItem[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface FeedPageUnselected {
|
||||||
|
api: FeedAPI
|
||||||
|
cursor: string | undefined
|
||||||
|
feed: AppBskyFeedDefs.FeedViewPost[]
|
||||||
|
}
|
||||||
|
|
||||||
export interface FeedPage {
|
export interface FeedPage {
|
||||||
|
api: FeedAPI
|
||||||
|
tuner: FeedTuner | NoopFeedTuner
|
||||||
cursor: string | undefined
|
cursor: string | undefined
|
||||||
slices: FeedPostSlice[]
|
slices: FeedPostSlice[]
|
||||||
}
|
}
|
||||||
|
@ -76,84 +85,62 @@ export function usePostFeedQuery(
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const feedTuners = useFeedTuners(feedDesc)
|
const feedTuners = useFeedTuners(feedDesc)
|
||||||
const enabled = opts?.enabled !== false
|
const enabled = opts?.enabled !== false
|
||||||
const moderationOpts = useModerationOpts()
|
|
||||||
const agent = getAgent()
|
|
||||||
|
|
||||||
const api: FeedAPI = useMemo(() => {
|
return useInfiniteQuery<
|
||||||
if (feedDesc === 'home') {
|
FeedPageUnselected,
|
||||||
return new MergeFeedAPI(agent, params || {}, feedTuners)
|
|
||||||
} else if (feedDesc === 'following') {
|
|
||||||
return new FollowingFeedAPI(agent)
|
|
||||||
} else if (feedDesc.startsWith('author')) {
|
|
||||||
const [_, actor, filter] = feedDesc.split('|')
|
|
||||||
return new AuthorFeedAPI(agent, {actor, filter})
|
|
||||||
} else if (feedDesc.startsWith('likes')) {
|
|
||||||
const [_, actor] = feedDesc.split('|')
|
|
||||||
return new LikesFeedAPI(agent, {actor})
|
|
||||||
} else if (feedDesc.startsWith('feedgen')) {
|
|
||||||
const [_, feed] = feedDesc.split('|')
|
|
||||||
return new CustomFeedAPI(agent, {feed})
|
|
||||||
} else if (feedDesc.startsWith('list')) {
|
|
||||||
const [_, list] = feedDesc.split('|')
|
|
||||||
return new ListFeedAPI(agent, {list})
|
|
||||||
} else {
|
|
||||||
// shouldnt happen
|
|
||||||
return new FollowingFeedAPI(agent)
|
|
||||||
}
|
|
||||||
}, [feedDesc, params, feedTuners, agent])
|
|
||||||
|
|
||||||
const disableTuner = !!params?.disableTuner
|
|
||||||
const tuner = useMemo(
|
|
||||||
() => (disableTuner ? new NoopFeedTuner() : new FeedTuner()),
|
|
||||||
[disableTuner],
|
|
||||||
)
|
|
||||||
|
|
||||||
const pollLatest = useCallback(async () => {
|
|
||||||
if (!enabled) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.debug('usePostFeedQuery: pollLatest')
|
|
||||||
|
|
||||||
const post = await api.peekLatest()
|
|
||||||
|
|
||||||
if (post && moderationOpts) {
|
|
||||||
const slices = tuner.tune([post], feedTuners, {
|
|
||||||
dryRun: true,
|
|
||||||
maintainOrder: true,
|
|
||||||
})
|
|
||||||
if (slices[0]) {
|
|
||||||
if (
|
|
||||||
!moderatePost(slices[0].items[0].post, moderationOpts).content.filter
|
|
||||||
) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}, [api, tuner, feedTuners, moderationOpts, enabled])
|
|
||||||
|
|
||||||
const out = useInfiniteQuery<
|
|
||||||
FeedPage,
|
|
||||||
Error,
|
Error,
|
||||||
InfiniteData<FeedPage>,
|
InfiniteData<FeedPage>,
|
||||||
QueryKey,
|
QueryKey,
|
||||||
RQPageParam
|
RQPageParam
|
||||||
>({
|
>({
|
||||||
|
enabled,
|
||||||
staleTime: STALE.INFINITY,
|
staleTime: STALE.INFINITY,
|
||||||
queryKey: RQKEY(feedDesc, params),
|
queryKey: RQKEY(feedDesc, params),
|
||||||
async queryFn({pageParam}: {pageParam: RQPageParam}) {
|
async queryFn({pageParam}: {pageParam: RQPageParam}) {
|
||||||
logger.debug('usePostFeedQuery', {feedDesc, pageParam})
|
logger.debug('usePostFeedQuery', {feedDesc, pageParam})
|
||||||
if (!pageParam) {
|
|
||||||
tuner.reset()
|
const {api, cursor} = pageParam
|
||||||
|
? pageParam
|
||||||
|
: {
|
||||||
|
api: createApi(feedDesc, params || {}, feedTuners),
|
||||||
|
cursor: undefined,
|
||||||
}
|
}
|
||||||
const res = await api.fetch({cursor: pageParam, limit: 30})
|
|
||||||
|
const res = await api.fetch({cursor, limit: 30})
|
||||||
precacheResolvedUris(queryClient, res.feed) // precache the handle->did resolution
|
precacheResolvedUris(queryClient, res.feed) // precache the handle->did resolution
|
||||||
const slices = tuner.tune(res.feed, feedTuners)
|
|
||||||
|
/*
|
||||||
|
* If this is a public view, we need to check if posts fail moderation.
|
||||||
|
* If all fail, we throw an error. If only some fail, we continue and let
|
||||||
|
* moderations happen later, which results in some posts being shown and
|
||||||
|
* some not.
|
||||||
|
*/
|
||||||
|
if (!getAgent().session) {
|
||||||
|
assertSomePostsPassModeration(res.feed)
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
api,
|
||||||
cursor: res.cursor,
|
cursor: res.cursor,
|
||||||
slices: slices.map(slice => ({
|
feed: res.feed,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
initialPageParam: undefined,
|
||||||
|
getNextPageParam: lastPage => ({
|
||||||
|
api: lastPage.api,
|
||||||
|
cursor: lastPage.cursor,
|
||||||
|
}),
|
||||||
|
select(data) {
|
||||||
|
const tuner = params?.disableTuner
|
||||||
|
? new NoopFeedTuner()
|
||||||
|
: new FeedTuner(feedTuners)
|
||||||
|
return {
|
||||||
|
pageParams: data.pageParams,
|
||||||
|
pages: data.pages.map(page => ({
|
||||||
|
api: page.api,
|
||||||
|
tuner,
|
||||||
|
cursor: page.cursor,
|
||||||
|
slices: tuner.tune(page.feed).map(slice => ({
|
||||||
_reactKey: slice._reactKey,
|
_reactKey: slice._reactKey,
|
||||||
rootUri: slice.rootItem.post.uri,
|
rootUri: slice.rootItem.post.uri,
|
||||||
isThread:
|
isThread:
|
||||||
|
@ -172,21 +159,65 @@ export function usePostFeedQuery(
|
||||||
uri: item.post.uri,
|
uri: item.post.uri,
|
||||||
post: item.post,
|
post: item.post,
|
||||||
record: item.post.record,
|
record: item.post.record,
|
||||||
reason: i === 0 && slice.source ? slice.source : item.reason,
|
reason:
|
||||||
|
i === 0 && slice.source ? slice.source : item.reason,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return undefined
|
return undefined
|
||||||
})
|
})
|
||||||
.filter(Boolean) as FeedPostSliceItem[],
|
.filter(Boolean) as FeedPostSliceItem[],
|
||||||
})),
|
})),
|
||||||
|
})),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
initialPageParam: undefined,
|
|
||||||
getNextPageParam: lastPage => lastPage.cursor,
|
|
||||||
enabled,
|
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return {...out, pollLatest}
|
export async function pollLatest(page: FeedPage | undefined) {
|
||||||
|
if (!page) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug('usePostFeedQuery: pollLatest')
|
||||||
|
const post = await page.api.peekLatest()
|
||||||
|
if (post) {
|
||||||
|
const slices = page.tuner.tune([post], {
|
||||||
|
dryRun: true,
|
||||||
|
maintainOrder: true,
|
||||||
|
})
|
||||||
|
if (slices[0]) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
function createApi(
|
||||||
|
feedDesc: FeedDescriptor,
|
||||||
|
params: FeedParams,
|
||||||
|
feedTuners: FeedTunerFn[],
|
||||||
|
) {
|
||||||
|
if (feedDesc === 'home') {
|
||||||
|
return new MergeFeedAPI(params, feedTuners)
|
||||||
|
} else if (feedDesc === 'following') {
|
||||||
|
return new FollowingFeedAPI()
|
||||||
|
} else if (feedDesc.startsWith('author')) {
|
||||||
|
const [_, actor, filter] = feedDesc.split('|')
|
||||||
|
return new AuthorFeedAPI({actor, filter})
|
||||||
|
} else if (feedDesc.startsWith('likes')) {
|
||||||
|
const [_, actor] = feedDesc.split('|')
|
||||||
|
return new LikesFeedAPI({actor})
|
||||||
|
} else if (feedDesc.startsWith('feedgen')) {
|
||||||
|
const [_, feed] = feedDesc.split('|')
|
||||||
|
return new CustomFeedAPI({feed})
|
||||||
|
} else if (feedDesc.startsWith('list')) {
|
||||||
|
const [_, list] = feedDesc.split('|')
|
||||||
|
return new ListFeedAPI({list})
|
||||||
|
} else {
|
||||||
|
// shouldnt happen
|
||||||
|
return new FollowingFeedAPI()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -196,8 +227,10 @@ export function usePostFeedQuery(
|
||||||
export function findPostInQueryData(
|
export function findPostInQueryData(
|
||||||
queryClient: QueryClient,
|
queryClient: QueryClient,
|
||||||
uri: string,
|
uri: string,
|
||||||
): FeedPostSliceItem | undefined {
|
): AppBskyFeedDefs.FeedViewPost | undefined {
|
||||||
const queryDatas = queryClient.getQueriesData<InfiniteData<FeedPage>>({
|
const queryDatas = queryClient.getQueriesData<
|
||||||
|
InfiniteData<FeedPageUnselected>
|
||||||
|
>({
|
||||||
queryKey: ['post-feed'],
|
queryKey: ['post-feed'],
|
||||||
})
|
})
|
||||||
for (const [_queryKey, queryData] of queryDatas) {
|
for (const [_queryKey, queryData] of queryDatas) {
|
||||||
|
@ -205,14 +238,34 @@ export function findPostInQueryData(
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for (const page of queryData?.pages) {
|
for (const page of queryData?.pages) {
|
||||||
for (const slice of page.slices) {
|
for (const item of page.feed) {
|
||||||
for (const item of slice.items) {
|
if (item.post.uri === uri) {
|
||||||
if (item.uri === uri) {
|
|
||||||
return item
|
return item
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function assertSomePostsPassModeration(feed: AppBskyFeedDefs.FeedViewPost[]) {
|
||||||
|
// assume false
|
||||||
|
let somePostsPassModeration = false
|
||||||
|
|
||||||
|
for (const item of feed) {
|
||||||
|
const moderationOpts = getModerationOpts({
|
||||||
|
userDid: '',
|
||||||
|
preferences: DEFAULT_LOGGED_OUT_PREFERENCES,
|
||||||
|
})
|
||||||
|
const moderation = moderatePost(item.post, moderationOpts)
|
||||||
|
|
||||||
|
if (!moderation.content.filter) {
|
||||||
|
// we have a sfw post
|
||||||
|
somePostsPassModeration = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!somePostsPassModeration) {
|
||||||
|
throw new Error(KnownError.FeedNSFPublic)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ import {AppBskyFeedGetLikes} from '@atproto/api'
|
||||||
import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
|
import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
|
||||||
|
|
||||||
import {getAgent} from '#/state/session'
|
import {getAgent} from '#/state/session'
|
||||||
import {STALE} from '#/state/queries'
|
|
||||||
|
|
||||||
const PAGE_SIZE = 30
|
const PAGE_SIZE = 30
|
||||||
type RQPageParam = string | undefined
|
type RQPageParam = string | undefined
|
||||||
|
@ -18,7 +17,6 @@ export function usePostLikedByQuery(resolvedUri: string | undefined) {
|
||||||
QueryKey,
|
QueryKey,
|
||||||
RQPageParam
|
RQPageParam
|
||||||
>({
|
>({
|
||||||
staleTime: STALE.MINUTES.ONE,
|
|
||||||
queryKey: RQKEY(resolvedUri || ''),
|
queryKey: RQKEY(resolvedUri || ''),
|
||||||
async queryFn({pageParam}: {pageParam: RQPageParam}) {
|
async queryFn({pageParam}: {pageParam: RQPageParam}) {
|
||||||
const res = await getAgent().getLikes({
|
const res = await getAgent().getLikes({
|
||||||
|
|
|
@ -2,7 +2,6 @@ import {AppBskyFeedGetRepostedBy} from '@atproto/api'
|
||||||
import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
|
import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
|
||||||
|
|
||||||
import {getAgent} from '#/state/session'
|
import {getAgent} from '#/state/session'
|
||||||
import {STALE} from '#/state/queries'
|
|
||||||
|
|
||||||
const PAGE_SIZE = 30
|
const PAGE_SIZE = 30
|
||||||
type RQPageParam = string | undefined
|
type RQPageParam = string | undefined
|
||||||
|
@ -18,7 +17,6 @@ export function usePostRepostedByQuery(resolvedUri: string | undefined) {
|
||||||
QueryKey,
|
QueryKey,
|
||||||
RQPageParam
|
RQPageParam
|
||||||
>({
|
>({
|
||||||
staleTime: STALE.MINUTES.ONE,
|
|
||||||
queryKey: RQKEY(resolvedUri || ''),
|
queryKey: RQKEY(resolvedUri || ''),
|
||||||
async queryFn({pageParam}: {pageParam: RQPageParam}) {
|
async queryFn({pageParam}: {pageParam: RQPageParam}) {
|
||||||
const res = await getAgent().getRepostedBy({
|
const res = await getAgent().getRepostedBy({
|
||||||
|
|
|
@ -7,11 +7,7 @@ import {useQuery, useQueryClient, QueryClient} from '@tanstack/react-query'
|
||||||
|
|
||||||
import {getAgent} from '#/state/session'
|
import {getAgent} from '#/state/session'
|
||||||
import {UsePreferencesQueryResponse} from '#/state/queries/preferences/types'
|
import {UsePreferencesQueryResponse} from '#/state/queries/preferences/types'
|
||||||
import {STALE} from '#/state/queries'
|
import {findPostInQueryData as findPostInFeedQueryData} from './post-feed'
|
||||||
import {
|
|
||||||
findPostInQueryData as findPostInFeedQueryData,
|
|
||||||
FeedPostSliceItem,
|
|
||||||
} from './post-feed'
|
|
||||||
import {findPostInQueryData as findPostInNotifsQueryData} from './notifications/feed'
|
import {findPostInQueryData as findPostInNotifsQueryData} from './notifications/feed'
|
||||||
import {precacheThreadPosts as precacheResolvedUris} from './resolve-uri'
|
import {precacheThreadPosts as precacheResolvedUris} from './resolve-uri'
|
||||||
|
|
||||||
|
@ -68,7 +64,6 @@ export type ThreadNode =
|
||||||
export function usePostThreadQuery(uri: string | undefined) {
|
export function usePostThreadQuery(uri: string | undefined) {
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
return useQuery<ThreadNode, Error>({
|
return useQuery<ThreadNode, Error>({
|
||||||
staleTime: STALE.MINUTES.ONE,
|
|
||||||
queryKey: RQKEY(uri || ''),
|
queryKey: RQKEY(uri || ''),
|
||||||
async queryFn() {
|
async queryFn() {
|
||||||
const res = await getAgent().getPostThread({uri: uri!})
|
const res = await getAgent().getPostThread({uri: uri!})
|
||||||
|
@ -93,7 +88,7 @@ export function usePostThreadQuery(uri: string | undefined) {
|
||||||
{
|
{
|
||||||
const item = findPostInFeedQueryData(queryClient, uri)
|
const item = findPostInFeedQueryData(queryClient, uri)
|
||||||
if (item) {
|
if (item) {
|
||||||
return feedItemToPlaceholderThread(item)
|
return feedViewPostToPlaceholderThread(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -275,13 +270,15 @@ function threadNodeToPlaceholderThread(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function feedItemToPlaceholderThread(item: FeedPostSliceItem): ThreadNode {
|
function feedViewPostToPlaceholderThread(
|
||||||
|
item: AppBskyFeedDefs.FeedViewPost,
|
||||||
|
): ThreadNode {
|
||||||
return {
|
return {
|
||||||
type: 'post',
|
type: 'post',
|
||||||
_reactKey: item.post.uri,
|
_reactKey: item.post.uri,
|
||||||
uri: item.post.uri,
|
uri: item.post.uri,
|
||||||
post: item.post,
|
post: item.post,
|
||||||
record: item.record,
|
record: item.post.record as AppBskyFeedPost.Record, // validated in post-feed
|
||||||
parent: undefined,
|
parent: undefined,
|
||||||
replies: undefined,
|
replies: undefined,
|
||||||
viewer: item.post.viewer,
|
viewer: item.post.viewer,
|
||||||
|
@ -291,7 +288,7 @@ function feedItemToPlaceholderThread(item: FeedPostSliceItem): ThreadNode {
|
||||||
hasMore: false,
|
hasMore: false,
|
||||||
showChildReplyLine: false,
|
showChildReplyLine: false,
|
||||||
showParentReplyLine: false,
|
showParentReplyLine: false,
|
||||||
isParentLoading: !!item.record.reply,
|
isParentLoading: !!(item.post.record as AppBskyFeedPost.Record).reply,
|
||||||
isChildLoading: !!item.post.replyCount,
|
isChildLoading: !!item.post.replyCount,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -305,7 +302,7 @@ function postViewToPlaceholderThread(
|
||||||
_reactKey: post.uri,
|
_reactKey: post.uri,
|
||||||
uri: post.uri,
|
uri: post.uri,
|
||||||
post: post,
|
post: post,
|
||||||
record: post.record as AppBskyFeedPost.Record, // validate in notifs
|
record: post.record as AppBskyFeedPost.Record, // validated in notifs
|
||||||
parent: undefined,
|
parent: undefined,
|
||||||
replies: undefined,
|
replies: undefined,
|
||||||
viewer: post.viewer,
|
viewer: post.viewer,
|
||||||
|
|
|
@ -4,13 +4,11 @@ import {useQuery, useMutation, useQueryClient} from '@tanstack/react-query'
|
||||||
|
|
||||||
import {getAgent} from '#/state/session'
|
import {getAgent} from '#/state/session'
|
||||||
import {updatePostShadow} from '#/state/cache/post-shadow'
|
import {updatePostShadow} from '#/state/cache/post-shadow'
|
||||||
import {STALE} from '#/state/queries'
|
|
||||||
|
|
||||||
export const RQKEY = (postUri: string) => ['post', postUri]
|
export const RQKEY = (postUri: string) => ['post', postUri]
|
||||||
|
|
||||||
export function usePostQuery(uri: string | undefined) {
|
export function usePostQuery(uri: string | undefined) {
|
||||||
return useQuery<AppBskyFeedDefs.PostView>({
|
return useQuery<AppBskyFeedDefs.PostView>({
|
||||||
staleTime: STALE.MINUTES.ONE,
|
|
||||||
queryKey: RQKEY(uri || ''),
|
queryKey: RQKEY(uri || ''),
|
||||||
async queryFn() {
|
async queryFn() {
|
||||||
const res = await getAgent().getPosts({uris: [uri!]})
|
const res = await getAgent().getPosts({uris: [uri!]})
|
||||||
|
@ -29,7 +27,6 @@ export function useGetPost() {
|
||||||
return React.useCallback(
|
return React.useCallback(
|
||||||
async ({uri}: {uri: string}) => {
|
async ({uri}: {uri: string}) => {
|
||||||
return queryClient.fetchQuery({
|
return queryClient.fetchQuery({
|
||||||
staleTime: STALE.MINUTES.ONE,
|
|
||||||
queryKey: RQKEY(uri || ''),
|
queryKey: RQKEY(uri || ''),
|
||||||
async queryFn() {
|
async queryFn() {
|
||||||
const urip = new AtUri(uri)
|
const urip = new AtUri(uri)
|
||||||
|
|
|
@ -2,7 +2,6 @@ import {AppBskyFeedGetActorFeeds} from '@atproto/api'
|
||||||
import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
|
import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
|
||||||
|
|
||||||
import {getAgent} from '#/state/session'
|
import {getAgent} from '#/state/session'
|
||||||
import {STALE} from '#/state/queries'
|
|
||||||
|
|
||||||
const PAGE_SIZE = 30
|
const PAGE_SIZE = 30
|
||||||
type RQPageParam = string | undefined
|
type RQPageParam = string | undefined
|
||||||
|
@ -22,7 +21,6 @@ export function useProfileFeedgensQuery(
|
||||||
QueryKey,
|
QueryKey,
|
||||||
RQPageParam
|
RQPageParam
|
||||||
>({
|
>({
|
||||||
staleTime: STALE.MINUTES.ONE,
|
|
||||||
queryKey: RQKEY(did),
|
queryKey: RQKEY(did),
|
||||||
async queryFn({pageParam}: {pageParam: RQPageParam}) {
|
async queryFn({pageParam}: {pageParam: RQPageParam}) {
|
||||||
const res = await getAgent().app.bsky.feed.getActorFeeds({
|
const res = await getAgent().app.bsky.feed.getActorFeeds({
|
||||||
|
|
|
@ -2,7 +2,6 @@ import {AppBskyGraphGetFollowers} from '@atproto/api'
|
||||||
import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
|
import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
|
||||||
|
|
||||||
import {getAgent} from '#/state/session'
|
import {getAgent} from '#/state/session'
|
||||||
import {STALE} from '#/state/queries'
|
|
||||||
|
|
||||||
const PAGE_SIZE = 30
|
const PAGE_SIZE = 30
|
||||||
type RQPageParam = string | undefined
|
type RQPageParam = string | undefined
|
||||||
|
@ -17,7 +16,6 @@ export function useProfileFollowersQuery(did: string | undefined) {
|
||||||
QueryKey,
|
QueryKey,
|
||||||
RQPageParam
|
RQPageParam
|
||||||
>({
|
>({
|
||||||
staleTime: STALE.MINUTES.FIVE,
|
|
||||||
queryKey: RQKEY(did || ''),
|
queryKey: RQKEY(did || ''),
|
||||||
async queryFn({pageParam}: {pageParam: RQPageParam}) {
|
async queryFn({pageParam}: {pageParam: RQPageParam}) {
|
||||||
const res = await getAgent().app.bsky.graph.getFollowers({
|
const res = await getAgent().app.bsky.graph.getFollowers({
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import {AppBskyGraphGetLists} from '@atproto/api'
|
import {AppBskyGraphGetLists} from '@atproto/api'
|
||||||
import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
|
import {useInfiniteQuery, InfiniteData, QueryKey} from '@tanstack/react-query'
|
||||||
|
|
||||||
import {getAgent} from '#/state/session'
|
import {getAgent} from '#/state/session'
|
||||||
import {STALE} from '#/state/queries'
|
|
||||||
|
|
||||||
const PAGE_SIZE = 30
|
const PAGE_SIZE = 30
|
||||||
type RQPageParam = string | undefined
|
type RQPageParam = string | undefined
|
||||||
|
@ -18,7 +16,6 @@ export function useProfileListsQuery(did: string, opts?: {enabled?: boolean}) {
|
||||||
QueryKey,
|
QueryKey,
|
||||||
RQPageParam
|
RQPageParam
|
||||||
>({
|
>({
|
||||||
staleTime: STALE.MINUTES.ONE,
|
|
||||||
queryKey: RQKEY(did),
|
queryKey: RQKEY(did),
|
||||||
async queryFn({pageParam}: {pageParam: RQPageParam}) {
|
async queryFn({pageParam}: {pageParam: RQPageParam}) {
|
||||||
const res = await getAgent().app.bsky.graph.getLists({
|
const res = await getAgent().app.bsky.graph.getLists({
|
||||||
|
|
|
@ -4,7 +4,6 @@ import {
|
||||||
AppBskyActorDefs,
|
AppBskyActorDefs,
|
||||||
AppBskyActorProfile,
|
AppBskyActorProfile,
|
||||||
AppBskyActorGetProfile,
|
AppBskyActorGetProfile,
|
||||||
BskyAgent,
|
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
import {useQuery, useQueryClient, useMutation} from '@tanstack/react-query'
|
import {useQuery, useQueryClient, useMutation} from '@tanstack/react-query'
|
||||||
import {Image as RNImage} from 'react-native-image-crop-picker'
|
import {Image as RNImage} from 'react-native-image-crop-picker'
|
||||||
|
@ -22,6 +21,10 @@ export const RQKEY = (did: string) => ['profile', did]
|
||||||
|
|
||||||
export function useProfileQuery({did}: {did: string | undefined}) {
|
export function useProfileQuery({did}: {did: string | undefined}) {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
|
// WARNING
|
||||||
|
// this staleTime is load-bearing
|
||||||
|
// if you remove it, the UI infinite-loops
|
||||||
|
// -prf
|
||||||
staleTime: STALE.MINUTES.FIVE,
|
staleTime: STALE.MINUTES.FIVE,
|
||||||
queryKey: RQKEY(did || ''),
|
queryKey: RQKEY(did || ''),
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
|
@ -68,7 +71,7 @@ export function useProfileUpdateMutation() {
|
||||||
}
|
}
|
||||||
return existing
|
return existing
|
||||||
})
|
})
|
||||||
await whenAppViewReady(getAgent(), profile.did, res => {
|
await whenAppViewReady(profile.did, res => {
|
||||||
if (typeof newUserAvatar !== 'undefined') {
|
if (typeof newUserAvatar !== 'undefined') {
|
||||||
if (newUserAvatar === null && res.data.avatar) {
|
if (newUserAvatar === null && res.data.avatar) {
|
||||||
// url hasnt cleared yet
|
// url hasnt cleared yet
|
||||||
|
@ -464,7 +467,6 @@ function useProfileUnblockMutation() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function whenAppViewReady(
|
async function whenAppViewReady(
|
||||||
agent: BskyAgent,
|
|
||||||
actor: string,
|
actor: string,
|
||||||
fn: (res: AppBskyActorGetProfile.Response) => boolean,
|
fn: (res: AppBskyActorGetProfile.Response) => boolean,
|
||||||
) {
|
) {
|
||||||
|
@ -472,6 +474,6 @@ async function whenAppViewReady(
|
||||||
5, // 5 tries
|
5, // 5 tries
|
||||||
1e3, // 1s delay between tries
|
1e3, // 1s delay between tries
|
||||||
fn,
|
fn,
|
||||||
() => agent.app.bsky.actor.getProfile({actor}),
|
() => getAgent().app.bsky.actor.getProfile({actor}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ export function useResolveUriQuery(uri: string | undefined): UriUseQueryResult {
|
||||||
|
|
||||||
export function useResolveDidQuery(didOrHandle: string | undefined) {
|
export function useResolveDidQuery(didOrHandle: string | undefined) {
|
||||||
return useQuery<string, Error>({
|
return useQuery<string, Error>({
|
||||||
staleTime: STALE.INFINITY,
|
staleTime: STALE.HOURS.ONE,
|
||||||
queryKey: RQKEY(didOrHandle || ''),
|
queryKey: RQKEY(didOrHandle || ''),
|
||||||
async queryFn() {
|
async queryFn() {
|
||||||
if (!didOrHandle) {
|
if (!didOrHandle) {
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
import {BskyAgent} from '@atproto/api'
|
import {BskyAgent} from '@atproto/api'
|
||||||
import {useQuery} from '@tanstack/react-query'
|
import {useQuery} from '@tanstack/react-query'
|
||||||
|
|
||||||
import {STALE} from '#/state/queries'
|
|
||||||
|
|
||||||
export const RQKEY = (serviceUrl: string) => ['service', serviceUrl]
|
export const RQKEY = (serviceUrl: string) => ['service', serviceUrl]
|
||||||
|
|
||||||
export function useServiceQuery(serviceUrl: string) {
|
export function useServiceQuery(serviceUrl: string) {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
staleTime: STALE.HOURS.ONE,
|
|
||||||
queryKey: RQKEY(serviceUrl),
|
queryKey: RQKEY(serviceUrl),
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const agent = new BskyAgent({service: serviceUrl})
|
const agent = new BskyAgent({service: serviceUrl})
|
||||||
|
|
|
@ -90,7 +90,7 @@ export function useGetSuggestedFollowersByActor() {
|
||||||
return React.useCallback(
|
return React.useCallback(
|
||||||
async (actor: string) => {
|
async (actor: string) => {
|
||||||
const res = await queryClient.fetchQuery({
|
const res = await queryClient.fetchQuery({
|
||||||
staleTime: 60 * 1000,
|
staleTime: STALE.MINUTES.ONE,
|
||||||
queryKey: suggestedFollowsByActorQueryKey(actor),
|
queryKey: suggestedFollowsByActorQueryKey(actor),
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const res =
|
const res =
|
||||||
|
|
|
@ -13,6 +13,12 @@ import {useCloseAllActiveElements} from '#/state/util'
|
||||||
|
|
||||||
let __globalAgent: BskyAgent = PUBLIC_BSKY_AGENT
|
let __globalAgent: BskyAgent = PUBLIC_BSKY_AGENT
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NOTE
|
||||||
|
* Never hold on to the object returned by this function.
|
||||||
|
* Call `getAgent()` at the time of invocation to ensure
|
||||||
|
* that you never have a stale agent.
|
||||||
|
*/
|
||||||
export function getAgent() {
|
export function getAgent() {
|
||||||
return __globalAgent
|
return __globalAgent
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,30 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {ScrollView, TouchableOpacity, View} from 'react-native'
|
import {ScrollView, TouchableOpacity, View} from 'react-native'
|
||||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
import {
|
||||||
|
FontAwesomeIcon,
|
||||||
|
FontAwesomeIconStyle,
|
||||||
|
} from '@fortawesome/react-native-fontawesome'
|
||||||
import {useAnalytics} from 'lib/analytics/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {Text} from '../../util/text/Text'
|
import {Text} from '../../util/text/Text'
|
||||||
import {UserAvatar} from '../../util/UserAvatar'
|
import {UserAvatar} from '../../util/UserAvatar'
|
||||||
import {s} from 'lib/styles'
|
import {s, colors} from 'lib/styles'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
import {Trans, msg} from '@lingui/macro'
|
import {Trans, msg} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {styles} from './styles'
|
import {styles} from './styles'
|
||||||
import {useSession, useSessionApi, SessionAccount} from '#/state/session'
|
import {useSession, useSessionApi, SessionAccount} from '#/state/session'
|
||||||
import {useProfileQuery} from '#/state/queries/profile'
|
import {useProfileQuery} from '#/state/queries/profile'
|
||||||
|
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
||||||
|
import * as Toast from '#/view/com/util/Toast'
|
||||||
|
|
||||||
function AccountItem({
|
function AccountItem({
|
||||||
account,
|
account,
|
||||||
onSelect,
|
onSelect,
|
||||||
|
isCurrentAccount,
|
||||||
}: {
|
}: {
|
||||||
account: SessionAccount
|
account: SessionAccount
|
||||||
onSelect: (account: SessionAccount) => void
|
onSelect: (account: SessionAccount) => void
|
||||||
|
isCurrentAccount: boolean
|
||||||
}) {
|
}) {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
@ -48,11 +55,19 @@ function AccountItem({
|
||||||
{account.handle}
|
{account.handle}
|
||||||
</Text>
|
</Text>
|
||||||
</Text>
|
</Text>
|
||||||
|
{isCurrentAccount ? (
|
||||||
|
<FontAwesomeIcon
|
||||||
|
icon="check"
|
||||||
|
size={16}
|
||||||
|
style={[{color: colors.green3} as FontAwesomeIconStyle, s.mr10]}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
icon="angle-right"
|
icon="angle-right"
|
||||||
size={16}
|
size={16}
|
||||||
style={[pal.text, s.mr10]}
|
style={[pal.text, s.mr10]}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
)
|
)
|
||||||
|
@ -67,8 +82,9 @@ export const ChooseAccountForm = ({
|
||||||
const {track, screen} = useAnalytics()
|
const {track, screen} = useAnalytics()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const {accounts} = useSession()
|
const {accounts, currentAccount} = useSession()
|
||||||
const {initSession} = useSessionApi()
|
const {initSession} = useSessionApi()
|
||||||
|
const {setShowLoggedOut} = useLoggedOutViewControls()
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
screen('Choose Account')
|
screen('Choose Account')
|
||||||
|
@ -77,13 +93,21 @@ export const ChooseAccountForm = ({
|
||||||
const onSelect = React.useCallback(
|
const onSelect = React.useCallback(
|
||||||
async (account: SessionAccount) => {
|
async (account: SessionAccount) => {
|
||||||
if (account.accessJwt) {
|
if (account.accessJwt) {
|
||||||
|
if (account.did === currentAccount?.did) {
|
||||||
|
setShowLoggedOut(false)
|
||||||
|
Toast.show(`Already signed in as @${account.handle}`)
|
||||||
|
} else {
|
||||||
await initSession(account)
|
await initSession(account)
|
||||||
track('Sign In', {resumedSession: true})
|
track('Sign In', {resumedSession: true})
|
||||||
|
setTimeout(() => {
|
||||||
|
Toast.show(`Signed in as @${account.handle}`)
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
onSelectAccount(account)
|
onSelectAccount(account)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[track, initSession, onSelectAccount],
|
[currentAccount, track, initSession, onSelectAccount, setShowLoggedOut],
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -94,7 +118,12 @@ export const ChooseAccountForm = ({
|
||||||
<Trans>Sign in as...</Trans>
|
<Trans>Sign in as...</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
{accounts.map(account => (
|
{accounts.map(account => (
|
||||||
<AccountItem key={account.did} account={account} onSelect={onSelect} />
|
<AccountItem
|
||||||
|
key={account.did}
|
||||||
|
account={account}
|
||||||
|
onSelect={onSelect}
|
||||||
|
isCurrentAccount={account.did === currentAccount?.did}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
testID="chooseNewAccountBtn"
|
testID="chooseNewAccountBtn"
|
||||||
|
|
|
@ -62,7 +62,7 @@ export function FeedPage({
|
||||||
const onSoftReset = React.useCallback(() => {
|
const onSoftReset = React.useCallback(() => {
|
||||||
if (isPageFocused) {
|
if (isPageFocused) {
|
||||||
scrollToTop()
|
scrollToTop()
|
||||||
queryClient.invalidateQueries({queryKey: FEED_RQKEY(feed)})
|
queryClient.resetQueries({queryKey: FEED_RQKEY(feed)})
|
||||||
setHasNew(false)
|
setHasNew(false)
|
||||||
}
|
}
|
||||||
}, [isPageFocused, scrollToTop, queryClient, feed, setHasNew])
|
}, [isPageFocused, scrollToTop, queryClient, feed, setHasNew])
|
||||||
|
@ -83,7 +83,7 @@ export function FeedPage({
|
||||||
|
|
||||||
const onPressLoadLatest = React.useCallback(() => {
|
const onPressLoadLatest = React.useCallback(() => {
|
||||||
scrollToTop()
|
scrollToTop()
|
||||||
queryClient.invalidateQueries({queryKey: FEED_RQKEY(feed)})
|
queryClient.resetQueries({queryKey: FEED_RQKEY(feed)})
|
||||||
setHasNew(false)
|
setHasNew(false)
|
||||||
}, [scrollToTop, feed, queryClient, setHasNew])
|
}, [scrollToTop, feed, queryClient, setHasNew])
|
||||||
|
|
||||||
|
|
|
@ -17,12 +17,14 @@ import {useModalControls} from '#/state/modals'
|
||||||
import {msg} from '@lingui/macro'
|
import {msg} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {
|
import {
|
||||||
|
usePinFeedMutation,
|
||||||
UsePreferencesQueryResponse,
|
UsePreferencesQueryResponse,
|
||||||
usePreferencesQuery,
|
usePreferencesQuery,
|
||||||
useSaveFeedMutation,
|
useSaveFeedMutation,
|
||||||
useRemoveFeedMutation,
|
useRemoveFeedMutation,
|
||||||
} from '#/state/queries/preferences'
|
} from '#/state/queries/preferences'
|
||||||
import {useFeedSourceInfoQuery, FeedSourceInfo} from '#/state/queries/feed'
|
import {useFeedSourceInfoQuery, FeedSourceInfo} from '#/state/queries/feed'
|
||||||
|
import {FeedLoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder'
|
||||||
|
|
||||||
export function FeedSourceCard({
|
export function FeedSourceCard({
|
||||||
feedUri,
|
feedUri,
|
||||||
|
@ -30,17 +32,27 @@ export function FeedSourceCard({
|
||||||
showSaveBtn = false,
|
showSaveBtn = false,
|
||||||
showDescription = false,
|
showDescription = false,
|
||||||
showLikes = false,
|
showLikes = false,
|
||||||
|
LoadingComponent,
|
||||||
|
pinOnSave = false,
|
||||||
}: {
|
}: {
|
||||||
feedUri: string
|
feedUri: string
|
||||||
style?: StyleProp<ViewStyle>
|
style?: StyleProp<ViewStyle>
|
||||||
showSaveBtn?: boolean
|
showSaveBtn?: boolean
|
||||||
showDescription?: boolean
|
showDescription?: boolean
|
||||||
showLikes?: boolean
|
showLikes?: boolean
|
||||||
|
LoadingComponent?: JSX.Element
|
||||||
|
pinOnSave?: boolean
|
||||||
}) {
|
}) {
|
||||||
const {data: preferences} = usePreferencesQuery()
|
const {data: preferences} = usePreferencesQuery()
|
||||||
const {data: feed} = useFeedSourceInfoQuery({uri: feedUri})
|
const {data: feed} = useFeedSourceInfoQuery({uri: feedUri})
|
||||||
|
|
||||||
if (!feed || !preferences) return null
|
if (!feed || !preferences) {
|
||||||
|
return LoadingComponent ? (
|
||||||
|
LoadingComponent
|
||||||
|
) : (
|
||||||
|
<FeedLoadingPlaceholder style={{flex: 1}} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FeedSourceCardLoaded
|
<FeedSourceCardLoaded
|
||||||
|
@ -50,6 +62,7 @@ export function FeedSourceCard({
|
||||||
showSaveBtn={showSaveBtn}
|
showSaveBtn={showSaveBtn}
|
||||||
showDescription={showDescription}
|
showDescription={showDescription}
|
||||||
showLikes={showLikes}
|
showLikes={showLikes}
|
||||||
|
pinOnSave={pinOnSave}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -61,6 +74,7 @@ export function FeedSourceCardLoaded({
|
||||||
showSaveBtn = false,
|
showSaveBtn = false,
|
||||||
showDescription = false,
|
showDescription = false,
|
||||||
showLikes = false,
|
showLikes = false,
|
||||||
|
pinOnSave = false,
|
||||||
}: {
|
}: {
|
||||||
feed: FeedSourceInfo
|
feed: FeedSourceInfo
|
||||||
preferences: UsePreferencesQueryResponse
|
preferences: UsePreferencesQueryResponse
|
||||||
|
@ -68,6 +82,7 @@ export function FeedSourceCardLoaded({
|
||||||
showSaveBtn?: boolean
|
showSaveBtn?: boolean
|
||||||
showDescription?: boolean
|
showDescription?: boolean
|
||||||
showLikes?: boolean
|
showLikes?: boolean
|
||||||
|
pinOnSave?: boolean
|
||||||
}) {
|
}) {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
|
@ -78,6 +93,7 @@ export function FeedSourceCardLoaded({
|
||||||
useSaveFeedMutation()
|
useSaveFeedMutation()
|
||||||
const {isPending: isRemovePending, mutateAsync: removeFeed} =
|
const {isPending: isRemovePending, mutateAsync: removeFeed} =
|
||||||
useRemoveFeedMutation()
|
useRemoveFeedMutation()
|
||||||
|
const {isPending: isPinPending, mutateAsync: pinFeed} = usePinFeedMutation()
|
||||||
|
|
||||||
const isSaved = Boolean(preferences?.feeds?.saved?.includes(feed.uri))
|
const isSaved = Boolean(preferences?.feeds?.saved?.includes(feed.uri))
|
||||||
|
|
||||||
|
@ -103,14 +119,18 @@ export function FeedSourceCardLoaded({
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
|
if (pinOnSave) {
|
||||||
|
await pinFeed({uri: feed.uri})
|
||||||
|
} else {
|
||||||
await saveFeed({uri: feed.uri})
|
await saveFeed({uri: feed.uri})
|
||||||
|
}
|
||||||
Toast.show('Added to my feeds')
|
Toast.show('Added to my feeds')
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Toast.show('There was an issue contacting your server')
|
Toast.show('There was an issue contacting your server')
|
||||||
logger.error('Failed to save feed', {error: e})
|
logger.error('Failed to save feed', {error: e})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [isSaved, openModal, feed, removeFeed, saveFeed, _])
|
}, [isSaved, openModal, feed, removeFeed, saveFeed, _, pinOnSave, pinFeed])
|
||||||
|
|
||||||
if (!feed || !preferences) return null
|
if (!feed || !preferences) return null
|
||||||
|
|
||||||
|
@ -150,7 +170,7 @@ export function FeedSourceCardLoaded({
|
||||||
{showSaveBtn && feed.type === 'feed' && (
|
{showSaveBtn && feed.type === 'feed' && (
|
||||||
<View>
|
<View>
|
||||||
<Pressable
|
<Pressable
|
||||||
disabled={isSavePending || isRemovePending}
|
disabled={isSavePending || isPinPending || isRemovePending}
|
||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
accessibilityLabel={
|
accessibilityLabel={
|
||||||
isSaved ? 'Remove from my feeds' : 'Add to my feeds'
|
isSaved ? 'Remove from my feeds' : 'Add to my feeds'
|
||||||
|
|
|
@ -35,15 +35,13 @@ export function Feed({
|
||||||
const [isPTRing, setIsPTRing] = React.useState(false)
|
const [isPTRing, setIsPTRing] = React.useState(false)
|
||||||
|
|
||||||
const moderationOpts = useModerationOpts()
|
const moderationOpts = useModerationOpts()
|
||||||
const {markAllRead} = useUnreadNotificationsApi()
|
const {markAllRead, checkUnread} = useUnreadNotificationsApi()
|
||||||
const {
|
const {
|
||||||
data,
|
data,
|
||||||
isLoading,
|
|
||||||
isFetching,
|
isFetching,
|
||||||
isFetched,
|
isFetched,
|
||||||
isError,
|
isError,
|
||||||
error,
|
error,
|
||||||
refetch,
|
|
||||||
hasNextPage,
|
hasNextPage,
|
||||||
isFetchingNextPage,
|
isFetchingNextPage,
|
||||||
fetchNextPage,
|
fetchNextPage,
|
||||||
|
@ -52,13 +50,11 @@ export function Feed({
|
||||||
const firstItem = data?.pages[0]?.items[0]
|
const firstItem = data?.pages[0]?.items[0]
|
||||||
|
|
||||||
// mark all read on fresh data
|
// mark all read on fresh data
|
||||||
|
// (this will fire each time firstItem changes)
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
let cleanup
|
|
||||||
if (firstItem) {
|
if (firstItem) {
|
||||||
const to = setTimeout(() => markAllRead(), 250)
|
markAllRead()
|
||||||
cleanup = () => clearTimeout(to)
|
|
||||||
}
|
}
|
||||||
return cleanup
|
|
||||||
}, [firstItem, markAllRead])
|
}, [firstItem, markAllRead])
|
||||||
|
|
||||||
const items = React.useMemo(() => {
|
const items = React.useMemo(() => {
|
||||||
|
@ -83,7 +79,7 @@ export function Feed({
|
||||||
const onRefresh = React.useCallback(async () => {
|
const onRefresh = React.useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
setIsPTRing(true)
|
setIsPTRing(true)
|
||||||
await refetch()
|
await checkUnread({invalidate: true})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('Failed to refresh notifications feed', {
|
logger.error('Failed to refresh notifications feed', {
|
||||||
error: err,
|
error: err,
|
||||||
|
@ -91,7 +87,7 @@ export function Feed({
|
||||||
} finally {
|
} finally {
|
||||||
setIsPTRing(false)
|
setIsPTRing(false)
|
||||||
}
|
}
|
||||||
}, [refetch, setIsPTRing])
|
}, [checkUnread, setIsPTRing])
|
||||||
|
|
||||||
const onEndReached = React.useCallback(async () => {
|
const onEndReached = React.useCallback(async () => {
|
||||||
if (isFetching || !hasNextPage || isError) return
|
if (isFetching || !hasNextPage || isError) return
|
||||||
|
@ -136,21 +132,6 @@ export function Feed({
|
||||||
[onPressRetryLoadMore, moderationOpts],
|
[onPressRetryLoadMore, moderationOpts],
|
||||||
)
|
)
|
||||||
|
|
||||||
const showHeaderSpinner = !isPTRing && isFetching && !isLoading
|
|
||||||
const FeedHeader = React.useCallback(
|
|
||||||
() => (
|
|
||||||
<View>
|
|
||||||
{ListHeaderComponent ? <ListHeaderComponent /> : null}
|
|
||||||
{showHeaderSpinner ? (
|
|
||||||
<View style={{padding: 10}}>
|
|
||||||
<ActivityIndicator />
|
|
||||||
</View>
|
|
||||||
) : null}
|
|
||||||
</View>
|
|
||||||
),
|
|
||||||
[ListHeaderComponent, showHeaderSpinner],
|
|
||||||
)
|
|
||||||
|
|
||||||
const FeedFooter = React.useCallback(
|
const FeedFooter = React.useCallback(
|
||||||
() =>
|
() =>
|
||||||
isFetchingNextPage ? (
|
isFetchingNextPage ? (
|
||||||
|
@ -180,7 +161,7 @@ export function Feed({
|
||||||
data={items}
|
data={items}
|
||||||
keyExtractor={item => item._reactKey}
|
keyExtractor={item => item._reactKey}
|
||||||
renderItem={renderItem}
|
renderItem={renderItem}
|
||||||
ListHeaderComponent={FeedHeader}
|
ListHeaderComponent={ListHeaderComponent}
|
||||||
ListFooterComponent={FeedFooter}
|
ListFooterComponent={FeedFooter}
|
||||||
refreshControl={
|
refreshControl={
|
||||||
<RefreshControl
|
<RefreshControl
|
||||||
|
|
|
@ -12,6 +12,9 @@ import {usePinnedFeedsInfos} from '#/state/queries/feed'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
import {TextLink} from '#/view/com/util/Link'
|
import {TextLink} from '#/view/com/util/Link'
|
||||||
import {CenteredView} from '../util/Views'
|
import {CenteredView} from '../util/Views'
|
||||||
|
import {isWeb} from 'platform/detection'
|
||||||
|
import {useNavigation} from '@react-navigation/native'
|
||||||
|
import {NavigationProp} from 'lib/routes/types'
|
||||||
|
|
||||||
export function FeedsTabBar(
|
export function FeedsTabBar(
|
||||||
props: RenderTabBarFnProps & {testID?: string; onPressSelected: () => void},
|
props: RenderTabBarFnProps & {testID?: string; onPressSelected: () => void},
|
||||||
|
@ -79,11 +82,37 @@ function FeedsTabBarPublic() {
|
||||||
function FeedsTabBarTablet(
|
function FeedsTabBarTablet(
|
||||||
props: RenderTabBarFnProps & {testID?: string; onPressSelected: () => void},
|
props: RenderTabBarFnProps & {testID?: string; onPressSelected: () => void},
|
||||||
) {
|
) {
|
||||||
const feeds = usePinnedFeedsInfos()
|
const {feeds, hasPinnedCustom} = usePinnedFeedsInfos()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
const {hasSession} = useSession()
|
||||||
|
const navigation = useNavigation<NavigationProp>()
|
||||||
const {headerMinimalShellTransform} = useMinimalShellMode()
|
const {headerMinimalShellTransform} = useMinimalShellMode()
|
||||||
const {headerHeight} = useShellLayout()
|
const {headerHeight} = useShellLayout()
|
||||||
const items = feeds.map(f => f.displayName)
|
const pinnedDisplayNames = hasSession ? feeds.map(f => f.displayName) : []
|
||||||
|
const showFeedsLinkInTabBar = hasSession && !hasPinnedCustom
|
||||||
|
const items = showFeedsLinkInTabBar
|
||||||
|
? pinnedDisplayNames.concat('Feeds ✨')
|
||||||
|
: pinnedDisplayNames
|
||||||
|
|
||||||
|
const onPressDiscoverFeeds = React.useCallback(() => {
|
||||||
|
if (isWeb) {
|
||||||
|
navigation.navigate('Feeds')
|
||||||
|
} else {
|
||||||
|
navigation.navigate('FeedsTab')
|
||||||
|
navigation.popToTop()
|
||||||
|
}
|
||||||
|
}, [navigation])
|
||||||
|
|
||||||
|
const onSelect = React.useCallback(
|
||||||
|
(index: number) => {
|
||||||
|
if (showFeedsLinkInTabBar && index === items.length - 1) {
|
||||||
|
onPressDiscoverFeeds()
|
||||||
|
} else if (props.onSelect) {
|
||||||
|
props.onSelect(index)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[items.length, onPressDiscoverFeeds, props, showFeedsLinkInTabBar],
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// @ts-ignore the type signature for transform wrong here, translateX and translateY need to be in separate objects -prf
|
// @ts-ignore the type signature for transform wrong here, translateX and translateY need to be in separate objects -prf
|
||||||
|
@ -95,6 +124,7 @@ function FeedsTabBarTablet(
|
||||||
<TabBar
|
<TabBar
|
||||||
key={items.join(',')}
|
key={items.join(',')}
|
||||||
{...props}
|
{...props}
|
||||||
|
onSelect={onSelect}
|
||||||
items={items}
|
items={items}
|
||||||
indicatorColor={pal.colors.link}
|
indicatorColor={pal.colors.link}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -18,6 +18,9 @@ import {useSetDrawerOpen} from '#/state/shell/drawer-open'
|
||||||
import {useShellLayout} from '#/state/shell/shell-layout'
|
import {useShellLayout} from '#/state/shell/shell-layout'
|
||||||
import {useSession} from '#/state/session'
|
import {useSession} from '#/state/session'
|
||||||
import {usePinnedFeedsInfos} from '#/state/queries/feed'
|
import {usePinnedFeedsInfos} from '#/state/queries/feed'
|
||||||
|
import {isWeb} from 'platform/detection'
|
||||||
|
import {useNavigation} from '@react-navigation/native'
|
||||||
|
import {NavigationProp} from 'lib/routes/types'
|
||||||
|
|
||||||
export function FeedsTabBar(
|
export function FeedsTabBar(
|
||||||
props: RenderTabBarFnProps & {testID?: string; onPressSelected: () => void},
|
props: RenderTabBarFnProps & {testID?: string; onPressSelected: () => void},
|
||||||
|
@ -26,11 +29,36 @@ export function FeedsTabBar(
|
||||||
const {isSandbox, hasSession} = useSession()
|
const {isSandbox, hasSession} = useSession()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const setDrawerOpen = useSetDrawerOpen()
|
const setDrawerOpen = useSetDrawerOpen()
|
||||||
const feeds = usePinnedFeedsInfos()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
|
const {feeds, hasPinnedCustom} = usePinnedFeedsInfos()
|
||||||
const brandBlue = useColorSchemeStyle(s.brandBlue, s.blue3)
|
const brandBlue = useColorSchemeStyle(s.brandBlue, s.blue3)
|
||||||
const {headerHeight} = useShellLayout()
|
const {headerHeight} = useShellLayout()
|
||||||
const {headerMinimalShellTransform} = useMinimalShellMode()
|
const {headerMinimalShellTransform} = useMinimalShellMode()
|
||||||
const items = feeds.map(f => f.displayName)
|
const pinnedDisplayNames = hasSession ? feeds.map(f => f.displayName) : []
|
||||||
|
const showFeedsLinkInTabBar = hasSession && !hasPinnedCustom
|
||||||
|
const items = showFeedsLinkInTabBar
|
||||||
|
? pinnedDisplayNames.concat('Feeds ✨')
|
||||||
|
: pinnedDisplayNames
|
||||||
|
|
||||||
|
const onPressFeedsLink = React.useCallback(() => {
|
||||||
|
if (isWeb) {
|
||||||
|
navigation.navigate('Feeds')
|
||||||
|
} else {
|
||||||
|
navigation.navigate('FeedsTab')
|
||||||
|
navigation.popToTop()
|
||||||
|
}
|
||||||
|
}, [navigation])
|
||||||
|
|
||||||
|
const onSelect = React.useCallback(
|
||||||
|
(index: number) => {
|
||||||
|
if (showFeedsLinkInTabBar && index === items.length - 1) {
|
||||||
|
onPressFeedsLink()
|
||||||
|
} else if (props.onSelect) {
|
||||||
|
props.onSelect(index)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[items.length, onPressFeedsLink, props, showFeedsLinkInTabBar],
|
||||||
|
)
|
||||||
|
|
||||||
const onPressAvi = React.useCallback(() => {
|
const onPressAvi = React.useCallback(() => {
|
||||||
setDrawerOpen(true)
|
setDrawerOpen(true)
|
||||||
|
@ -84,7 +112,7 @@ export function FeedsTabBar(
|
||||||
key={items.join(',')}
|
key={items.join(',')}
|
||||||
onPressSelected={props.onPressSelected}
|
onPressSelected={props.onPressSelected}
|
||||||
selectedPage={props.selectedPage}
|
selectedPage={props.selectedPage}
|
||||||
onSelect={props.onSelect}
|
onSelect={onSelect}
|
||||||
testID={props.testID}
|
testID={props.testID}
|
||||||
items={items}
|
items={items}
|
||||||
indicatorColor={pal.colors.link}
|
indicatorColor={pal.colors.link}
|
||||||
|
|
|
@ -108,6 +108,7 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>(
|
||||||
pointerEvents: isHeaderReady ? 'auto' : 'none',
|
pointerEvents: isHeaderReady ? 'auto' : 'none',
|
||||||
}}>
|
}}>
|
||||||
<TabBar
|
<TabBar
|
||||||
|
testID={testID}
|
||||||
items={items}
|
items={items}
|
||||||
selectedPage={currentPage}
|
selectedPage={currentPage}
|
||||||
onSelect={props.onSelect}
|
onSelect={props.onSelect}
|
||||||
|
@ -127,6 +128,7 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>(
|
||||||
isMobile,
|
isMobile,
|
||||||
onTabBarLayout,
|
onTabBarLayout,
|
||||||
onHeaderOnlyLayout,
|
onHeaderOnlyLayout,
|
||||||
|
testID,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,7 @@ export function TabBar({
|
||||||
return (
|
return (
|
||||||
<View testID={testID} style={[pal.view, styles.outer]}>
|
<View testID={testID} style={[pal.view, styles.outer]}>
|
||||||
<DraggableScrollView
|
<DraggableScrollView
|
||||||
|
testID={`${testID}-selector`}
|
||||||
horizontal={true}
|
horizontal={true}
|
||||||
showsHorizontalScrollIndicator={false}
|
showsHorizontalScrollIndicator={false}
|
||||||
ref={scrollElRef}
|
ref={scrollElRef}
|
||||||
|
@ -76,6 +77,7 @@ export function TabBar({
|
||||||
const selected = i === selectedPage
|
const selected = i === selectedPage
|
||||||
return (
|
return (
|
||||||
<PressableWithHover
|
<PressableWithHover
|
||||||
|
testID={`${testID}-selector-${i}`}
|
||||||
key={item}
|
key={item}
|
||||||
onLayout={e => onItemLayout(e, i)}
|
onLayout={e => onItemLayout(e, i)}
|
||||||
style={[styles.item, selected && indicatorStyle]}
|
style={[styles.item, selected && indicatorStyle]}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import {
|
||||||
FeedDescriptor,
|
FeedDescriptor,
|
||||||
FeedParams,
|
FeedParams,
|
||||||
usePostFeedQuery,
|
usePostFeedQuery,
|
||||||
|
pollLatest,
|
||||||
} from '#/state/queries/post-feed'
|
} from '#/state/queries/post-feed'
|
||||||
import {useModerationOpts} from '#/state/queries/preferences'
|
import {useModerationOpts} from '#/state/queries/preferences'
|
||||||
|
|
||||||
|
@ -84,22 +85,21 @@ let Feed = ({
|
||||||
hasNextPage,
|
hasNextPage,
|
||||||
isFetchingNextPage,
|
isFetchingNextPage,
|
||||||
fetchNextPage,
|
fetchNextPage,
|
||||||
pollLatest,
|
|
||||||
} = usePostFeedQuery(feed, feedParams, opts)
|
} = usePostFeedQuery(feed, feedParams, opts)
|
||||||
const isEmpty = !isFetching && !data?.pages[0]?.slices.length
|
const isEmpty = !isFetching && !data?.pages[0]?.slices.length
|
||||||
|
|
||||||
const checkForNew = React.useCallback(async () => {
|
const checkForNew = React.useCallback(async () => {
|
||||||
if (!isFetched || isFetching || !onHasNew) {
|
if (!data?.pages[0] || isFetching || !onHasNew) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (await pollLatest()) {
|
if (await pollLatest(data.pages[0])) {
|
||||||
onHasNew(true)
|
onHasNew(true)
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error('Poll latest failed', {feed, error: String(e)})
|
logger.error('Poll latest failed', {feed, error: String(e)})
|
||||||
}
|
}
|
||||||
}, [feed, isFetched, isFetching, pollLatest, onHasNew])
|
}, [feed, data, isFetching, onHasNew])
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
// we store the interval handler in a ref to avoid needless
|
// we store the interval handler in a ref to avoid needless
|
||||||
|
|
|
@ -17,28 +17,15 @@ import {EmptyState} from '../util/EmptyState'
|
||||||
import {cleanError} from '#/lib/strings/errors'
|
import {cleanError} from '#/lib/strings/errors'
|
||||||
import {useRemoveFeedMutation} from '#/state/queries/preferences'
|
import {useRemoveFeedMutation} from '#/state/queries/preferences'
|
||||||
|
|
||||||
enum KnownError {
|
export enum KnownError {
|
||||||
Block,
|
Block = 'Block',
|
||||||
FeedgenDoesNotExist,
|
FeedgenDoesNotExist = 'FeedgenDoesNotExist',
|
||||||
FeedgenMisconfigured,
|
FeedgenMisconfigured = 'FeedgenMisconfigured',
|
||||||
FeedgenBadResponse,
|
FeedgenBadResponse = 'FeedgenBadResponse',
|
||||||
FeedgenOffline,
|
FeedgenOffline = 'FeedgenOffline',
|
||||||
FeedgenUnknown,
|
FeedgenUnknown = 'FeedgenUnknown',
|
||||||
Unknown,
|
FeedNSFPublic = 'FeedNSFPublic',
|
||||||
}
|
Unknown = 'Unknown',
|
||||||
|
|
||||||
const MESSAGES = {
|
|
||||||
[KnownError.Unknown]: '',
|
|
||||||
[KnownError.Block]: '',
|
|
||||||
[KnownError.FeedgenDoesNotExist]: `Hmmm, we're having trouble finding this feed. It may have been deleted.`,
|
|
||||||
[KnownError.FeedgenMisconfigured]:
|
|
||||||
'Hmm, the feed server appears to be misconfigured. Please let the feed owner know about this issue.',
|
|
||||||
[KnownError.FeedgenBadResponse]:
|
|
||||||
'Hmm, the feed server gave a bad response. Please let the feed owner know about this issue.',
|
|
||||||
[KnownError.FeedgenOffline]:
|
|
||||||
'Hmm, the feed server appears to be offline. Please let the feed owner know about this issue.',
|
|
||||||
[KnownError.FeedgenUnknown]:
|
|
||||||
'Hmm, some kind of issue occured when contacting the feed server. Please let the feed owner know about this issue.',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function FeedErrorMessage({
|
export function FeedErrorMessage({
|
||||||
|
@ -90,7 +77,32 @@ function FeedgenErrorMessage({
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const {_: _l} = useLingui()
|
const {_: _l} = useLingui()
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
const msg = MESSAGES[knownError]
|
const msg = React.useMemo(
|
||||||
|
() =>
|
||||||
|
({
|
||||||
|
[KnownError.Unknown]: '',
|
||||||
|
[KnownError.Block]: '',
|
||||||
|
[KnownError.FeedgenDoesNotExist]: _l(
|
||||||
|
msgLingui`Hmmm, we're having trouble finding this feed. It may have been deleted.`,
|
||||||
|
),
|
||||||
|
[KnownError.FeedgenMisconfigured]: _l(
|
||||||
|
msgLingui`Hmm, the feed server appears to be misconfigured. Please let the feed owner know about this issue.`,
|
||||||
|
),
|
||||||
|
[KnownError.FeedgenBadResponse]: _l(
|
||||||
|
msgLingui`Hmm, the feed server gave a bad response. Please let the feed owner know about this issue.`,
|
||||||
|
),
|
||||||
|
[KnownError.FeedgenOffline]: _l(
|
||||||
|
msgLingui`Hmm, the feed server appears to be offline. Please let the feed owner know about this issue.`,
|
||||||
|
),
|
||||||
|
[KnownError.FeedNSFPublic]: _l(
|
||||||
|
msgLingui`We're sorry, but this content is not viewable without a Bluesky account.`,
|
||||||
|
),
|
||||||
|
[KnownError.FeedgenUnknown]: _l(
|
||||||
|
msgLingui`Hmm, some kind of issue occured when contacting the feed server. Please let the feed owner know about this issue.`,
|
||||||
|
),
|
||||||
|
}[knownError]),
|
||||||
|
[_l, knownError],
|
||||||
|
)
|
||||||
const [_, uri] = feedDesc.split('|')
|
const [_, uri] = feedDesc.split('|')
|
||||||
const [ownerDid] = safeParseFeedgenUri(uri)
|
const [ownerDid] = safeParseFeedgenUri(uri)
|
||||||
const {openModal, closeModal} = useModalControls()
|
const {openModal, closeModal} = useModalControls()
|
||||||
|
@ -121,6 +133,36 @@ function FeedgenErrorMessage({
|
||||||
})
|
})
|
||||||
}, [openModal, closeModal, uri, removeFeed, _l])
|
}, [openModal, closeModal, uri, removeFeed, _l])
|
||||||
|
|
||||||
|
const cta = React.useMemo(() => {
|
||||||
|
switch (knownError) {
|
||||||
|
case KnownError.FeedNSFPublic: {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
case KnownError.FeedgenDoesNotExist:
|
||||||
|
case KnownError.FeedgenMisconfigured:
|
||||||
|
case KnownError.FeedgenBadResponse:
|
||||||
|
case KnownError.FeedgenOffline:
|
||||||
|
case KnownError.FeedgenUnknown: {
|
||||||
|
return (
|
||||||
|
<View style={{flexDirection: 'row', alignItems: 'center', gap: 10}}>
|
||||||
|
{knownError === KnownError.FeedgenDoesNotExist && (
|
||||||
|
<Button
|
||||||
|
type="inverted"
|
||||||
|
label="Remove feed"
|
||||||
|
onPress={onRemoveFeed}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<Button
|
||||||
|
type="default-light"
|
||||||
|
label="View profile"
|
||||||
|
onPress={onViewProfile}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [knownError, onViewProfile, onRemoveFeed])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
|
@ -134,16 +176,7 @@ function FeedgenErrorMessage({
|
||||||
},
|
},
|
||||||
]}>
|
]}>
|
||||||
<Text style={pal.text}>{msg}</Text>
|
<Text style={pal.text}>{msg}</Text>
|
||||||
<View style={{flexDirection: 'row', alignItems: 'center', gap: 10}}>
|
{cta}
|
||||||
{knownError === KnownError.FeedgenDoesNotExist && (
|
|
||||||
<Button type="inverted" label="Remove feed" onPress={onRemoveFeed} />
|
|
||||||
)}
|
|
||||||
<Button
|
|
||||||
type="default-light"
|
|
||||||
label="View profile"
|
|
||||||
onPress={onViewProfile}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -196,5 +229,8 @@ function detectKnownError(
|
||||||
if (error.includes('feed provided an invalid response')) {
|
if (error.includes('feed provided an invalid response')) {
|
||||||
return KnownError.FeedgenBadResponse
|
return KnownError.FeedgenBadResponse
|
||||||
}
|
}
|
||||||
|
if (error.includes(KnownError.FeedNSFPublic)) {
|
||||||
|
return KnownError.FeedNSFPublic
|
||||||
|
}
|
||||||
return KnownError.FeedgenUnknown
|
return KnownError.FeedgenUnknown
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ interface Props extends ComponentProps<typeof TouchableOpacity> {
|
||||||
noFeedback?: boolean
|
noFeedback?: boolean
|
||||||
asAnchor?: boolean
|
asAnchor?: boolean
|
||||||
anchorNoUnderline?: boolean
|
anchorNoUnderline?: boolean
|
||||||
|
navigationAction?: 'push' | 'replace' | 'navigate'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Link = memo(function Link({
|
export const Link = memo(function Link({
|
||||||
|
@ -58,6 +59,7 @@ export const Link = memo(function Link({
|
||||||
asAnchor,
|
asAnchor,
|
||||||
accessible,
|
accessible,
|
||||||
anchorNoUnderline,
|
anchorNoUnderline,
|
||||||
|
navigationAction,
|
||||||
...props
|
...props
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const {closeModal} = useModalControls()
|
const {closeModal} = useModalControls()
|
||||||
|
@ -67,10 +69,16 @@ export const Link = memo(function Link({
|
||||||
const onPress = React.useCallback(
|
const onPress = React.useCallback(
|
||||||
(e?: Event) => {
|
(e?: Event) => {
|
||||||
if (typeof href === 'string') {
|
if (typeof href === 'string') {
|
||||||
return onPressInner(closeModal, navigation, sanitizeUrl(href), e)
|
return onPressInner(
|
||||||
|
closeModal,
|
||||||
|
navigation,
|
||||||
|
sanitizeUrl(href),
|
||||||
|
navigationAction,
|
||||||
|
e,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[closeModal, navigation, href],
|
[closeModal, navigation, navigationAction, href],
|
||||||
)
|
)
|
||||||
|
|
||||||
if (noFeedback) {
|
if (noFeedback) {
|
||||||
|
@ -146,6 +154,7 @@ export const TextLink = memo(function TextLink({
|
||||||
title,
|
title,
|
||||||
onPress,
|
onPress,
|
||||||
warnOnMismatchingLabel,
|
warnOnMismatchingLabel,
|
||||||
|
navigationAction,
|
||||||
...orgProps
|
...orgProps
|
||||||
}: {
|
}: {
|
||||||
testID?: string
|
testID?: string
|
||||||
|
@ -158,6 +167,7 @@ export const TextLink = memo(function TextLink({
|
||||||
dataSet?: any
|
dataSet?: any
|
||||||
title?: string
|
title?: string
|
||||||
warnOnMismatchingLabel?: boolean
|
warnOnMismatchingLabel?: boolean
|
||||||
|
navigationAction?: 'push' | 'replace' | 'navigate'
|
||||||
} & TextProps) {
|
} & TextProps) {
|
||||||
const {...props} = useLinkProps({to: sanitizeUrl(href)})
|
const {...props} = useLinkProps({to: sanitizeUrl(href)})
|
||||||
const navigation = useNavigation<NavigationProp>()
|
const navigation = useNavigation<NavigationProp>()
|
||||||
|
@ -185,7 +195,13 @@ export const TextLink = memo(function TextLink({
|
||||||
// @ts-ignore function signature differs by platform -prf
|
// @ts-ignore function signature differs by platform -prf
|
||||||
return onPress()
|
return onPress()
|
||||||
}
|
}
|
||||||
return onPressInner(closeModal, navigation, sanitizeUrl(href), e)
|
return onPressInner(
|
||||||
|
closeModal,
|
||||||
|
navigation,
|
||||||
|
sanitizeUrl(href),
|
||||||
|
navigationAction,
|
||||||
|
e,
|
||||||
|
)
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
onPress,
|
onPress,
|
||||||
|
@ -195,6 +211,7 @@ export const TextLink = memo(function TextLink({
|
||||||
href,
|
href,
|
||||||
text,
|
text,
|
||||||
warnOnMismatchingLabel,
|
warnOnMismatchingLabel,
|
||||||
|
navigationAction,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
const hrefAttrs = useMemo(() => {
|
const hrefAttrs = useMemo(() => {
|
||||||
|
@ -241,6 +258,7 @@ interface TextLinkOnWebOnlyProps extends TextProps {
|
||||||
accessibilityLabel?: string
|
accessibilityLabel?: string
|
||||||
accessibilityHint?: string
|
accessibilityHint?: string
|
||||||
title?: string
|
title?: string
|
||||||
|
navigationAction?: 'push' | 'replace' | 'navigate'
|
||||||
}
|
}
|
||||||
export const TextLinkOnWebOnly = memo(function DesktopWebTextLink({
|
export const TextLinkOnWebOnly = memo(function DesktopWebTextLink({
|
||||||
testID,
|
testID,
|
||||||
|
@ -250,6 +268,7 @@ export const TextLinkOnWebOnly = memo(function DesktopWebTextLink({
|
||||||
text,
|
text,
|
||||||
numberOfLines,
|
numberOfLines,
|
||||||
lineHeight,
|
lineHeight,
|
||||||
|
navigationAction,
|
||||||
...props
|
...props
|
||||||
}: TextLinkOnWebOnlyProps) {
|
}: TextLinkOnWebOnlyProps) {
|
||||||
if (isWeb) {
|
if (isWeb) {
|
||||||
|
@ -263,6 +282,7 @@ export const TextLinkOnWebOnly = memo(function DesktopWebTextLink({
|
||||||
numberOfLines={numberOfLines}
|
numberOfLines={numberOfLines}
|
||||||
lineHeight={lineHeight}
|
lineHeight={lineHeight}
|
||||||
title={props.title}
|
title={props.title}
|
||||||
|
navigationAction={navigationAction}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
@ -296,6 +316,7 @@ function onPressInner(
|
||||||
closeModal = () => {},
|
closeModal = () => {},
|
||||||
navigation: NavigationProp,
|
navigation: NavigationProp,
|
||||||
href: string,
|
href: string,
|
||||||
|
navigationAction: 'push' | 'replace' | 'navigate' = 'push',
|
||||||
e?: Event,
|
e?: Event,
|
||||||
) {
|
) {
|
||||||
let shouldHandle = false
|
let shouldHandle = false
|
||||||
|
@ -328,8 +349,18 @@ function onPressInner(
|
||||||
} else {
|
} else {
|
||||||
closeModal() // close any active modals
|
closeModal() // close any active modals
|
||||||
|
|
||||||
|
if (navigationAction === 'push') {
|
||||||
// @ts-ignore we're not able to type check on this one -prf
|
// @ts-ignore we're not able to type check on this one -prf
|
||||||
navigation.dispatch(StackActions.push(...router.matchPath(href)))
|
navigation.dispatch(StackActions.push(...router.matchPath(href)))
|
||||||
|
} else if (navigationAction === 'replace') {
|
||||||
|
// @ts-ignore we're not able to type check on this one -prf
|
||||||
|
navigation.dispatch(StackActions.replace(...router.matchPath(href)))
|
||||||
|
} else if (navigationAction === 'navigate') {
|
||||||
|
// @ts-ignore we're not able to type check on this one -prf
|
||||||
|
navigation.navigate(...router.matchPath(href))
|
||||||
|
} else {
|
||||||
|
throw Error('Unsupported navigator action.')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,14 +171,22 @@ export function ProfileCardFeedLoadingPlaceholder() {
|
||||||
|
|
||||||
export function FeedLoadingPlaceholder({
|
export function FeedLoadingPlaceholder({
|
||||||
style,
|
style,
|
||||||
|
showLowerPlaceholder = true,
|
||||||
|
showTopBorder = true,
|
||||||
}: {
|
}: {
|
||||||
style?: StyleProp<ViewStyle>
|
style?: StyleProp<ViewStyle>
|
||||||
|
showTopBorder?: boolean
|
||||||
|
showLowerPlaceholder?: boolean
|
||||||
}) {
|
}) {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
{paddingHorizontal: 12, paddingVertical: 18, borderTopWidth: 1},
|
{
|
||||||
|
paddingHorizontal: 12,
|
||||||
|
paddingVertical: 18,
|
||||||
|
borderTopWidth: showTopBorder ? 1 : 0,
|
||||||
|
},
|
||||||
pal.border,
|
pal.border,
|
||||||
style,
|
style,
|
||||||
]}>
|
]}>
|
||||||
|
@ -193,6 +201,7 @@ export function FeedLoadingPlaceholder({
|
||||||
<LoadingPlaceholder width={120} height={8} />
|
<LoadingPlaceholder width={120} height={8} />
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
{showLowerPlaceholder && (
|
||||||
<View style={{paddingHorizontal: 5}}>
|
<View style={{paddingHorizontal: 5}}>
|
||||||
<LoadingPlaceholder
|
<LoadingPlaceholder
|
||||||
width={260}
|
width={260}
|
||||||
|
@ -201,6 +210,7 @@ export function FeedLoadingPlaceholder({
|
||||||
/>
|
/>
|
||||||
<LoadingPlaceholder width={120} height={8} />
|
<LoadingPlaceholder width={120} height={8} />
|
||||||
</View>
|
</View>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -437,6 +437,7 @@ export function FeedsScreen(_props: Props) {
|
||||||
showSaveBtn={hasSession}
|
showSaveBtn={hasSession}
|
||||||
showDescription
|
showDescription
|
||||||
showLikes
|
showLikes
|
||||||
|
pinOnSave
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
} else if (item.type === 'popularFeedsNoResults') {
|
} else if (item.type === 'popularFeedsNoResults') {
|
||||||
|
|
|
@ -40,6 +40,12 @@ function HomeScreenReady({
|
||||||
const setDrawerSwipeDisabled = useSetDrawerSwipeDisabled()
|
const setDrawerSwipeDisabled = useSetDrawerSwipeDisabled()
|
||||||
const [selectedPage, setSelectedPage] = React.useState(0)
|
const [selectedPage, setSelectedPage] = React.useState(0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to ensure that we re-compute `customFeeds` AND force a re-render of
|
||||||
|
* the pager with the new order of feeds.
|
||||||
|
*/
|
||||||
|
const pinnedFeedOrderKey = JSON.stringify(preferences.feeds.pinned)
|
||||||
|
|
||||||
const customFeeds = React.useMemo(() => {
|
const customFeeds = React.useMemo(() => {
|
||||||
const pinned = preferences.feeds.pinned
|
const pinned = preferences.feeds.pinned
|
||||||
const feeds: FeedDescriptor[] = []
|
const feeds: FeedDescriptor[] = []
|
||||||
|
@ -83,7 +89,6 @@ function HomeScreenReady({
|
||||||
emitSoftReset()
|
emitSoftReset()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
// TODO(pwi) may need this in public view
|
|
||||||
const onPageScrollStateChanged = React.useCallback(
|
const onPageScrollStateChanged = React.useCallback(
|
||||||
(state: 'idle' | 'dragging' | 'settling') => {
|
(state: 'idle' | 'dragging' | 'settling') => {
|
||||||
if (state === 'dragging') {
|
if (state === 'dragging') {
|
||||||
|
@ -118,6 +123,7 @@ function HomeScreenReady({
|
||||||
|
|
||||||
return hasSession ? (
|
return hasSession ? (
|
||||||
<Pager
|
<Pager
|
||||||
|
key={pinnedFeedOrderKey}
|
||||||
testID="homeScreen"
|
testID="homeScreen"
|
||||||
onPageSelected={onPageSelected}
|
onPageSelected={onPageSelected}
|
||||||
onPageScrollStateChanged={onPageScrollStateChanged}
|
onPageScrollStateChanged={onPageScrollStateChanged}
|
||||||
|
|
|
@ -19,7 +19,10 @@ import {logger} from '#/logger'
|
||||||
import {useSetMinimalShellMode} from '#/state/shell'
|
import {useSetMinimalShellMode} from '#/state/shell'
|
||||||
import {Trans, msg} from '@lingui/macro'
|
import {Trans, msg} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {useUnreadNotifications} from '#/state/queries/notifications/unread'
|
import {
|
||||||
|
useUnreadNotifications,
|
||||||
|
useUnreadNotificationsApi,
|
||||||
|
} from '#/state/queries/notifications/unread'
|
||||||
import {RQKEY as NOTIFS_RQKEY} from '#/state/queries/notifications/feed'
|
import {RQKEY as NOTIFS_RQKEY} from '#/state/queries/notifications/feed'
|
||||||
import {listenSoftReset, emitSoftReset} from '#/state/events'
|
import {listenSoftReset, emitSoftReset} from '#/state/events'
|
||||||
|
|
||||||
|
@ -35,8 +38,9 @@ export function NotificationsScreen({}: Props) {
|
||||||
const {screen} = useAnalytics()
|
const {screen} = useAnalytics()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const {isDesktop} = useWebMediaQueries()
|
const {isDesktop} = useWebMediaQueries()
|
||||||
const unreadNotifs = useUnreadNotifications()
|
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
|
const unreadNotifs = useUnreadNotifications()
|
||||||
|
const unreadApi = useUnreadNotificationsApi()
|
||||||
const hasNew = !!unreadNotifs
|
const hasNew = !!unreadNotifs
|
||||||
|
|
||||||
// event handlers
|
// event handlers
|
||||||
|
@ -48,10 +52,16 @@ export function NotificationsScreen({}: Props) {
|
||||||
|
|
||||||
const onPressLoadLatest = React.useCallback(() => {
|
const onPressLoadLatest = React.useCallback(() => {
|
||||||
scrollToTop()
|
scrollToTop()
|
||||||
queryClient.invalidateQueries({
|
if (hasNew) {
|
||||||
|
// render what we have now
|
||||||
|
queryClient.resetQueries({
|
||||||
queryKey: NOTIFS_RQKEY(),
|
queryKey: NOTIFS_RQKEY(),
|
||||||
})
|
})
|
||||||
}, [scrollToTop, queryClient])
|
} else {
|
||||||
|
// check with the server
|
||||||
|
unreadApi.checkUnread({invalidate: true})
|
||||||
|
}
|
||||||
|
}, [scrollToTop, queryClient, unreadApi, hasNew])
|
||||||
|
|
||||||
// on-visible setup
|
// on-visible setup
|
||||||
// =
|
// =
|
||||||
|
|
|
@ -267,6 +267,7 @@ function ProfileScreenLoaded({
|
||||||
screenDescription="profile"
|
screenDescription="profile"
|
||||||
moderation={moderation.account}>
|
moderation={moderation.account}>
|
||||||
<PagerWithHeader
|
<PagerWithHeader
|
||||||
|
testID="profilePager"
|
||||||
isHeaderReady={true}
|
isHeaderReady={true}
|
||||||
items={sectionTitles}
|
items={sectionTitles}
|
||||||
onPageSelected={onPageSelected}
|
onPageSelected={onPageSelected}
|
||||||
|
@ -403,7 +404,7 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
|
||||||
|
|
||||||
const onScrollToTop = React.useCallback(() => {
|
const onScrollToTop = React.useCallback(() => {
|
||||||
scrollElRef.current?.scrollToOffset({offset: -headerHeight})
|
scrollElRef.current?.scrollToOffset({offset: -headerHeight})
|
||||||
queryClient.invalidateQueries({queryKey: FEED_RQKEY(feed)})
|
queryClient.resetQueries({queryKey: FEED_RQKEY(feed)})
|
||||||
setHasNew(false)
|
setHasNew(false)
|
||||||
}, [scrollElRef, headerHeight, queryClient, feed, setHasNew])
|
}, [scrollElRef, headerHeight, queryClient, feed, setHasNew])
|
||||||
React.useImperativeHandle(ref, () => ({
|
React.useImperativeHandle(ref, () => ({
|
||||||
|
|
|
@ -353,6 +353,7 @@ export function ProfileFeedScreenInner({
|
||||||
style={styles.btn}
|
style={styles.btn}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
|
testID={isPinned ? 'unpinBtn' : 'pinBtn'}
|
||||||
disabled={isPinPending || isUnpinPending}
|
disabled={isPinPending || isUnpinPending}
|
||||||
type={isPinned ? 'default' : 'inverted'}
|
type={isPinned ? 'default' : 'inverted'}
|
||||||
label={isPinned ? 'Unpin' : 'Pin to home'}
|
label={isPinned ? 'Unpin' : 'Pin to home'}
|
||||||
|
@ -501,7 +502,7 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
|
||||||
|
|
||||||
const onScrollToTop = useCallback(() => {
|
const onScrollToTop = useCallback(() => {
|
||||||
scrollElRef.current?.scrollToOffset({offset: -headerHeight})
|
scrollElRef.current?.scrollToOffset({offset: -headerHeight})
|
||||||
queryClient.invalidateQueries({queryKey: FEED_RQKEY(feed)})
|
queryClient.resetQueries({queryKey: FEED_RQKEY(feed)})
|
||||||
setHasNew(false)
|
setHasNew(false)
|
||||||
}, [scrollElRef, headerHeight, queryClient, feed, setHasNew])
|
}, [scrollElRef, headerHeight, queryClient, feed, setHasNew])
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,7 @@ function ProfileListScreenLoaded({
|
||||||
list,
|
list,
|
||||||
onChange() {
|
onChange() {
|
||||||
if (isCurateList) {
|
if (isCurateList) {
|
||||||
queryClient.invalidateQueries({
|
queryClient.resetQueries({
|
||||||
// TODO(eric) should construct these strings with a fn too
|
// TODO(eric) should construct these strings with a fn too
|
||||||
queryKey: FEED_RQKEY(`list|${list.uri}`),
|
queryKey: FEED_RQKEY(`list|${list.uri}`),
|
||||||
})
|
})
|
||||||
|
@ -530,7 +530,7 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
|
||||||
|
|
||||||
const onScrollToTop = useCallback(() => {
|
const onScrollToTop = useCallback(() => {
|
||||||
scrollElRef.current?.scrollToOffset({offset: -headerHeight})
|
scrollElRef.current?.scrollToOffset({offset: -headerHeight})
|
||||||
queryClient.invalidateQueries({queryKey: FEED_RQKEY(feed)})
|
queryClient.resetQueries({queryKey: FEED_RQKEY(feed)})
|
||||||
setHasNew(false)
|
setHasNew(false)
|
||||||
}, [scrollElRef, headerHeight, queryClient, feed, setHasNew])
|
}, [scrollElRef, headerHeight, queryClient, feed, setHasNew])
|
||||||
React.useImperativeHandle(ref, () => ({
|
React.useImperativeHandle(ref, () => ({
|
||||||
|
|
|
@ -1,14 +1,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {
|
import {StyleSheet, View, ActivityIndicator, Pressable} from 'react-native'
|
||||||
StyleSheet,
|
|
||||||
View,
|
|
||||||
ActivityIndicator,
|
|
||||||
Pressable,
|
|
||||||
TouchableOpacity,
|
|
||||||
} from 'react-native'
|
|
||||||
import {useFocusEffect} from '@react-navigation/native'
|
import {useFocusEffect} from '@react-navigation/native'
|
||||||
import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
||||||
import {useQueryClient} from '@tanstack/react-query'
|
|
||||||
import {track} from '#/lib/analytics/analytics'
|
import {track} from '#/lib/analytics/analytics'
|
||||||
import {useAnalytics} from 'lib/analytics/analytics'
|
import {useAnalytics} from 'lib/analytics/analytics'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
@ -32,9 +25,8 @@ import {
|
||||||
usePinFeedMutation,
|
usePinFeedMutation,
|
||||||
useUnpinFeedMutation,
|
useUnpinFeedMutation,
|
||||||
useSetSaveFeedsMutation,
|
useSetSaveFeedsMutation,
|
||||||
preferencesQueryKey,
|
|
||||||
UsePreferencesQueryResponse,
|
|
||||||
} from '#/state/queries/preferences'
|
} from '#/state/queries/preferences'
|
||||||
|
import {FeedLoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder'
|
||||||
|
|
||||||
const HITSLOP_TOP = {
|
const HITSLOP_TOP = {
|
||||||
top: 20,
|
top: 20,
|
||||||
|
@ -57,6 +49,24 @@ export function SavedFeeds({}: Props) {
|
||||||
const {screen} = useAnalytics()
|
const {screen} = useAnalytics()
|
||||||
const setMinimalShellMode = useSetMinimalShellMode()
|
const setMinimalShellMode = useSetMinimalShellMode()
|
||||||
const {data: preferences} = usePreferencesQuery()
|
const {data: preferences} = usePreferencesQuery()
|
||||||
|
const {
|
||||||
|
mutateAsync: setSavedFeeds,
|
||||||
|
variables: optimisticSavedFeedsResponse,
|
||||||
|
reset: resetSaveFeedsMutationState,
|
||||||
|
error: setSavedFeedsError,
|
||||||
|
} = useSetSaveFeedsMutation()
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use optimistic data if exists and no error, otherwise fallback to remote
|
||||||
|
* data
|
||||||
|
*/
|
||||||
|
const currentFeeds =
|
||||||
|
optimisticSavedFeedsResponse && !setSavedFeedsError
|
||||||
|
? optimisticSavedFeedsResponse
|
||||||
|
: preferences?.feeds || {saved: [], pinned: []}
|
||||||
|
const unpinned = currentFeeds.saved.filter(f => {
|
||||||
|
return !currentFeeds.pinned?.includes(f)
|
||||||
|
})
|
||||||
|
|
||||||
useFocusEffect(
|
useFocusEffect(
|
||||||
React.useCallback(() => {
|
React.useCallback(() => {
|
||||||
|
@ -80,7 +90,7 @@ export function SavedFeeds({}: Props) {
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
{preferences?.feeds ? (
|
{preferences?.feeds ? (
|
||||||
!preferences.feeds.pinned.length ? (
|
!currentFeeds.pinned.length ? (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
pal.border,
|
pal.border,
|
||||||
|
@ -93,8 +103,15 @@ export function SavedFeeds({}: Props) {
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
) : (
|
) : (
|
||||||
preferences?.feeds?.pinned?.map(uri => (
|
currentFeeds.pinned.map(uri => (
|
||||||
<ListItem key={uri} feedUri={uri} isPinned />
|
<ListItem
|
||||||
|
key={uri}
|
||||||
|
feedUri={uri}
|
||||||
|
isPinned
|
||||||
|
setSavedFeeds={setSavedFeeds}
|
||||||
|
resetSaveFeedsMutationState={resetSaveFeedsMutationState}
|
||||||
|
currentFeeds={currentFeeds}
|
||||||
|
/>
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
) : (
|
) : (
|
||||||
|
@ -106,7 +123,7 @@ export function SavedFeeds({}: Props) {
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
{preferences?.feeds ? (
|
{preferences?.feeds ? (
|
||||||
!preferences.feeds.unpinned.length ? (
|
!unpinned.length ? (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
pal.border,
|
pal.border,
|
||||||
|
@ -119,8 +136,15 @@ export function SavedFeeds({}: Props) {
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
) : (
|
) : (
|
||||||
preferences.feeds.unpinned.map(uri => (
|
unpinned.map(uri => (
|
||||||
<ListItem key={uri} feedUri={uri} isPinned={false} />
|
<ListItem
|
||||||
|
key={uri}
|
||||||
|
feedUri={uri}
|
||||||
|
isPinned={false}
|
||||||
|
setSavedFeeds={setSavedFeeds}
|
||||||
|
resetSaveFeedsMutationState={resetSaveFeedsMutationState}
|
||||||
|
currentFeeds={currentFeeds}
|
||||||
|
/>
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
) : (
|
) : (
|
||||||
|
@ -151,22 +175,30 @@ export function SavedFeeds({}: Props) {
|
||||||
function ListItem({
|
function ListItem({
|
||||||
feedUri,
|
feedUri,
|
||||||
isPinned,
|
isPinned,
|
||||||
|
currentFeeds,
|
||||||
|
setSavedFeeds,
|
||||||
|
resetSaveFeedsMutationState,
|
||||||
}: {
|
}: {
|
||||||
feedUri: string // uri
|
feedUri: string // uri
|
||||||
isPinned: boolean
|
isPinned: boolean
|
||||||
|
currentFeeds: {saved: string[]; pinned: string[]}
|
||||||
|
setSavedFeeds: ReturnType<typeof useSetSaveFeedsMutation>['mutateAsync']
|
||||||
|
resetSaveFeedsMutationState: ReturnType<
|
||||||
|
typeof useSetSaveFeedsMutation
|
||||||
|
>['reset']
|
||||||
}) {
|
}) {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const queryClient = useQueryClient()
|
|
||||||
const {isPending: isPinPending, mutateAsync: pinFeed} = usePinFeedMutation()
|
const {isPending: isPinPending, mutateAsync: pinFeed} = usePinFeedMutation()
|
||||||
const {isPending: isUnpinPending, mutateAsync: unpinFeed} =
|
const {isPending: isUnpinPending, mutateAsync: unpinFeed} =
|
||||||
useUnpinFeedMutation()
|
useUnpinFeedMutation()
|
||||||
const {isPending: isMovePending, mutateAsync: setSavedFeeds} =
|
const isPending = isPinPending || isUnpinPending
|
||||||
useSetSaveFeedsMutation()
|
|
||||||
|
|
||||||
const onTogglePinned = React.useCallback(async () => {
|
const onTogglePinned = React.useCallback(async () => {
|
||||||
Haptics.default()
|
Haptics.default()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
resetSaveFeedsMutationState()
|
||||||
|
|
||||||
if (isPinned) {
|
if (isPinned) {
|
||||||
await unpinFeed({uri: feedUri})
|
await unpinFeed({uri: feedUri})
|
||||||
} else {
|
} else {
|
||||||
|
@ -176,23 +208,20 @@ function ListItem({
|
||||||
Toast.show('There was an issue contacting the server')
|
Toast.show('There was an issue contacting the server')
|
||||||
logger.error('Failed to toggle pinned feed', {error: e})
|
logger.error('Failed to toggle pinned feed', {error: e})
|
||||||
}
|
}
|
||||||
}, [feedUri, isPinned, pinFeed, unpinFeed])
|
}, [feedUri, isPinned, pinFeed, unpinFeed, resetSaveFeedsMutationState])
|
||||||
|
|
||||||
const onPressUp = React.useCallback(async () => {
|
const onPressUp = React.useCallback(async () => {
|
||||||
if (!isPinned) return
|
if (!isPinned) return
|
||||||
|
|
||||||
const feeds =
|
// create new array, do not mutate
|
||||||
queryClient.getQueryData<UsePreferencesQueryResponse>(
|
const pinned = [...currentFeeds.pinned]
|
||||||
preferencesQueryKey,
|
|
||||||
)?.feeds
|
|
||||||
const pinned = feeds?.pinned ?? []
|
|
||||||
const index = pinned.indexOf(feedUri)
|
const index = pinned.indexOf(feedUri)
|
||||||
|
|
||||||
if (index === -1 || index === 0) return
|
if (index === -1 || index === 0) return
|
||||||
;[pinned[index], pinned[index - 1]] = [pinned[index - 1], pinned[index]]
|
;[pinned[index], pinned[index - 1]] = [pinned[index - 1], pinned[index]]
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await setSavedFeeds({saved: feeds?.saved ?? [], pinned})
|
await setSavedFeeds({saved: currentFeeds.saved, pinned})
|
||||||
track('CustomFeed:Reorder', {
|
track('CustomFeed:Reorder', {
|
||||||
uri: feedUri,
|
uri: feedUri,
|
||||||
index: pinned.indexOf(feedUri),
|
index: pinned.indexOf(feedUri),
|
||||||
|
@ -201,23 +230,19 @@ function ListItem({
|
||||||
Toast.show('There was an issue contacting the server')
|
Toast.show('There was an issue contacting the server')
|
||||||
logger.error('Failed to set pinned feed order', {error: e})
|
logger.error('Failed to set pinned feed order', {error: e})
|
||||||
}
|
}
|
||||||
}, [feedUri, isPinned, queryClient, setSavedFeeds])
|
}, [feedUri, isPinned, setSavedFeeds, currentFeeds])
|
||||||
|
|
||||||
const onPressDown = React.useCallback(async () => {
|
const onPressDown = React.useCallback(async () => {
|
||||||
if (!isPinned) return
|
if (!isPinned) return
|
||||||
|
|
||||||
const feeds =
|
const pinned = [...currentFeeds.pinned]
|
||||||
queryClient.getQueryData<UsePreferencesQueryResponse>(
|
|
||||||
preferencesQueryKey,
|
|
||||||
)?.feeds
|
|
||||||
const pinned = feeds?.pinned ?? []
|
|
||||||
const index = pinned.indexOf(feedUri)
|
const index = pinned.indexOf(feedUri)
|
||||||
|
|
||||||
if (index === -1 || index >= pinned.length - 1) return
|
if (index === -1 || index >= pinned.length - 1) return
|
||||||
;[pinned[index], pinned[index + 1]] = [pinned[index + 1], pinned[index]]
|
;[pinned[index], pinned[index + 1]] = [pinned[index + 1], pinned[index]]
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await setSavedFeeds({saved: feeds?.saved ?? [], pinned})
|
await setSavedFeeds({saved: currentFeeds.saved, pinned})
|
||||||
track('CustomFeed:Reorder', {
|
track('CustomFeed:Reorder', {
|
||||||
uri: feedUri,
|
uri: feedUri,
|
||||||
index: pinned.indexOf(feedUri),
|
index: pinned.indexOf(feedUri),
|
||||||
|
@ -226,7 +251,7 @@ function ListItem({
|
||||||
Toast.show('There was an issue contacting the server')
|
Toast.show('There was an issue contacting the server')
|
||||||
logger.error('Failed to set pinned feed order', {error: e})
|
logger.error('Failed to set pinned feed order', {error: e})
|
||||||
}
|
}
|
||||||
}, [feedUri, isPinned, queryClient, setSavedFeeds])
|
}, [feedUri, isPinned, setSavedFeeds, currentFeeds])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Pressable
|
<Pressable
|
||||||
|
@ -234,24 +259,30 @@ function ListItem({
|
||||||
style={[styles.itemContainer, pal.border]}>
|
style={[styles.itemContainer, pal.border]}>
|
||||||
{isPinned ? (
|
{isPinned ? (
|
||||||
<View style={styles.webArrowButtonsContainer}>
|
<View style={styles.webArrowButtonsContainer}>
|
||||||
<TouchableOpacity
|
<Pressable
|
||||||
disabled={isMovePending}
|
disabled={isPending}
|
||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
onPress={onPressUp}
|
onPress={onPressUp}
|
||||||
hitSlop={HITSLOP_TOP}>
|
hitSlop={HITSLOP_TOP}
|
||||||
|
style={state => ({
|
||||||
|
opacity: state.hovered || state.focused || isPending ? 0.5 : 1,
|
||||||
|
})}>
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
icon="arrow-up"
|
icon="arrow-up"
|
||||||
size={12}
|
size={12}
|
||||||
style={[pal.text, styles.webArrowUpButton]}
|
style={[pal.text, styles.webArrowUpButton]}
|
||||||
/>
|
/>
|
||||||
</TouchableOpacity>
|
</Pressable>
|
||||||
<TouchableOpacity
|
<Pressable
|
||||||
disabled={isMovePending}
|
disabled={isPending}
|
||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
onPress={onPressDown}
|
onPress={onPressDown}
|
||||||
hitSlop={HITSLOP_BOTTOM}>
|
hitSlop={HITSLOP_BOTTOM}
|
||||||
|
style={state => ({
|
||||||
|
opacity: state.hovered || state.focused || isPending ? 0.5 : 1,
|
||||||
|
})}>
|
||||||
<FontAwesomeIcon icon="arrow-down" size={12} style={[pal.text]} />
|
<FontAwesomeIcon icon="arrow-down" size={12} style={[pal.text]} />
|
||||||
</TouchableOpacity>
|
</Pressable>
|
||||||
</View>
|
</View>
|
||||||
) : null}
|
) : null}
|
||||||
<FeedSourceCard
|
<FeedSourceCard
|
||||||
|
@ -259,18 +290,28 @@ function ListItem({
|
||||||
feedUri={feedUri}
|
feedUri={feedUri}
|
||||||
style={styles.noBorder}
|
style={styles.noBorder}
|
||||||
showSaveBtn
|
showSaveBtn
|
||||||
|
LoadingComponent={
|
||||||
|
<FeedLoadingPlaceholder
|
||||||
|
style={{flex: 1}}
|
||||||
|
showLowerPlaceholder={false}
|
||||||
|
showTopBorder={false}
|
||||||
/>
|
/>
|
||||||
<TouchableOpacity
|
}
|
||||||
disabled={isPinPending || isUnpinPending}
|
/>
|
||||||
|
<Pressable
|
||||||
|
disabled={isPending}
|
||||||
accessibilityRole="button"
|
accessibilityRole="button"
|
||||||
hitSlop={10}
|
hitSlop={10}
|
||||||
onPress={onTogglePinned}>
|
onPress={onTogglePinned}
|
||||||
|
style={state => ({
|
||||||
|
opacity: state.hovered || state.focused || isPending ? 0.5 : 1,
|
||||||
|
})}>
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
icon="thumb-tack"
|
icon="thumb-tack"
|
||||||
size={20}
|
size={20}
|
||||||
color={isPinned ? colors.blue3 : pal.colors.icon}
|
color={isPinned ? colors.blue3 : pal.colors.icon}
|
||||||
/>
|
/>
|
||||||
</TouchableOpacity>
|
</Pressable>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,7 @@ import {
|
||||||
View,
|
View,
|
||||||
ViewStyle,
|
ViewStyle,
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import {
|
import {useFocusEffect, useNavigation} from '@react-navigation/native'
|
||||||
useFocusEffect,
|
|
||||||
useNavigation,
|
|
||||||
StackActions,
|
|
||||||
} from '@react-navigation/native'
|
|
||||||
import {
|
import {
|
||||||
FontAwesomeIcon,
|
FontAwesomeIcon,
|
||||||
FontAwesomeIconStyle,
|
FontAwesomeIconStyle,
|
||||||
|
@ -73,6 +69,8 @@ import {STATUS_PAGE_URL} from 'lib/constants'
|
||||||
import {Plural, Trans, msg} from '@lingui/macro'
|
import {Plural, Trans, msg} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
import {useQueryClient} from '@tanstack/react-query'
|
import {useQueryClient} from '@tanstack/react-query'
|
||||||
|
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
||||||
|
import {useCloseAllActiveElements} from '#/state/util'
|
||||||
|
|
||||||
function SettingsAccountCard({account}: {account: SessionAccount}) {
|
function SettingsAccountCard({account}: {account: SessionAccount}) {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
|
@ -154,13 +152,14 @@ export function SettingsScreen({}: Props) {
|
||||||
const {screen, track} = useAnalytics()
|
const {screen, track} = useAnalytics()
|
||||||
const {openModal} = useModalControls()
|
const {openModal} = useModalControls()
|
||||||
const {isSwitchingAccounts, accounts, currentAccount} = useSession()
|
const {isSwitchingAccounts, accounts, currentAccount} = useSession()
|
||||||
const {clearCurrentAccount} = useSessionApi()
|
|
||||||
const [debugHeaderEnabled, toggleDebugHeader] = useDebugHeaderSetting(
|
const [debugHeaderEnabled, toggleDebugHeader] = useDebugHeaderSetting(
|
||||||
getAgent(),
|
getAgent(),
|
||||||
)
|
)
|
||||||
const {mutate: clearPreferences} = useClearPreferencesMutation()
|
const {mutate: clearPreferences} = useClearPreferencesMutation()
|
||||||
const {data: invites} = useInviteCodesQuery()
|
const {data: invites} = useInviteCodesQuery()
|
||||||
const invitesAvailable = invites?.available?.length ?? 0
|
const invitesAvailable = invites?.available?.length ?? 0
|
||||||
|
const {setShowLoggedOut} = useLoggedOutViewControls()
|
||||||
|
const closeAllActiveElements = useCloseAllActiveElements()
|
||||||
|
|
||||||
const primaryBg = useCustomPalette<ViewStyle>({
|
const primaryBg = useCustomPalette<ViewStyle>({
|
||||||
light: {backgroundColor: colors.blue0},
|
light: {backgroundColor: colors.blue0},
|
||||||
|
@ -189,10 +188,9 @@ export function SettingsScreen({}: Props) {
|
||||||
|
|
||||||
const onPressAddAccount = React.useCallback(() => {
|
const onPressAddAccount = React.useCallback(() => {
|
||||||
track('Settings:AddAccountButtonClicked')
|
track('Settings:AddAccountButtonClicked')
|
||||||
navigation.navigate('HomeTab')
|
setShowLoggedOut(true)
|
||||||
navigation.dispatch(StackActions.popToTop())
|
closeAllActiveElements()
|
||||||
clearCurrentAccount()
|
}, [track, setShowLoggedOut, closeAllActiveElements])
|
||||||
}, [track, navigation, clearCurrentAccount])
|
|
||||||
|
|
||||||
const onPressChangeHandle = React.useCallback(() => {
|
const onPressChangeHandle = React.useCallback(() => {
|
||||||
track('Settings:ChangeHandleButtonClicked')
|
track('Settings:ChangeHandleButtonClicked')
|
||||||
|
|
|
@ -141,7 +141,7 @@ export function DrawerContent() {
|
||||||
} else {
|
} else {
|
||||||
if (tab === 'Notifications') {
|
if (tab === 'Notifications') {
|
||||||
// fetch new notifs on view
|
// fetch new notifs on view
|
||||||
queryClient.invalidateQueries({
|
queryClient.resetQueries({
|
||||||
queryKey: NOTIFS_RQKEY(),
|
queryKey: NOTIFS_RQKEY(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
||||||
} else {
|
} else {
|
||||||
if (tab === 'Notifications') {
|
if (tab === 'Notifications') {
|
||||||
// fetch new notifs on view
|
// fetch new notifs on view
|
||||||
queryClient.invalidateQueries({
|
queryClient.resetQueries({
|
||||||
queryKey: NOTIFS_RQKEY(),
|
queryKey: NOTIFS_RQKEY(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,7 +137,7 @@ const NavItem: React.FC<{
|
||||||
: isTab(currentRoute.name, routeName)
|
: isTab(currentRoute.name, routeName)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link href={href} style={styles.ctrl}>
|
<Link href={href} style={styles.ctrl} navigationAction="navigate">
|
||||||
{children({isActive})}
|
{children({isActive})}
|
||||||
</Link>
|
</Link>
|
||||||
)
|
)
|
||||||
|
|
|
@ -11,7 +11,7 @@ import {usePinnedFeedsInfos} from '#/state/queries/feed'
|
||||||
export function DesktopFeeds() {
|
export function DesktopFeeds() {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const feeds = usePinnedFeedsInfos()
|
const {feeds} = usePinnedFeedsInfos()
|
||||||
|
|
||||||
const route = useNavigationState(state => {
|
const route = useNavigationState(state => {
|
||||||
if (!state) {
|
if (!state) {
|
||||||
|
|
|
@ -150,7 +150,7 @@ function NavItem({count, href, icon, iconFilled, label}: NavItemProps) {
|
||||||
} else {
|
} else {
|
||||||
if (href === '/notifications') {
|
if (href === '/notifications') {
|
||||||
// fetch new notifs on view
|
// fetch new notifs on view
|
||||||
queryClient.invalidateQueries({
|
queryClient.resetQueries({
|
||||||
queryKey: NOTIFS_RQKEY(),
|
queryKey: NOTIFS_RQKEY(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue