diff --git a/app.config.js b/app.config.js --- a/app.config.js +++ b/app.config.js @@ -221,7 +221,7 @@ compileSdkVersion: 35, targetSdkVersion: 35, buildToolsVersion: '35.0.0', - newArchEnabled: true, + newArchEnabled: false, }, }, ], diff --git a/package.json b/package.json --- a/package.json +++ b/package.json @@ -61,8 +61,7 @@ "intl:push": "crowdin push translations --verbose -b main", "nuke": "rm -rf ./node_modules && rm -rf ./ios && rm -rf ./android", "update-extensions": "bash scripts/updateExtensions.sh", - "export-ios": "npx expo export --platform ios --dump-sourcemap && yarn upload-native-sourcemaps", - "export-android": "npx expo export --platform android --dump-sourcemap && yarn upload-native-sourcemaps", + "export": "npx expo export --dump-sourcemap && yarn upload-native-sourcemaps", "upload-native-sourcemaps": "npx sentry-expo-upload-sourcemaps dist", "make-deploy-bundle": "bash scripts/bundleUpdate.sh", "generate-webpack-stats-file": "EXPO_PUBLIC_GENERATE_STATS=1 yarn build-web", @@ -266,7 +265,7 @@ "lint-staged": "^13.2.3", "lockfile-lint": "^4.14.0", "metro-react-native-babel-preset": "^0.77.0", - "prettier": "^2.8.3", + "prettier": "^3.6.0", "react-native-dotenv": "^3.4.11", "react-refresh": "^0.14.0", "svgo": "^3.3.2", diff --git a/svgo.config.mjs b/svgo.config.mjs --- a/svgo.config.mjs +++ b/svgo.config.mjs @@ -1,64 +1,66 @@ const preset = [ - "removeDoctype", - "removeXMLProcInst", - "removeComments", - "removeMetadata", - "removeEditorsNSData", - "cleanupAttrs", - "mergeStyles", - "inlineStyles", - "minifyStyles", - "cleanupIds", - "removeUselessDefs", - "cleanupNumericValues", - "convertColors", - "removeUnknownsAndDefaults", - "removeNonInheritableGroupAttrs", - "removeUselessStrokeAndFill", - "removeDimensions", - "cleanupEnableBackground", - "removeHiddenElems", - "removeEmptyText", - "convertShapeToPath", - "convertEllipseToCircle", - "moveElemsAttrsToGroup", - "moveGroupAttrsToElems", - "collapseGroups", - "convertPathData", - "convertTransform", - "removeEmptyAttrs", - "removeEmptyContainers", - "removeUnusedNS", - "mergePaths", - "sortAttrs", - "sortDefsChildren", - "removeTitle", - "removeDesc", + 'removeDoctype', + 'removeXMLProcInst', + 'removeComments', + 'removeMetadata', + 'removeEditorsNSData', + 'cleanupAttrs', + 'mergeStyles', + 'inlineStyles', + 'minifyStyles', + 'cleanupIds', + 'removeUselessDefs', + 'cleanupNumericValues', + 'convertColors', + 'removeUnknownsAndDefaults', + 'removeNonInheritableGroupAttrs', + 'removeUselessStrokeAndFill', + 'removeDimensions', + 'cleanupEnableBackground', + 'removeHiddenElems', + 'removeEmptyText', + 'convertShapeToPath', + 'convertEllipseToCircle', + 'moveElemsAttrsToGroup', + 'moveGroupAttrsToElems', + 'collapseGroups', + 'convertPathData', + 'convertTransform', + 'removeEmptyAttrs', + 'removeEmptyContainers', + 'removeUnusedNS', + 'mergePaths', + 'sortAttrs', + 'sortDefsChildren', + 'removeTitle', + 'removeDesc', ] export default { - plugins: [...preset.map(name => ({ - name, - params: { - floatPrecision: 3, - transformPrecision: 5, - // minimise diff in ouput from svgomg - // maybe remove in future? will produce smaller output - convertToZ: false, - removeUseless: false, - } - })), - { - name: 'addTrailingWhitespace', - fn() { - return { - root: { - exit (root) { - root.children.push({ type: 'text', value: '\n' }) - return root - } + plugins: [ + ...preset.map(name => ({ + name, + params: { + floatPrecision: 3, + transformPrecision: 5, + // minimise diff in ouput from svgomg + // maybe remove in future? will produce smaller output + convertToZ: false, + removeUseless: false, + }, + })), + { + name: 'addTrailingWhitespace', + fn() { + return { + root: { + exit(root) { + root.children.push({type: 'text', value: '\n'}) + return root + }, + }, } - } - } - }] -}; + }, + }, + ], +} diff --git a/yarn.lock b/yarn.lock --- a/yarn.lock +++ b/yarn.lock @@ -16220,10 +16220,10 @@ resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prettier@^2.8.3: - version "2.8.8" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" - integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== +prettier@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.6.0.tgz#18ec98d62cb0757a5d4eab40253ff3e6d0fc8dea" + integrity sha512-ujSB9uXHJKzM/2GBuE0hBOUgC77CN3Bnpqa+g80bkv3T3A93wL/xlzDATHhnhkzifz/UE2SNOvmbTz5hSkDlHw== pretty-bytes@^5.6.0: version "5.6.0" diff --git a/bskyembed/tailwind.config.cjs b/bskyembed/tailwind.config.cjs --- a/bskyembed/tailwind.config.cjs +++ b/bskyembed/tailwind.config.cjs @@ -1,9 +1,7 @@ /** @type {import('tailwindcss').Config} */ module.exports = { content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'], - darkMode: ['variant', [ - '&:is(.dark *):not(:is(.dark .light *))', - ]], + darkMode: ['variant', ['&:is(.dark *):not(:is(.dark .light *))']], theme: { extend: { colors: { diff --git a/bskyembed/tsconfig.snippet.json b/bskyembed/tsconfig.snippet.json --- a/bskyembed/tsconfig.snippet.json +++ b/bskyembed/tsconfig.snippet.json @@ -1,4 +1,3 @@ - { "compilerOptions": { "target": "ES5", diff --git a/scripts/bundleUpdate.js b/scripts/bundleUpdate.js --- a/scripts/bundleUpdate.js +++ b/scripts/bundleUpdate.js @@ -3,25 +3,17 @@ const fsp = fs.promises const path = require('path') -const IOS_DIST_DIR = './ios-dist' -const ANDROID_DIST_DIR = './android-dist' - +const DIST_DIR = './dist' const BUNDLES_DIR = '/_expo/static/js' - -const IOS_BUNDLE_DIR = path.join(IOS_DIST_DIR, BUNDLES_DIR, '/ios') -const ANDROID_BUNDLE_DIR = path.join(ANDROID_DIST_DIR, BUNDLES_DIR, '/android') - -const IOS_METADATA_PATH = path.join(IOS_DIST_DIR, '/metadata.json') -const ANDROID_METADATA_PATH = path.join(ANDROID_DIST_DIR, '/metadata.json') - +const IOS_BUNDLE_DIR = path.join(DIST_DIR, BUNDLES_DIR, '/ios') +const ANDROID_BUNDLE_DIR = path.join(DIST_DIR, BUNDLES_DIR, '/android') +const METADATA_PATH = path.join(DIST_DIR, '/metadata.json') const DEST_DIR = './bundleTempDir' // Weird, don't feel like figuring out _why_ it wants this -const IOS_METADATA = require(`../${IOS_METADATA_PATH}`) -const ANDROID_METADATA = require(`../${ANDROID_METADATA_PATH}`) - -const IOS_METADATA_ASSETS = IOS_METADATA.fileMetadata.ios.assets -const ANDROID_METADATA_ASSETS = ANDROID_METADATA.fileMetadata.android.assets +const METADATA = require(`../${METADATA_PATH}`) +const IOS_METADATA_ASSETS = METADATA.fileMetadata.ios.assets +const ANDROID_METADATA_ASSETS = METADATA.fileMetadata.android.assets const getMd5 = async path => { return new Promise(res => { @@ -68,7 +60,7 @@ console.log('Getting ios asset md5s and moving them...') for (const asset of IOS_METADATA_ASSETS) { - const currPath = path.join(IOS_DIST_DIR, asset.path) + const currPath = path.join(DIST_DIR, asset.path) const md5 = await getMd5(currPath) const withExtPath = `assets/${md5}.${asset.ext}` iosAssets.push(withExtPath) @@ -77,7 +69,7 @@ console.log('Getting android asset md5s and moving them...') for (const asset of ANDROID_METADATA_ASSETS) { - const currPath = path.join(ANDROID_DIST_DIR, asset.path) + const currPath = path.join(DIST_DIR, asset.path) const md5 = await getMd5(currPath) const withExtPath = `assets/${md5}.${asset.ext}` androidAssets.push(withExtPath) diff --git a/scripts/post-web-build.js b/scripts/post-web-build.js --- a/scripts/post-web-build.js +++ b/scripts/post-web-build.js @@ -9,10 +9,9 @@ 'scripts.html', ) -const {entrypoints} = require(path.join( - projectRoot, - 'web-build/asset-manifest.json', -)) +const {entrypoints} = require( + path.join(projectRoot, 'web-build/asset-manifest.json'), +) console.log(`Found ${entrypoints.length} entrypoints`) console.log(`Writing ${templateFile}`) diff --git a/src/App.native.tsx b/src/App.native.tsx --- a/src/App.native.tsx +++ b/src/App.native.tsx @@ -33,6 +33,7 @@ ensureGeolocationResolved, Provider as GeolocationProvider, } from '#/state/geolocation' +import {GlobalGestureEventsProvider} from '#/state/global-gesture-events' import {Provider as HomeBadgeProvider} from '#/state/home-badge' import {Provider as InvitesStateProvider} from '#/state/invites' import {Provider as LightboxStateProvider} from '#/state/lightbox' @@ -154,11 +155,13 @@ - - - - - + + + + + + + diff --git a/src/style.css b/src/style.css --- a/src/style.css +++ b/src/style.css @@ -328,8 +328,44 @@ /* #/components/Select/index.web.tsx */ .radix-select-content { - box-shadow: 0px 6px 24px -10px rgba(22, 23, 24, 0.25), + box-shadow: + 0px 6px 24px -10px rgba(22, 23, 24, 0.25), 0px 6px 12px -12px rgba(22, 23, 24, 0.15); min-width: var(--radix-select-trigger-width); max-height: var(--radix-select-content-available-height); +} + +/* + * #/components/Tooltip/index.web.tsx + */ +.radix-popover-content { + animation-duration: 300ms; + animation-timing-function: cubic-bezier(0.17, 0.73, 0.14, 1); + will-change: transform, opacity; +} +.radix-popover-content[data-state='open'][data-side='top'] { + animation-name: radixPopoverSlideUpAndFade; +} +.radix-popover-content[data-state='open'][data-side='bottom'] { + animation-name: radixPopoverSlideDownAndFade; +} +@keyframes radixPopoverSlideUpAndFade { + from { + opacity: 0; + transform: translateY(2px); + } + to { + opacity: 1; + transform: translateY(0); + } +} +@keyframes radixPopoverSlideDownAndFade { + from { + opacity: 0; + transform: translateY(-2px); + } + to { + opacity: 1; + transform: translateY(0); + } } diff --git a/.github/workflows/build-submit-android.yml b/.github/workflows/build-submit-android.yml --- a/.github/workflows/build-submit-android.yml +++ b/.github/workflows/build-submit-android.yml @@ -52,10 +52,6 @@ distribution: 'temurin' java-version: '17' - - name: "Use upgraded MMKV for Fabric" - run: | - sed -i 's/"react-native-mmkv": "\^2\.12\.2"/"react-native-mmkv": "^3.3.0"/' package.json - - name: βš™οΈ Install dependencies run: yarn install diff --git a/.github/workflows/bundle-deploy-eas-update.yml b/.github/workflows/bundle-deploy-eas-update.yml --- a/.github/workflows/bundle-deploy-eas-update.yml +++ b/.github/workflows/bundle-deploy-eas-update.yml @@ -5,7 +5,6 @@ push: branches: - main - - hailey/eas-fab workflow_dispatch: inputs: channel: @@ -119,14 +118,7 @@ - name: πŸ—οΈ Create Bundle if: ${{ !steps.fingerprint.outputs.includes-changes }} - run: | - SENTRY_DIST=${{ steps.sentry.outputs.SENTRY_DIST }} SENTRY_RELEASE=${{ steps.sentry.outputs.SENTRY_RELEASE }} SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_DSN=${{ secrets.SENTRY_DSN }} EXPO_PUBLIC_ENV="${{ inputs.channel || 'testflight' }}" yarn export-ios - mv ./dist ./ios-dist - sed -i 's/"react-native-mmkv": "\^2\.12\.2"/"react-native-mmkv": "^3.3.0"/' package.json - yarn install - SENTRY_DIST=${{ steps.sentry.outputs.SENTRY_DIST }} SENTRY_RELEASE=${{ steps.sentry.outputs.SENTRY_RELEASE }} SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_DSN=${{ secrets.SENTRY_DSN }} EXPO_PUBLIC_ENV="${{ inputs.channel || 'testflight' }}" yarn export-android - mv ./dist ./android-dist - + run: SENTRY_DIST=${{ steps.sentry.outputs.SENTRY_DIST }} SENTRY_RELEASE=${{ steps.sentry.outputs.SENTRY_RELEASE }} SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_DSN=${{ secrets.SENTRY_DSN }} EXPO_PUBLIC_ENV="${{ inputs.channel || 'testflight' }}" yarn export - name: πŸ“¦ Package Bundle and πŸš€ Deploy if: ${{ !steps.fingerprint.outputs.includes-changes }} @@ -282,10 +274,6 @@ with: distribution: 'temurin' java-version: '17' - - - name: "Use upgraded MMKV for Fabric" - run: | - sed -i 's/"react-native-mmkv": "\^2\.12\.2"/"react-native-mmkv": "^3.3.0"/' package.json - name: βš™οΈ Install dependencies run: yarn install diff --git a/bskylink/src/index.ts b/bskylink/src/index.ts --- a/bskylink/src/index.ts +++ b/bskylink/src/index.ts @@ -1,11 +1,11 @@ import events from 'node:events' -import http from 'node:http' +import type http from 'node:http' import cors from 'cors' import express from 'express' -import {createHttpTerminator, HttpTerminator} from 'http-terminator' +import {createHttpTerminator, type HttpTerminator} from 'http-terminator' -import {Config} from './config.js' +import {type Config} from './config.js' import {AppContext} from './context.js' import {default as routes, errorHandler} from './routes/index.js' @@ -17,7 +17,10 @@ public server?: http.Server private terminator?: HttpTerminator - constructor(public app: express.Application, public ctx: AppContext) {} + constructor( + public app: express.Application, + public ctx: AppContext, + ) {} static async create(cfg: Config): Promise { let app = express() diff --git a/bskyogcard/src/index.ts b/bskyogcard/src/index.ts --- a/bskyogcard/src/index.ts +++ b/bskyogcard/src/index.ts @@ -1,10 +1,10 @@ import events from 'node:events' -import http from 'node:http' +import type http from 'node:http' import express from 'express' -import {createHttpTerminator, HttpTerminator} from 'http-terminator' +import {createHttpTerminator, type HttpTerminator} from 'http-terminator' -import {Config} from './config.js' +import {type Config} from './config.js' import {AppContext} from './context.js' import {default as routes, errorHandler} from './routes/index.js' @@ -15,7 +15,10 @@ public server?: http.Server private terminator?: HttpTerminator - constructor(public app: express.Application, public ctx: AppContext) {} + constructor( + public app: express.Application, + public ctx: AppContext, + ) {} static async create(cfg: Config): Promise { let app = express() diff --git a/src/alf/atoms.ts b/src/alf/atoms.ts --- a/src/alf/atoms.ts +++ b/src/alf/atoms.ts @@ -983,6 +983,10 @@ transition_none: web({ transitionProperty: 'none', }), + transition_timing_default: web({ + transitionTimingFunction: 'cubic-bezier(0.17, 0.73, 0.14, 1)', + transitionDuration: '100ms', + }), transition_all: web({ transitionProperty: 'all', transitionTimingFunction: 'cubic-bezier(0.17, 0.73, 0.14, 1)', diff --git a/src/components/Link.tsx b/src/components/Link.tsx --- a/src/components/Link.tsx +++ b/src/components/Link.tsx @@ -100,10 +100,10 @@ return typeof to === 'string' ? convertBskyAppUrlIfNeeded(sanitizeUrl(to)) : to.screen - ? router.matchName(to.screen)?.build(to.params) - : to.href - ? convertBskyAppUrlIfNeeded(sanitizeUrl(to.href)) - : undefined + ? router.matchName(to.screen)?.build(to.params) + : to.href + ? convertBskyAppUrlIfNeeded(sanitizeUrl(to.href)) + : undefined }, [to]) if (!href) { diff --git a/src/components/WhoCanReply.tsx b/src/components/WhoCanReply.tsx --- a/src/components/WhoCanReply.tsx +++ b/src/components/WhoCanReply.tsx @@ -1,9 +1,15 @@ import React from 'react' -import {Keyboard, Platform, StyleProp, View, ViewStyle} from 'react-native' import { - AppBskyFeedDefs, + Keyboard, + Platform, + type StyleProp, + View, + type ViewStyle, +} from 'react-native' +import { + type AppBskyFeedDefs, AppBskyFeedPost, - AppBskyGraphDefs, + type AppBskyGraphDefs, AtUri, } from '@atproto/api' import {msg, Trans} from '@lingui/macro' @@ -13,7 +19,7 @@ import {makeListLink, makeProfileLink} from '#/lib/routes/links' import {isNative} from '#/platform/detection' import { - ThreadgateAllowUISetting, + type ThreadgateAllowUISetting, threadgateViewToAllowUISetting, } from '#/state/queries/threadgate' import {atoms as a, useTheme} from '#/alf' @@ -70,8 +76,8 @@ const description = anyoneCanReply ? _(msg`Everybody can reply`) : noOneCanReply - ? _(msg`Replies disabled`) - : _(msg`Some people can reply`) + ? _(msg`Replies disabled`) + : _(msg`Some people can reply`) const onPressOpen = () => { if (isNative && Keyboard.isVisible()) { diff --git a/src/lib/moderation.ts b/src/lib/moderation.ts --- a/src/lib/moderation.ts +++ b/src/lib/moderation.ts @@ -1,18 +1,18 @@ import React from 'react' import { - AppBskyLabelerDefs, + type AppBskyLabelerDefs, BskyAgent, - ComAtprotoLabelDefs, - InterpretedLabelValueDefinition, + type ComAtprotoLabelDefs, + type InterpretedLabelValueDefinition, LABELS, - ModerationCause, - ModerationOpts, - ModerationUI, + type ModerationCause, + type ModerationOpts, + type ModerationUI, } from '@atproto/api' import {sanitizeDisplayName} from '#/lib/strings/display-names' import {sanitizeHandle} from '#/lib/strings/handles' -import {AppModerationCause} from '#/components/Pills' +import {type AppModerationCause} from '#/components/Pills' export const ADULT_CONTENT_LABELS = ['sexual', 'nudity', 'porn'] export const OTHER_SELF_LABELS = ['graphic-media'] @@ -29,8 +29,8 @@ cause.source.type === 'labeler' ? cause.source.did : cause.source.type === 'list' - ? cause.source.list.uri - : 'user' + ? cause.source.list.uri + : 'user' if (cause.type === 'label') { return `label:${cause.label.val}:${source}` } diff --git a/src/platform/polyfills.ts b/src/platform/polyfills.ts --- a/src/platform/polyfills.ts +++ b/src/platform/polyfills.ts @@ -41,12 +41,12 @@ r1 === 64 ? String.fromCharCode((bitmap >> 16) & 255) : r2 === 64 - ? String.fromCharCode((bitmap >> 16) & 255, (bitmap >> 8) & 255) - : String.fromCharCode( - (bitmap >> 16) & 255, - (bitmap >> 8) & 255, - bitmap & 255, - ) + ? String.fromCharCode((bitmap >> 16) & 255, (bitmap >> 8) & 255) + : String.fromCharCode( + (bitmap >> 16) & 255, + (bitmap >> 8) & 255, + bitmap & 255, + ) } return result } diff --git a/src/storage/index.ts b/src/storage/index.ts --- a/src/storage/index.ts +++ b/src/storage/index.ts @@ -1,7 +1,7 @@ import {useCallback, useEffect, useState} from 'react' import {MMKV} from 'react-native-mmkv' -import {Account, Device} from '#/storage/schema' +import {type Account, type Device} from '#/storage/schema' export * from '#/storage/schema' @@ -83,18 +83,10 @@ } } -type StorageSchema> = T extends Storage< - any, - infer U -> - ? U - : never -type StorageScopes> = T extends Storage< - infer S, - any -> - ? S - : never +type StorageSchema> = + T extends Storage ? U : never +type StorageScopes> = + T extends Storage ? S : never /** * Hook to use a storage instance. Acts like a useState hook, but persists the diff --git a/bskylink/src/db/index.ts b/bskylink/src/db/index.ts --- a/bskylink/src/db/index.ts +++ b/bskylink/src/db/index.ts @@ -1,27 +1,30 @@ import assert from 'assert' import { Kysely, - KyselyPlugin, + type KyselyPlugin, Migrator, - PluginTransformQueryArgs, - PluginTransformResultArgs, + type PluginTransformQueryArgs, + type PluginTransformResultArgs, PostgresDialect, - QueryResult, - RootOperationNode, - UnknownRow, + type QueryResult, + type RootOperationNode, + type UnknownRow, } from 'kysely' import {default as Pg} from 'pg' import {dbLogger as log} from '../logger.js' import {default as migrations} from './migrations/index.js' import {DbMigrationProvider} from './migrations/provider.js' -import {DbSchema} from './schema.js' +import {type DbSchema} from './schema.js' export class Database { migrator: Migrator destroyed = false - constructor(public db: Kysely, public cfg: PgConfig) { + constructor( + public db: Kysely, + public cfg: PgConfig, + ) { this.migrator = new Migrator({ db, migrationTableSchema: cfg.schema, diff --git a/modules/expo-emoji-picker/src/EmojiPicker.android.tsx b/modules/expo-emoji-picker/src/EmojiPicker.android.tsx --- a/modules/expo-emoji-picker/src/EmojiPicker.android.tsx +++ b/modules/expo-emoji-picker/src/EmojiPicker.android.tsx @@ -12,7 +12,7 @@ flex: 1, width: '100%', backgroundColor: scheme === 'dark' ? '#000' : '#fff', - } as const), + }) as const, [scheme], ) diff --git a/src/components/ContextMenu/index.tsx b/src/components/ContextMenu/index.tsx --- a/src/components/ContextMenu/index.tsx +++ b/src/components/ContextMenu/index.tsx @@ -190,7 +190,7 @@ if (item) playHaptic('Light') setHoveredMenuItem(item) }, - } satisfies ContextType), + }) satisfies ContextType, [ measurement, setMeasurement, @@ -710,8 +710,8 @@ const xOffset = position ? position.x : align === 'left' - ? measurement.x - : measurement.x + measurement.width - layout.width + ? measurement.x + : measurement.x + measurement.width - layout.width registerHoverable( id, diff --git a/src/components/Select/index.web.tsx b/src/components/Select/index.web.tsx --- a/src/components/Select/index.web.tsx +++ b/src/components/Select/index.web.tsx @@ -111,8 +111,8 @@ borderColor: focused ? t.palette.primary_500 : hovered - ? t.palette.contrast_100 - : t.palette.contrast_25, + ? t.palette.contrast_100 + : t.palette.contrast_25, }, ])}> {children} diff --git a/src/components/Tooltip/const.ts b/src/components/Tooltip/const.ts new file mode 100644 --- /dev/null +++ b/src/components/Tooltip/const.ts @@ -0,0 +1,6 @@ +import {atoms as a} from '#/alf' + +export const BUBBLE_MAX_WIDTH = 240 +export const ARROW_SIZE = 12 +export const ARROW_HALF_SIZE = ARROW_SIZE / 2 +export const MIN_EDGE_SPACE = a.px_lg.paddingLeft diff --git a/src/components/Tooltip/index.tsx b/src/components/Tooltip/index.tsx new file mode 100644 --- /dev/null +++ b/src/components/Tooltip/index.tsx @@ -0,0 +1,411 @@ +import { + Children, + createContext, + useCallback, + useContext, + useMemo, + useRef, + useState, +} from 'react' +import {useWindowDimensions, View} from 'react-native' +import Animated, {Easing, ZoomIn} from 'react-native-reanimated' +import {useSafeAreaInsets} from 'react-native-safe-area-context' + +import {atoms as a, select, useTheme} from '#/alf' +import {useOnGesture} from '#/components/hooks/useOnGesture' +import {Portal} from '#/components/Portal' +import { + ARROW_HALF_SIZE, + ARROW_SIZE, + BUBBLE_MAX_WIDTH, + MIN_EDGE_SPACE, +} from '#/components/Tooltip/const' +import {Text} from '#/components/Typography' + +/** + * These are native specific values, not shared with web + */ +const ARROW_VISUAL_OFFSET = ARROW_SIZE / 1.25 // vibes-based, slightly off the target +const BUBBLE_SHADOW_OFFSET = ARROW_SIZE / 3 // vibes-based, provide more shadow beneath tip + +type TooltipContextType = { + position: 'top' | 'bottom' + ready: boolean + onVisibleChange: (visible: boolean) => void +} + +type TargetContextType = { + targetMeasurements: + | { + x: number + y: number + width: number + height: number + } + | undefined + targetRef: React.RefObject +} + +const TooltipContext = createContext({ + position: 'bottom', + ready: false, + onVisibleChange: () => {}, +}) + +const TargetContext = createContext({ + targetMeasurements: undefined, + targetRef: {current: null}, +}) + +export function Outer({ + children, + position = 'bottom', + visible: requestVisible, + onVisibleChange, +}: { + children: React.ReactNode + position?: 'top' | 'bottom' + visible: boolean + onVisibleChange: (visible: boolean) => void +}) { + /** + * Whether we have measured the target and are ready to show the tooltip. + */ + const [ready, setReady] = useState(false) + /** + * Lagging state to track the externally-controlled visibility of the + * tooltip. + */ + const [prevRequestVisible, setPrevRequestVisible] = useState< + boolean | undefined + >() + /** + * Needs to reference the element this Tooltip is attached to. + */ + const targetRef = useRef(null) + const [targetMeasurements, setTargetMeasurements] = useState< + | { + x: number + y: number + width: number + height: number + } + | undefined + >(undefined) + + if (requestVisible && !prevRequestVisible) { + setPrevRequestVisible(true) + + if (targetRef.current) { + /* + * Once opened, measure the dimensions and position of the target + */ + targetRef.current.measure((_x, _y, width, height, pageX, pageY) => { + if (pageX !== undefined && pageY !== undefined && width && height) { + setTargetMeasurements({x: pageX, y: pageY, width, height}) + setReady(true) + } + }) + } + } else if (!requestVisible && prevRequestVisible) { + setPrevRequestVisible(false) + setTargetMeasurements(undefined) + setReady(false) + } + + const ctx = useMemo( + () => ({position, ready, onVisibleChange}), + [position, ready, onVisibleChange], + ) + const targetCtx = useMemo( + () => ({targetMeasurements, targetRef}), + [targetMeasurements, targetRef], + ) + + return ( + + + {children} + + + ) +} + +export function Target({children}: {children: React.ReactNode}) { + const {targetRef} = useContext(TargetContext) + + return ( + + {children} + + ) +} + +export function Content({ + children, + label, +}: { + children: React.ReactNode + label: string +}) { + const {position, ready, onVisibleChange} = useContext(TooltipContext) + const {targetMeasurements} = useContext(TargetContext) + const requestClose = useCallback(() => { + onVisibleChange(false) + }, [onVisibleChange]) + + if (!ready || !targetMeasurements) return null + + return ( + + + {children} + + + ) +} + +function Bubble({ + children, + label, + position, + requestClose, + targetMeasurements, +}: { + children: React.ReactNode + label: string + position: TooltipContextType['position'] + requestClose: () => void + targetMeasurements: Exclude< + TargetContextType['targetMeasurements'], + undefined + > +}) { + const t = useTheme() + const insets = useSafeAreaInsets() + const dimensions = useWindowDimensions() + const [bubbleMeasurements, setBubbleMeasurements] = useState< + | { + width: number + height: number + } + | undefined + >(undefined) + const coords = useMemo(() => { + if (!bubbleMeasurements) + return { + top: 0, + bottom: 0, + left: 0, + right: 0, + tipTop: 0, + tipLeft: 0, + } + + const {width: ww, height: wh} = dimensions + const maxTop = insets.top + const maxBottom = wh - insets.bottom + const {width: cw, height: ch} = bubbleMeasurements + const minLeft = MIN_EDGE_SPACE + const maxLeft = ww - minLeft + + let computedPosition: 'top' | 'bottom' = position + let top = targetMeasurements.y + targetMeasurements.height + let left = Math.max( + minLeft, + targetMeasurements.x + targetMeasurements.width / 2 - cw / 2, + ) + const tipTranslate = ARROW_HALF_SIZE * -1 + let tipTop = tipTranslate + + if (left + cw > maxLeft) { + left -= left + cw - maxLeft + } + + let tipLeft = + targetMeasurements.x - + left + + targetMeasurements.width / 2 - + ARROW_HALF_SIZE + + let bottom = top + ch + + function positionTop() { + top = top - ch - targetMeasurements.height + bottom = top + ch + tipTop = tipTop + ch + computedPosition = 'top' + } + + function positionBottom() { + top = targetMeasurements.y + targetMeasurements.height + bottom = top + ch + tipTop = tipTranslate + computedPosition = 'bottom' + } + + if (position === 'top') { + positionTop() + if (top < maxTop) { + positionBottom() + } + } else { + if (bottom > maxBottom) { + positionTop() + } + } + + if (computedPosition === 'bottom') { + top += ARROW_VISUAL_OFFSET + bottom += ARROW_VISUAL_OFFSET + } else { + top -= ARROW_VISUAL_OFFSET + bottom -= ARROW_VISUAL_OFFSET + } + + return { + computedPosition, + top, + bottom, + left, + right: left + cw, + tipTop, + tipLeft, + } + }, [position, targetMeasurements, bubbleMeasurements, insets, dimensions]) + + const requestCloseWrapped = useCallback(() => { + setBubbleMeasurements(undefined) + requestClose() + }, [requestClose]) + + useOnGesture( + useCallback( + e => { + const {x, y} = e + const isInside = + x > coords.left && + x < coords.right && + y > coords.top && + y < coords.bottom + + if (!isInside) { + requestCloseWrapped() + } + }, + [coords, requestCloseWrapped], + ), + ) + + return ( + + + + { + setBubbleMeasurements({ + width: e.nativeEvent.layout.width, + height: e.nativeEvent.layout.height, + }) + }}> + {children} + + + + ) +} + +function oppposite(position: 'top' | 'bottom') { + switch (position) { + case 'top': + return 'center bottom' + case 'bottom': + return 'center top' + default: + return 'center' + } +} + +export function TextBubble({children}: {children: React.ReactNode}) { + const c = Children.toArray(children) + return ( + + + {c.map((child, i) => ( + + {child} + + ))} + + + ) +} diff --git a/src/components/Tooltip/index.web.tsx b/src/components/Tooltip/index.web.tsx new file mode 100644 --- /dev/null +++ b/src/components/Tooltip/index.web.tsx @@ -0,0 +1,112 @@ +import {Children, createContext, useContext, useMemo} from 'react' +import {View} from 'react-native' +import {Popover} from 'radix-ui' + +import {atoms as a, flatten, select, useTheme} from '#/alf' +import {transparentifyColor} from '#/alf/util/colorGeneration' +import { + ARROW_SIZE, + BUBBLE_MAX_WIDTH, + MIN_EDGE_SPACE, +} from '#/components/Tooltip/const' +import {Text} from '#/components/Typography' + +type TooltipContextType = { + position: 'top' | 'bottom' +} + +const TooltipContext = createContext({ + position: 'bottom', +}) + +export function Outer({ + children, + position = 'bottom', + visible, + onVisibleChange, +}: { + children: React.ReactNode + position?: 'top' | 'bottom' + visible: boolean + onVisibleChange: (visible: boolean) => void +}) { + const ctx = useMemo(() => ({position}), [position]) + return ( + + {children} + + ) +} + +export function Target({children}: {children: React.ReactNode}) { + return ( + + {children} + + ) +} + +export function Content({ + children, + label, +}: { + children: React.ReactNode + label: string +}) { + const t = useTheme() + const {position} = useContext(TooltipContext) + return ( + + + + + {children} + + + + ) +} + +export function TextBubble({children}: {children: React.ReactNode}) { + const c = Children.toArray(children) + return ( + + + {c.map((child, i) => ( + + {child} + + ))} + + + ) +} diff --git a/src/components/dialogs/SearchablePeopleList.tsx b/src/components/dialogs/SearchablePeopleList.tsx --- a/src/components/dialogs/SearchablePeopleList.tsx +++ b/src/components/dialogs/SearchablePeopleList.tsx @@ -390,8 +390,8 @@ !enabled ? {opacity: 0.5} : pressed || focused || hovered - ? t.atoms.bg_contrast_25 - : t.atoms.bg, + ? t.atoms.bg_contrast_25 + : t.atoms.bg, ]}> {children} diff --git a/src/components/icons/VerifiedCheck.tsx b/src/components/icons/VerifiedCheck.tsx --- a/src/components/icons/VerifiedCheck.tsx +++ b/src/components/icons/VerifiedCheck.tsx @@ -3,28 +3,27 @@ import {type Props, useCommonSVGProps} from '#/components/icons/common' -export const VerifiedCheck = React.forwardRef(function LogoImpl( - props, - ref, -) { - const {fill, size, style, ...rest} = useCommonSVGProps(props) +export const VerifiedCheck = React.forwardRef( + function LogoImpl(props, ref) { + const {fill, size, style, ...rest} = useCommonSVGProps(props) - return ( - - - - - ) -}) + return ( + + + + + ) + }, +) diff --git a/src/components/icons/VerifierCheck.tsx b/src/components/icons/VerifierCheck.tsx --- a/src/components/icons/VerifierCheck.tsx +++ b/src/components/icons/VerifierCheck.tsx @@ -3,33 +3,32 @@ import {type Props, useCommonSVGProps} from '#/components/icons/common' -export const VerifierCheck = React.forwardRef(function LogoImpl( - props, - ref, -) { - const {fill, size, style, ...rest} = useCommonSVGProps(props) +export const VerifierCheck = React.forwardRef( + function LogoImpl(props, ref) { + const {fill, size, style, ...rest} = useCommonSVGProps(props) - return ( - - - - - ) -}) + return ( + + + + + ) + }, +) diff --git a/src/components/moderation/ContentHider.tsx b/src/components/moderation/ContentHider.tsx --- a/src/components/moderation/ContentHider.tsx +++ b/src/components/moderation/ContentHider.tsx @@ -1,6 +1,6 @@ import React from 'react' -import {StyleProp, View, ViewStyle} from 'react-native' -import {ModerationUI} from '@atproto/api' +import {type StyleProp, View, type ViewStyle} from 'react-native' +import {type ModerationUI} from '@atproto/api' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' @@ -148,8 +148,8 @@ modui.noOverride ? _(msg`Learn more about the moderation applied to this content`) : override - ? _(msg`Hides the content`) - : _(msg`Shows the content`) + ? _(msg`Hides the content`) + : _(msg`Shows the content`) }> {state => ( diff --git a/src/components/verification/VerificationsDialog.tsx b/src/components/verification/VerificationsDialog.tsx --- a/src/components/verification/VerificationsDialog.tsx +++ b/src/components/verification/VerificationsDialog.tsx @@ -64,13 +64,13 @@ ? _(msg`You are verified`) : _(msg`Your verifications`) : state.profile.isVerified - ? _(msg`${userName} is verified`) - : _( - msg({ - message: `${userName}'s verifications`, - comment: `Possessive, meaning "the verifications of {userName}"`, - }), - ) + ? _(msg`${userName} is verified`) + : _( + msg({ + message: `${userName}'s verifications`, + comment: `Possessive, meaning "the verifications of {userName}"`, + }), + ) return ( ({type: 'CONVERSATION', conversation: convo} as const), + convo => ({type: 'CONVERSATION', conversation: convo}) as const, ), ] satisfies ListItem[] } diff --git a/src/screens/Onboarding/StepFinished.tsx b/src/screens/Onboarding/StepFinished.tsx --- a/src/screens/Onboarding/StepFinished.tsx +++ b/src/screens/Onboarding/StepFinished.tsx @@ -176,8 +176,8 @@ avatarResult: profileStepResults.isCreatedAvatar ? 'created' : profileStepResults.image - ? 'uploaded' - : 'default', + ? 'uploaded' + : 'default', }) })(), requestNotificationsPermission('AfterOnboarding'), diff --git a/src/screens/Search/Explore.tsx b/src/screens/Search/Explore.tsx --- a/src/screens/Search/Explore.tsx +++ b/src/screens/Search/Explore.tsx @@ -342,11 +342,11 @@ ]) const topBorder = useMemo( - () => ({type: 'topBorder', key: 'top-border'} as const), + () => ({type: 'topBorder', key: 'top-border'}) as const, [], ) const trendingTopicsModule = useMemo( - () => ({type: 'trendingTopics', key: 'trending-topics'} as const), + () => ({type: 'trendingTopics', key: 'trending-topics'}) as const, [], ) const suggestedFollowsModule = useMemo(() => { diff --git a/src/state/cache/profile-shadow.ts b/src/state/cache/profile-shadow.ts --- a/src/state/cache/profile-shadow.ts +++ b/src/state/cache/profile-shadow.ts @@ -146,8 +146,8 @@ 'status' in shadow ? shadow.status : 'status' in profile - ? profile.status - : undefined, + ? profile.status + : undefined, }) } diff --git a/src/state/global-gesture-events/index.tsx b/src/state/global-gesture-events/index.tsx new file mode 100644 --- /dev/null +++ b/src/state/global-gesture-events/index.tsx @@ -0,0 +1,83 @@ +import {createContext, useContext, useMemo, useRef, useState} from 'react' +import {View} from 'react-native' +import { + Gesture, + GestureDetector, + type GestureStateChangeEvent, + type GestureUpdateEvent, + type PanGestureHandlerEventPayload, +} from 'react-native-gesture-handler' +import EventEmitter from 'eventemitter3' + +export type GlobalGestureEvents = { + begin: GestureStateChangeEvent + update: GestureUpdateEvent + end: GestureStateChangeEvent + finalize: GestureStateChangeEvent +} + +const Context = createContext<{ + events: EventEmitter + register: () => void + unregister: () => void +}>({ + events: new EventEmitter(), + register: () => {}, + unregister: () => {}, +}) + +export function GlobalGestureEventsProvider({ + children, +}: { + children: React.ReactNode +}) { + const refCount = useRef(0) + const events = useMemo(() => new EventEmitter(), []) + const [enabled, setEnabled] = useState(false) + const ctx = useMemo( + () => ({ + events, + register() { + refCount.current += 1 + if (refCount.current === 1) { + setEnabled(true) + } + }, + unregister() { + refCount.current -= 1 + if (refCount.current === 0) { + setEnabled(false) + } + }, + }), + [events, setEnabled], + ) + const gesture = Gesture.Pan() + .runOnJS(true) + .enabled(enabled) + .simultaneousWithExternalGesture() + .onBegin(e => { + events.emit('begin', e) + }) + .onUpdate(e => { + events.emit('update', e) + }) + .onEnd(e => { + events.emit('end', e) + }) + .onFinalize(e => { + events.emit('finalize', e) + }) + + return ( + + + {children} + + + ) +} + +export function useGlobalGestureEvents() { + return useContext(Context) +} diff --git a/src/state/global-gesture-events/index.web.tsx b/src/state/global-gesture-events/index.web.tsx new file mode 100644 --- /dev/null +++ b/src/state/global-gesture-events/index.web.tsx @@ -0,0 +1,9 @@ +export function GlobalGestureEventsProvider(_props: { + children: React.ReactNode +}) { + throw new Error('GlobalGestureEventsProvider is not supported on web.') +} + +export function useGlobalGestureEvents() { + throw new Error('useGlobalGestureEvents is not supported on web.') +} diff --git a/src/state/queries/explore-feed-previews.tsx b/src/state/queries/explore-feed-previews.tsx --- a/src/state/queries/explore-feed-previews.tsx +++ b/src/state/queries/explore-feed-previews.tsx @@ -36,38 +36,27 @@ const LIMIT = 8 // sliced to 6, overfetch to account for moderation const PINNED_POST_URIS: Record = { // πŸ“° News - 'at://did:plc:kkf4naxqmweop7dv4l2iqqf5/app.bsky.feed.post/3lgh27w2ngc2b': - true, + 'at://did:plc:kkf4naxqmweop7dv4l2iqqf5/app.bsky.feed.post/3lgh27w2ngc2b': true, // Gardening - 'at://did:plc:5rw2on4i56btlcajojaxwcat/app.bsky.feed.post/3kjorckgcwc27': - true, + 'at://did:plc:5rw2on4i56btlcajojaxwcat/app.bsky.feed.post/3kjorckgcwc27': true, // Web Development Trending - 'at://did:plc:m2sjv3wncvsasdapla35hzwj/app.bsky.feed.post/3lfaw445axs22': - true, + 'at://did:plc:m2sjv3wncvsasdapla35hzwj/app.bsky.feed.post/3lfaw445axs22': true, // Anime & Manga EN - 'at://did:plc:tazrmeme4dzahimsykusrwrk/app.bsky.feed.post/3knxx2gmkns2y': - true, + 'at://did:plc:tazrmeme4dzahimsykusrwrk/app.bsky.feed.post/3knxx2gmkns2y': true, // πŸ“½οΈ Film - 'at://did:plc:2hwwem55ce6djnk6bn62cstr/app.bsky.feed.post/3llhpzhbq7c2g': - true, + 'at://did:plc:2hwwem55ce6djnk6bn62cstr/app.bsky.feed.post/3llhpzhbq7c2g': true, // PopSky - 'at://did:plc:lfdf4srj43iwdng7jn35tjsp/app.bsky.feed.post/3lbblgly65c2g': - true, + 'at://did:plc:lfdf4srj43iwdng7jn35tjsp/app.bsky.feed.post/3lbblgly65c2g': true, // Science - 'at://did:plc:hu2obebw3nhfj667522dahfg/app.bsky.feed.post/3kl33otd6ob2s': - true, + 'at://did:plc:hu2obebw3nhfj667522dahfg/app.bsky.feed.post/3kl33otd6ob2s': true, // Birds! πŸ¦‰ - 'at://did:plc:ffkgesg3jsv2j7aagkzrtcvt/app.bsky.feed.post/3lbg4r57yk22d': - true, + 'at://did:plc:ffkgesg3jsv2j7aagkzrtcvt/app.bsky.feed.post/3lbg4r57yk22d': true, // Astronomy - 'at://did:plc:xy2zorw2ys47poflotxthlzg/app.bsky.feed.post/3kyzye4lujs2w': - true, + 'at://did:plc:xy2zorw2ys47poflotxthlzg/app.bsky.feed.post/3kyzye4lujs2w': true, // What's Cooking 🍽️ - 'at://did:plc:geoqe3qls5mwezckxxsewys2/app.bsky.feed.post/3lfqhgvxbqc2q': - true, + 'at://did:plc:geoqe3qls5mwezckxxsewys2/app.bsky.feed.post/3lfqhgvxbqc2q': true, // BookSky πŸ’™πŸ“š #booksky - 'at://did:plc:geoqe3qls5mwezckxxsewys2/app.bsky.feed.post/3kgrm2rw5ww2e': - true, + 'at://did:plc:geoqe3qls5mwezckxxsewys2/app.bsky.feed.post/3kgrm2rw5ww2e': true, } export type FeedPreviewItem = diff --git a/src/view/screens/DebugMod.tsx b/src/view/screens/DebugMod.tsx --- a/src/view/screens/DebugMod.tsx +++ b/src/view/screens/DebugMod.tsx @@ -113,14 +113,14 @@ }), ] : scenario[0] === 'label' && target[0] === 'profile' - ? [ - mock.label({ - src: isSelfLabel ? did : undefined, - val: label[0], - uri: `at://${did}/app.bsky.actor.profile/self`, - }), - ] - : undefined, + ? [ + mock.label({ + src: isSelfLabel ? did : undefined, + val: label[0], + uri: `at://${did}/app.bsky.actor.profile/self`, + }), + ] + : undefined, viewer: mock.actorViewerState({ following: isFollowing ? `at://${currentAccount?.did || ''}/app.bsky.graph.follow/1234` diff --git a/src/components/Post/Embed/ImageEmbed.tsx b/src/components/Post/Embed/ImageEmbed.tsx --- a/src/components/Post/Embed/ImageEmbed.tsx +++ b/src/components/Post/Embed/ImageEmbed.tsx @@ -82,9 +82,9 @@ rest.viewContext === PostEmbedViewContext.ThreadHighlighted ? 'none' : rest.viewContext === - PostEmbedViewContext.FeedEmbedRecordWithMedia - ? 'square' - : 'constrained' + PostEmbedViewContext.FeedEmbedRecordWithMedia + ? 'square' + : 'constrained' } image={image} onPress={(containerRef, dims) => onPress(0, [containerRef], [dims])} diff --git a/src/components/PostControls/PostMenu/PostMenuItems.tsx b/src/components/PostControls/PostMenu/PostMenuItems.tsx --- a/src/components/PostControls/PostMenu/PostMenuItems.tsx +++ b/src/components/PostControls/PostMenu/PostMenuItems.tsx @@ -698,8 +698,8 @@ isDetachPending ? Loader : quoteEmbed.isDetached - ? Eye - : EyeSlash + ? Eye + : EyeSlash } position="right" /> diff --git a/src/components/hooks/useOnGesture/index.ts b/src/components/hooks/useOnGesture/index.ts new file mode 100644 --- /dev/null +++ b/src/components/hooks/useOnGesture/index.ts @@ -0,0 +1,24 @@ +import {useEffect} from 'react' + +import { + type GlobalGestureEvents, + useGlobalGestureEvents, +} from '#/state/global-gesture-events' + +/** + * Listen for global gesture events. Callback should be wrapped with + * `useCallback` or otherwise memoized to avoid unnecessary re-renders. + */ +export function useOnGesture( + onGestureCallback: (e: GlobalGestureEvents['begin']) => void, +) { + const ctx = useGlobalGestureEvents() + useEffect(() => { + ctx.register() + ctx.events.on('begin', onGestureCallback) + return () => { + ctx.unregister() + ctx.events.off('begin', onGestureCallback) + } + }, [ctx, onGestureCallback]) +} diff --git a/src/components/hooks/useOnGesture/index.web.ts b/src/components/hooks/useOnGesture/index.web.ts new file mode 100644 --- /dev/null +++ b/src/components/hooks/useOnGesture/index.web.ts @@ -0,0 +1,1 @@ +export function useOnGesture() {} diff --git a/src/components/moderation/ReportDialog/index.tsx b/src/components/moderation/ReportDialog/index.tsx --- a/src/components/moderation/ReportDialog/index.tsx +++ b/src/components/moderation/ReportDialog/index.tsx @@ -512,13 +512,13 @@ backgroundColor: active ? t.palette.primary_500 : completed - ? t.palette.primary_100 - : t.atoms.bg_contrast_25.backgroundColor, + ? t.palette.primary_100 + : t.atoms.bg_contrast_25.backgroundColor, borderColor: active ? t.palette.primary_500 : completed - ? t.palette.primary_400 - : t.atoms.border_contrast_low.borderColor, + ? t.palette.primary_400 + : t.atoms.border_contrast_low.borderColor, }, ]}> {completed ? ( @@ -533,8 +533,8 @@ color: active ? 'white' : completed - ? t.palette.primary_700 - : t.atoms.text_contrast_medium.color, + ? t.palette.primary_700 + : t.atoms.text_contrast_medium.color, fontVariant: ['tabular-nums'], width: 24, height: 24, diff --git a/src/locale/locales/en/messages.po b/src/locale/locales/en/messages.po --- a/src/locale/locales/en/messages.po +++ b/src/locale/locales/en/messages.po @@ -456,7 +456,7 @@ msgid "<0>{0} is included in your starter pack" msgstr "" -#: src/components/WhoCanReply.tsx:296 +#: src/components/WhoCanReply.tsx:302 msgid "<0>{0} members" msgstr "" @@ -866,7 +866,7 @@ msgid "An error occurred while compressing the video." msgstr "" -#: src/state/queries/explore-feed-previews.tsx:184 +#: src/state/queries/explore-feed-previews.tsx:173 msgid "An error occurred while fetching the feed." msgstr "" @@ -939,7 +939,7 @@ msgid "an unknown labeler" msgstr "" -#: src/components/WhoCanReply.tsx:317 +#: src/components/WhoCanReply.tsx:323 msgid "and" msgstr "" @@ -1066,7 +1066,7 @@ msgid "Are you sure you want to delete the app password \"{0}\"?" msgstr "" -#: src/components/dms/MessageContextMenu.tsx:189 +#: src/components/dms/MessageContextMenu.tsx:188 msgid "Are you sure you want to delete this message? The message will be deleted for you, but not for the other participant." msgstr "" @@ -1128,7 +1128,7 @@ msgid "At least 3 characters" msgstr "" -#: src/screens/Settings/AppIconSettings/useAppIconSets.ts:40 +#: src/screens/Settings/AppIconSettings/useAppIconSets.ts:48 msgctxt "Name of app icon variant" msgid "Aurora" msgstr "" @@ -1302,7 +1302,7 @@ msgid "Bluesky cannot confirm the authenticity of the claimed date." msgstr "" -#: src/screens/Settings/AppIconSettings/useAppIconSets.ts:129 +#: src/screens/Settings/AppIconSettings/useAppIconSets.ts:165 msgctxt "Name of app icon variant" msgid "Bluesky Classicβ„’" msgstr "" @@ -2096,8 +2096,8 @@ msgid "Copy link to starter pack" msgstr "" -#: src/components/dms/MessageContextMenu.tsx:150 -#: src/components/dms/MessageContextMenu.tsx:153 +#: src/components/dms/MessageContextMenu.tsx:149 +#: src/components/dms/MessageContextMenu.tsx:152 msgid "Copy message text" msgstr "" @@ -2145,7 +2145,7 @@ msgid "Could not process your video" msgstr "" -#: src/state/queries/notifications/settings.ts:50 +#: src/state/queries/notifications/settings.ts:49 msgid "Could not update notification settings" msgstr "" @@ -2247,7 +2247,7 @@ msgid "Dark" msgstr "" -#: src/screens/Settings/AppIconSettings/useAppIconSets.ts:24 +#: src/screens/Settings/AppIconSettings/useAppIconSets.ts:28 msgctxt "Name of app icon variant" msgid "Dark" msgstr "" @@ -2286,7 +2286,7 @@ msgid "Default icons" msgstr "" -#: src/components/dms/MessageContextMenu.tsx:191 +#: src/components/dms/MessageContextMenu.tsx:190 #: src/components/PostControls/PostMenu/PostMenuItems.tsx:701 #: src/screens/Messages/components/ChatStatusInfo.tsx:55 #: src/screens/Settings/AppPasswords.tsx:212 @@ -2334,7 +2334,7 @@ msgid "Delete Conversation" msgstr "" -#: src/components/dms/MessageContextMenu.tsx:164 +#: src/components/dms/MessageContextMenu.tsx:163 msgid "Delete for me" msgstr "" @@ -2342,11 +2342,11 @@ msgid "Delete list" msgstr "" -#: src/components/dms/MessageContextMenu.tsx:187 +#: src/components/dms/MessageContextMenu.tsx:186 msgid "Delete message" msgstr "" -#: src/components/dms/MessageContextMenu.tsx:162 +#: src/components/dms/MessageContextMenu.tsx:161 msgid "Delete message for me" msgstr "" @@ -2433,7 +2433,7 @@ msgid "Developer options" msgstr "" -#: src/components/WhoCanReply.tsx:179 +#: src/components/WhoCanReply.tsx:185 msgid "Dialog: adjust who can interact with this post" msgstr "" @@ -2759,7 +2759,7 @@ msgid "Edit User List" msgstr "" -#: src/components/WhoCanReply.tsx:91 +#: src/components/WhoCanReply.tsx:97 msgid "Edit who can reply" msgstr "" @@ -2984,11 +2984,11 @@ msgid "Everybody" msgstr "" -#: src/components/WhoCanReply.tsx:71 +#: src/components/WhoCanReply.tsx:77 msgid "Everybody can reply" msgstr "" -#: src/components/WhoCanReply.tsx:222 +#: src/components/WhoCanReply.tsx:228 msgid "Everybody can reply to this post." msgstr "" @@ -3409,17 +3409,17 @@ msgid "Fitness" msgstr "" -#: src/screens/Settings/AppIconSettings/useAppIconSets.ts:117 +#: src/screens/Settings/AppIconSettings/useAppIconSets.ts:149 msgctxt "Name of app icon variant" msgid "Flat Black" msgstr "" -#: src/screens/Settings/AppIconSettings/useAppIconSets.ts:93 +#: src/screens/Settings/AppIconSettings/useAppIconSets.ts:117 msgctxt "Name of app icon variant" msgid "Flat Blue" msgstr "" -#: src/screens/Settings/AppIconSettings/useAppIconSets.ts:105 +#: src/screens/Settings/AppIconSettings/useAppIconSets.ts:133 msgctxt "Name of app icon variant" msgid "Flat White" msgstr "" @@ -3920,23 +3920,23 @@ msgid "Hides the content" msgstr "" -#: src/view/com/posts/PostFeedErrorMessage.tsx:117 +#: src/view/com/posts/PostFeedErrorMessage.tsx:121 msgid "Hmm, some kind of issue occurred when contacting the feed server. Please let the feed owner know about this issue." msgstr "" -#: src/view/com/posts/PostFeedErrorMessage.tsx:105 +#: src/view/com/posts/PostFeedErrorMessage.tsx:109 msgid "Hmm, the feed server appears to be misconfigured. Please let the feed owner know about this issue." msgstr "" -#: src/view/com/posts/PostFeedErrorMessage.tsx:111 +#: src/view/com/posts/PostFeedErrorMessage.tsx:115 msgid "Hmm, the feed server appears to be offline. Please let the feed owner know about this issue." msgstr "" -#: src/view/com/posts/PostFeedErrorMessage.tsx:108 +#: src/view/com/posts/PostFeedErrorMessage.tsx:112 msgid "Hmm, the feed server gave a bad response. Please let the feed owner know about this issue." msgstr "" -#: src/view/com/posts/PostFeedErrorMessage.tsx:102 +#: src/view/com/posts/PostFeedErrorMessage.tsx:106 msgid "Hmm, we're having trouble finding this feed. It may have been deleted." msgstr "" @@ -4680,7 +4680,7 @@ msgid "Mention notifications" msgstr "" -#: src/components/WhoCanReply.tsx:263 +#: src/components/WhoCanReply.tsx:269 msgid "mentioned users" msgstr "" @@ -4716,7 +4716,7 @@ msgid "Message from @{0}: {1}" msgstr "" -#: src/view/com/posts/PostFeedErrorMessage.tsx:201 +#: src/view/com/posts/PostFeedErrorMessage.tsx:205 msgid "Message from server: {0}" msgstr "" @@ -4737,7 +4737,7 @@ msgid "Messages" msgstr "" -#: src/screens/Settings/AppIconSettings/useAppIconSets.ts:81 +#: src/screens/Settings/AppIconSettings/useAppIconSets.ts:101 msgctxt "Name of app icon variant" msgid "Midnight" msgstr "" @@ -5193,7 +5193,7 @@ msgid "No one" msgstr "" -#: src/components/WhoCanReply.tsx:246 +#: src/components/WhoCanReply.tsx:252 msgid "No one but the author can quote this post." msgstr "" @@ -5419,7 +5419,7 @@ msgid "Only .jpg and .png files are supported" msgstr "" -#: src/components/WhoCanReply.tsx:226 +#: src/components/WhoCanReply.tsx:232 msgid "Only {0} can reply." msgstr "" @@ -6057,7 +6057,7 @@ msgid "Posts can be muted based on their text, their tags, or both. We recommend avoiding common words that appear in many posts, since it can result in no posts being shown." msgstr "" -#: src/view/com/posts/PostFeedErrorMessage.tsx:68 +#: src/view/com/posts/PostFeedErrorMessage.tsx:72 msgid "Posts hidden" msgstr "" @@ -6361,7 +6361,7 @@ #: src/screens/Settings/Settings.tsx:556 #: src/view/com/feeds/FeedSourceCard.tsx:322 #: src/view/com/modals/UserAddRemoveLists.tsx:235 -#: src/view/com/posts/PostFeedErrorMessage.tsx:213 +#: src/view/com/posts/PostFeedErrorMessage.tsx:217 msgid "Remove" msgstr "" @@ -6398,11 +6398,11 @@ #: src/view/com/posts/FeedShutdownMsg.tsx:116 #: src/view/com/posts/FeedShutdownMsg.tsx:120 -#: src/view/com/posts/PostFeedErrorMessage.tsx:169 +#: src/view/com/posts/PostFeedErrorMessage.tsx:173 msgid "Remove feed" msgstr "" -#: src/view/com/posts/PostFeedErrorMessage.tsx:210 +#: src/view/com/posts/PostFeedErrorMessage.tsx:214 msgid "Remove feed?" msgstr "" @@ -6455,7 +6455,7 @@ msgid "Remove subtitle file" msgstr "" -#: src/view/com/posts/PostFeedErrorMessage.tsx:211 +#: src/view/com/posts/PostFeedErrorMessage.tsx:215 msgid "Remove this feed from your saved feeds" msgstr "" @@ -6517,11 +6517,11 @@ msgid "Replies" msgstr "" -#: src/components/WhoCanReply.tsx:73 +#: src/components/WhoCanReply.tsx:79 msgid "Replies disabled" msgstr "" -#: src/components/WhoCanReply.tsx:224 +#: src/components/WhoCanReply.tsx:230 msgid "Replies to this post are disabled." msgstr "" @@ -6593,7 +6593,7 @@ msgid "Reply was successfully hidden" msgstr "" -#: src/components/dms/MessageContextMenu.tsx:172 +#: src/components/dms/MessageContextMenu.tsx:171 #: src/components/dms/MessagesListBlockedFooter.tsx:85 #: src/components/dms/MessagesListBlockedFooter.tsx:92 msgid "Report" @@ -6627,7 +6627,7 @@ msgid "Report list" msgstr "" -#: src/components/dms/MessageContextMenu.tsx:170 +#: src/components/dms/MessageContextMenu.tsx:169 msgid "Report message" msgstr "" @@ -7646,7 +7646,7 @@ msgid "Some other feeds you might like" msgstr "" -#: src/components/WhoCanReply.tsx:74 +#: src/components/WhoCanReply.tsx:80 msgid "Some people can reply" msgstr "" @@ -7871,12 +7871,12 @@ msgid "Suggestive" msgstr "" -#: src/screens/Settings/AppIconSettings/useAppIconSets.ts:60 +#: src/screens/Settings/AppIconSettings/useAppIconSets.ts:72 msgctxt "Name of app icon variant" msgid "Sunrise" msgstr "" -#: src/screens/Settings/AppIconSettings/useAppIconSets.ts:70 +#: src/screens/Settings/AppIconSettings/useAppIconSets.ts:86 msgctxt "Name of app icon variant" msgid "Sunset" msgstr "" @@ -8165,7 +8165,7 @@ msgstr "" #: src/screens/Search/Explore.tsx:990 -#: src/view/com/posts/PostFeed.tsx:657 +#: src/view/com/posts/PostFeed.tsx:656 msgid "There was an issue fetching posts. Tap here to try again." msgstr "" @@ -8186,7 +8186,7 @@ msgid "There was an issue fetching your service info" msgstr "" -#: src/view/com/posts/PostFeedErrorMessage.tsx:145 +#: src/view/com/posts/PostFeedErrorMessage.tsx:149 msgid "There was an issue removing this feed. Please check your internet connection and try again." msgstr "" @@ -8295,7 +8295,7 @@ msgid "This content is not available because one of the users involved has blocked the other." msgstr "" -#: src/view/com/posts/PostFeedErrorMessage.tsx:114 +#: src/view/com/posts/PostFeedErrorMessage.tsx:118 msgid "This content is not viewable without a Bluesky account." msgstr "" @@ -8319,7 +8319,7 @@ msgid "This feature is not available while using an App Password. Please sign in with your main password." msgstr "" -#: src/view/com/posts/PostFeedErrorMessage.tsx:120 +#: src/view/com/posts/PostFeedErrorMessage.tsx:124 msgid "This feed is currently receiving high traffic and is temporarily unavailable. Please try again later." msgstr "" @@ -8387,7 +8387,7 @@ msgid "This post claims to have been created on <0>{0}, but was first seen by Bluesky on <1>{1}." msgstr "" -#: src/components/WhoCanReply.tsx:217 +#: src/components/WhoCanReply.tsx:223 msgid "This post has an unknown type of threadgate on it. Your app may be out of date." msgstr "" @@ -8558,8 +8558,8 @@ msgid "Topic" msgstr "" -#: src/components/dms/MessageContextMenu.tsx:143 -#: src/components/dms/MessageContextMenu.tsx:145 +#: src/components/dms/MessageContextMenu.tsx:142 +#: src/components/dms/MessageContextMenu.tsx:144 #: src/components/PostControls/PostMenu/PostMenuItems.tsx:444 #: src/components/PostControls/PostMenu/PostMenuItems.tsx:446 #: src/screens/PostThread/components/ThreadItemAnchor.tsx:567 @@ -8984,11 +8984,11 @@ msgid "Username or email address" msgstr "" -#: src/components/WhoCanReply.tsx:280 +#: src/components/WhoCanReply.tsx:286 msgid "users followed by <0>@{0}" msgstr "" -#: src/components/WhoCanReply.tsx:267 +#: src/components/WhoCanReply.tsx:273 msgid "users following <0>@{0}" msgstr "" @@ -9188,7 +9188,7 @@ #: src/components/ProfileHoverCard/index.web.tsx:464 #: src/components/ProfileHoverCard/index.web.tsx:484 #: src/components/ProfileHoverCard/index.web.tsx:511 -#: src/view/com/posts/PostFeedErrorMessage.tsx:175 +#: src/view/com/posts/PostFeedErrorMessage.tsx:179 #: src/view/com/util/PostMeta.tsx:91 #: src/view/com/util/PostMeta.tsx:126 msgid "View profile" @@ -9416,11 +9416,11 @@ msgid "Which languages would you like to see in your algorithmic feeds?" msgstr "" -#: src/components/WhoCanReply.tsx:183 +#: src/components/WhoCanReply.tsx:189 msgid "Who can interact with this post?" msgstr "" -#: src/components/WhoCanReply.tsx:91 +#: src/components/WhoCanReply.tsx:97 msgid "Who can reply" msgstr "" diff --git a/src/screens/Profile/Header/ProfileHeaderLabeler.tsx b/src/screens/Profile/Header/ProfileHeaderLabeler.tsx --- a/src/screens/Profile/Header/ProfileHeaderLabeler.tsx +++ b/src/screens/Profile/Header/ProfileHeaderLabeler.tsx @@ -214,8 +214,8 @@ ? t.palette.contrast_50 : t.palette.contrast_25 : state.hovered || state.pressed - ? tokens.color.temp_purple_dark - : tokens.color.temp_purple, + ? tokens.color.temp_purple_dark + : tokens.color.temp_purple, }, ]}> { - return require(`../../../../assets/app-icons/ios_icon_default_light.png`) + return require( + `../../../../assets/app-icons/ios_icon_default_light.png`, + ) }, androidImage: () => { - return require(`../../../../assets/app-icons/android_icon_default_light.png`) + return require( + `../../../../assets/app-icons/android_icon_default_light.png`, + ) }, }, { id: 'default_dark', name: _(msg({context: 'Name of app icon variant', message: 'Dark'})), iosImage: () => { - return require(`../../../../assets/app-icons/ios_icon_default_dark.png`) + return require( + `../../../../assets/app-icons/ios_icon_default_dark.png`, + ) }, androidImage: () => { - return require(`../../../../assets/app-icons/android_icon_default_dark.png`) + return require( + `../../../../assets/app-icons/android_icon_default_dark.png`, + ) }, }, ] satisfies AppIconSet[] diff --git a/src/screens/Settings/components/ChangeHandleDialog.tsx b/src/screens/Settings/components/ChangeHandleDialog.tsx --- a/src/screens/Settings/components/ChangeHandleDialog.tsx +++ b/src/screens/Settings/components/ChangeHandleDialog.tsx @@ -525,8 +525,8 @@ isVerified ? _(msg`Update to ${domain}`) : dnsPanel - ? _(msg`Verify DNS Record`) - : _(msg`Verify Text File`) + ? _(msg`Verify DNS Record`) + : _(msg`Verify Text File`) } variant="solid" size="large" diff --git a/src/state/queries/notifications/settings.ts b/src/state/queries/notifications/settings.ts --- a/src/state/queries/notifications/settings.ts +++ b/src/state/queries/notifications/settings.ts @@ -36,9 +36,8 @@ mutationFn: async ( update: Partial, ) => { - const response = await agent.app.bsky.notification.putPreferencesV2( - update, - ) + const response = + await agent.app.bsky.notification.putPreferencesV2(update) return response.data.preferences }, onMutate: update => { diff --git a/src/state/queries/notifications/unread.tsx b/src/state/queries/notifications/unread.tsx --- a/src/state/queries/notifications/unread.tsx +++ b/src/state/queries/notifications/unread.tsx @@ -15,7 +15,7 @@ import {useModerationOpts} from '../../preferences/moderation-opts' import {truncateAndInvalidate} from '../util' import {RQKEY as RQKEY_NOTIFS} from './feed' -import {CachedFeedPage, FeedPage} from './types' +import {type CachedFeedPage, type FeedPage} from './types' import {fetchPage} from './util' const UPDATE_INTERVAL = 30 * 1e3 // 30sec @@ -96,8 +96,8 @@ data.event === '30+' ? 30 : data.event === '' - ? 0 - : parseInt(data.event, 10) || 1, + ? 0 + : parseInt(data.event, 10) || 1, } setNumUnread(data.event) } @@ -167,8 +167,8 @@ unreadCount >= 30 ? '30+' : unreadCount === 0 - ? '' - : String(unreadCount) + ? '' + : String(unreadCount) // track last sync const now = new Date() diff --git a/src/state/queries/usePostThread/index.ts b/src/state/queries/usePostThread/index.ts --- a/src/state/queries/usePostThread/index.ts +++ b/src/state/queries/usePostThread/index.ts @@ -52,8 +52,8 @@ return view === 'linear' ? LINEAR_VIEW_BELOW : isWeb && gtPhone - ? TREE_VIEW_BELOW_DESKTOP - : TREE_VIEW_BELOW + ? TREE_VIEW_BELOW_DESKTOP + : TREE_VIEW_BELOW }, [view, gtPhone]) const postThreadQueryKey = createPostThreadQueryKey({ diff --git a/src/state/queries/usePostThread/traversal.ts b/src/state/queries/usePostThread/traversal.ts --- a/src/state/queries/usePostThread/traversal.ts +++ b/src/state/queries/usePostThread/traversal.ts @@ -444,7 +444,7 @@ const anchorPost = items.at(0) const hasAnchorFromCache = anchorPost && anchorPost.type === 'threadPost' const skeletonReplies = hasAnchorFromCache - ? anchorPost.value.post.replyCount ?? 4 + ? (anchorPost.value.post.replyCount ?? 4) : 4 if (!items.length) { diff --git a/src/view/com/composer/Composer.tsx b/src/view/com/composer/Composer.tsx --- a/src/view/com/composer/Composer.tsx +++ b/src/view/com/composer/Composer.tsx @@ -518,8 +518,8 @@ thread.posts.length > 1 ? _(msg`Your posts have been published`) : replyTo - ? _(msg`Your reply has been published`) - : _(msg`Your post has been published`), + ? _(msg`Your reply has been published`) + : _(msg`Your post has been published`), ) }, [ _, @@ -1000,20 +1000,20 @@ }), ) : isThread - ? _( - msg({ - message: 'Publish posts', - comment: - 'Accessibility label for button to publish multiple posts in a thread', - }), - ) - : _( - msg({ - message: 'Publish post', - comment: - 'Accessibility label for button to publish a single post', - }), - ) + ? _( + msg({ + message: 'Publish posts', + comment: + 'Accessibility label for button to publish multiple posts in a thread', + }), + ) + : _( + msg({ + message: 'Publish post', + comment: + 'Accessibility label for button to publish a single post', + }), + ) } variant="solid" color="primary" diff --git a/src/view/com/lightbox/Lightbox.web.tsx b/src/view/com/lightbox/Lightbox.web.tsx --- a/src/view/com/lightbox/Lightbox.web.tsx +++ b/src/view/com/lightbox/Lightbox.web.tsx @@ -1,17 +1,17 @@ import React, {useCallback, useEffect, useState} from 'react' import { Image, - ImageStyle, + type ImageStyle, Pressable, StyleSheet, TouchableOpacity, TouchableWithoutFeedback, View, - ViewStyle, + type ViewStyle, } from 'react-native' import { FontAwesomeIcon, - FontAwesomeIconStyle, + type FontAwesomeIconStyle, } from '@fortawesome/react-native-fontawesome' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' @@ -21,7 +21,7 @@ import {colors, s} from '#/lib/styles' import {useLightbox, useLightboxControls} from '#/state/lightbox' import {Text} from '../util/text/Text' -import {ImageSource} from './ImageViewing/@types' +import {type ImageSource} from './ImageViewing/@types' import ImageDefaultHeader from './ImageViewing/components/ImageDefaultHeader' export function Lightbox() { @@ -121,8 +121,8 @@ img.type === 'circle-avi' ? '50%' : img.type === 'rect-avi' - ? '10%' - : 0, + ? '10%' + : 0, } as ImageStyle } alt={img.alt} diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx --- a/src/view/com/post-thread/PostThreadItem.tsx +++ b/src/view/com/post-thread/PostThreadItem.tsx @@ -630,8 +630,8 @@ showChildReplyLine && !isThreadedChild ? 0 : isThreadedChildAdjacentBot - ? 4 - : 8, + ? 4 + : 8, }, ]}> {/* If we are in threaded mode, the avatar is rendered in PostMeta */} diff --git a/src/view/com/posts/PostFeedErrorMessage.tsx b/src/view/com/posts/PostFeedErrorMessage.tsx --- a/src/view/com/posts/PostFeedErrorMessage.tsx +++ b/src/view/com/posts/PostFeedErrorMessage.tsx @@ -1,15 +1,19 @@ import React from 'react' import {View} from 'react-native' -import {AppBskyActorDefs, AppBskyFeedGetAuthorFeed, AtUri} from '@atproto/api' +import { + type AppBskyActorDefs, + AppBskyFeedGetAuthorFeed, + AtUri, +} from '@atproto/api' import {msg as msgLingui, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useNavigation} from '@react-navigation/native' import {usePalette} from '#/lib/hooks/usePalette' -import {NavigationProp} from '#/lib/routes/types' +import {type NavigationProp} from '#/lib/routes/types' import {cleanError} from '#/lib/strings/errors' import {logger} from '#/logger' -import {FeedDescriptor} from '#/state/queries/post-feed' +import {type FeedDescriptor} from '#/state/queries/post-feed' import {useRemoveFeedMutation} from '#/state/queries/preferences' import * as Prompt from '#/components/Prompt' import {EmptyState} from '../util/EmptyState' @@ -119,7 +123,7 @@ [KnownError.FeedTooManyRequests]: _l( msgLingui`This feed is currently receiving high traffic and is temporarily unavailable. Please try again later.`, ), - }[knownError]), + })[knownError], [_l, knownError], ) const [_, uri] = feedDesc.split('|') diff --git a/src/view/com/profile/ProfileMenu.tsx b/src/view/com/profile/ProfileMenu.tsx --- a/src/view/com/profile/ProfileMenu.tsx +++ b/src/view/com/profile/ProfileMenu.tsx @@ -495,12 +495,12 @@ msg`The account will be able to interact with you after unblocking.`, ) : profile.associated?.labeler - ? _( - msg`Blocking will not prevent labels from being applied on your account, but it will stop this account from replying in your threads or interacting with you.`, - ) - : _( - msg`Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you.`, - ) + ? _( + msg`Blocking will not prevent labels from being applied on your account, but it will stop this account from replying in your threads or interacting with you.`, + ) + : _( + msg`Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you.`, + ) } onConfirm={blockAccount} confirmButtonCta={ diff --git a/src/view/com/util/List.web.tsx b/src/view/com/util/List.web.tsx --- a/src/view/com/util/List.web.tsx +++ b/src/view/com/util/List.web.tsx @@ -1,6 +1,11 @@ import React, {isValidElement, memo, startTransition, useRef} from 'react' -import {FlatListProps, StyleSheet, View, ViewProps} from 'react-native' -import {ReanimatedScrollEvent} from 'react-native-reanimated/lib/typescript/hook/commonTypes' +import { + type FlatListProps, + StyleSheet, + View, + type ViewProps, +} from 'react-native' +import {type ReanimatedScrollEvent} from 'react-native-reanimated/lib/typescript/hook/commonTypes' import {batchedUpdates} from '#/lib/batchedUpdates' import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback' @@ -205,7 +210,7 @@ behavior: animated ? 'smooth' : 'instant', }) }, - } as any), // TODO: Better types. + }) as any, // TODO: Better types. [getScrollableNode], ) diff --git a/src/view/com/composer/photos/Gallery.tsx b/src/view/com/composer/photos/Gallery.tsx --- a/src/view/com/composer/photos/Gallery.tsx +++ b/src/view/com/composer/photos/Gallery.tsx @@ -1,12 +1,12 @@ import React from 'react' import { - ImageStyle, + type ImageStyle, Keyboard, - LayoutChangeEvent, + type LayoutChangeEvent, StyleSheet, TouchableOpacity, View, - ViewStyle, + type ViewStyle, } from 'react-native' import {Image} from 'expo-image' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' @@ -14,14 +14,14 @@ import {useLingui} from '@lingui/react' import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' -import {Dimensions} from '#/lib/media/types' +import {type Dimensions} from '#/lib/media/types' import {colors, s} from '#/lib/styles' import {isNative} from '#/platform/detection' -import {ComposerImage, cropImage} from '#/state/gallery' +import {type ComposerImage, cropImage} from '#/state/gallery' import {Text} from '#/view/com/util/text/Text' import {useTheme} from '#/alf' import * as Dialog from '#/components/Dialog' -import {PostAction} from '../state/composer' +import {type PostAction} from '../state/composer' import {EditImageDialog} from './EditImageDialog' import {ImageAltTextDialog} from './ImageAltTextDialog' @@ -74,8 +74,8 @@ altTextControlStyle: isOverflow ? {left: 4, bottom: 4} : !isMobile && images.length < 3 - ? {left: 8, top: 8} - : {left: 4, top: 4}, + ? {left: 8, top: 8} + : {left: 4, top: 4}, imageControlsStyle: { display: 'flex' as const, flexDirection: 'row' as const, @@ -83,8 +83,8 @@ ...(isOverflow ? {top: 4, right: 4, gap: 4} : !isMobile && images.length < 3 - ? {top: 8, right: 8, gap: 8} - : {top: 4, right: 4, gap: 4}), + ? {top: 8, right: 8, gap: 8} + : {top: 4, right: 4, gap: 4}), zIndex: 1, }, imageStyle: { diff --git a/src/view/com/composer/state/composer.ts b/src/view/com/composer/state/composer.ts --- a/src/view/com/composer/state/composer.ts +++ b/src/view/com/composer/state/composer.ts @@ -1,13 +1,13 @@ -import {ImagePickerAsset} from 'expo-image-picker' +import {type ImagePickerAsset} from 'expo-image-picker' import { - AppBskyFeedPostgate, + type AppBskyFeedPostgate, AppBskyRichtextFacet, - BskyPreferences, + type BskyPreferences, RichText, } from '@atproto/api' import {nanoid} from 'nanoid/non-secure' -import {SelfLabel} from '#/lib/moderation' +import {type SelfLabel} from '#/lib/moderation' import {insertMentionAt} from '#/lib/strings/mention-manip' import {shortenLinks} from '#/lib/strings/rich-text-manip' import { @@ -15,17 +15,22 @@ postUriToRelativePath, toBskyAppUrl, } from '#/lib/strings/url-helpers' -import {ComposerImage, createInitialImages} from '#/state/gallery' +import {type ComposerImage, createInitialImages} from '#/state/gallery' import {createPostgateRecord} from '#/state/queries/postgate/util' -import {Gif} from '#/state/queries/tenor' +import {type Gif} from '#/state/queries/tenor' import {threadgateRecordToAllowUISetting} from '#/state/queries/threadgate' -import {ThreadgateAllowUISetting} from '#/state/queries/threadgate' -import {ComposerOpts} from '#/state/shell/composer' +import {type ThreadgateAllowUISetting} from '#/state/queries/threadgate' +import {type ComposerOpts} from '#/state/shell/composer' import { - LinkFacetMatch, + type LinkFacetMatch, suggestLinkCardUri, } from '#/view/com/composer/text-input/text-input-util' -import {createVideoState, VideoAction, videoReducer, VideoState} from './video' +import { + createVideoState, + type VideoAction, + videoReducer, + type VideoState, +} from './video' type ImagesMedia = { type: 'images' @@ -514,12 +519,12 @@ text: initText ? initText : initMention - ? insertMentionAt( - `@${initMention}`, - initMention.length + 1, - `${initMention}`, - ) - : '', + ? insertMentionAt( + `@${initMention}`, + initMention.length + 1, + `${initMention}`, + ) + : '', }) let link: Link | undefined diff --git a/src/components/dialogs/EmailDialog/screens/Manage2FA/Disable.tsx b/src/components/dialogs/EmailDialog/screens/Manage2FA/Disable.tsx --- a/src/components/dialogs/EmailDialog/screens/Manage2FA/Disable.tsx +++ b/src/components/dialogs/EmailDialog/screens/Manage2FA/Disable.tsx @@ -185,8 +185,8 @@ state.emailStatus === 'pending' ? Loader : state.emailStatus === 'success' - ? Check - : Envelope + ? Check + : Envelope } /> diff --git a/src/components/dialogs/EmailDialog/screens/Manage2FA/Enable.tsx b/src/components/dialogs/EmailDialog/screens/Manage2FA/Enable.tsx --- a/src/components/dialogs/EmailDialog/screens/Manage2FA/Enable.tsx +++ b/src/components/dialogs/EmailDialog/screens/Manage2FA/Enable.tsx @@ -116,8 +116,8 @@ state.status === 'pending' ? Loader : state.status === 'success' - ? Check - : ShieldIcon + ? Check + : ShieldIcon } /> diff --git a/src/view/com/composer/text-input/web/Autocomplete.tsx b/src/view/com/composer/text-input/web/Autocomplete.tsx --- a/src/view/com/composer/text-input/web/Autocomplete.tsx +++ b/src/view/com/composer/text-input/web/Autocomplete.tsx @@ -209,8 +209,8 @@ itemIndex === 0 ? styles.firstMention : itemIndex === totalItems - 1 - ? styles.lastMention - : undefined, + ? styles.lastMention + : undefined, ]} onPress={onPress} accessibilityRole="button"> diff --git a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VideoControls.tsx b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VideoControls.tsx --- a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VideoControls.tsx +++ b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/web-controls/VideoControls.tsx @@ -317,8 +317,8 @@ !focused ? msg`Unmute video` : playing - ? msg`Pause video` - : msg`Play video`, + ? msg`Pause video` + : msg`Play video`, )} accessibilityHint="" style={[