diff --git a/eslint-suppressions.json b/eslint-suppressions.json
index 152355c62a..d8140cdf54 100644
--- a/eslint-suppressions.json
+++ b/eslint-suppressions.json
@@ -927,11 +927,6 @@
"count": 1
}
},
- "src/lib/hooks/useTabFocusEffect.ts": {
- "react-hooks/set-state-in-effect": {
- "count": 1
- }
- },
"src/lib/hooks/useToggleMutationQueue.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 2
@@ -1073,17 +1068,6 @@
"count": 1
}
},
- "src/screens/Bookmarks/index.tsx": {
- "@typescript-eslint/no-explicit-any": {
- "count": 1
- },
- "@typescript-eslint/no-misused-promises": {
- "count": 3
- },
- "@typescript-eslint/no-unsafe-member-access": {
- "count": 2
- }
- },
"src/screens/Deactivated.tsx": {
"@typescript-eslint/no-explicit-any": {
"count": 1
@@ -2291,14 +2275,6 @@
"count": 3
}
},
- "src/view/com/util/ViewSelector.tsx": {
- "@typescript-eslint/no-explicit-any": {
- "count": 6
- },
- "@typescript-eslint/no-unsafe-member-access": {
- "count": 1
- }
- },
"src/view/com/util/Views.tsx": {
"@typescript-eslint/no-explicit-any": {
"count": 1
@@ -2314,14 +2290,6 @@
"count": 1
}
},
- "src/view/screens/Debug.tsx": {
- "@typescript-eslint/no-explicit-any": {
- "count": 1
- },
- "@typescript-eslint/no-unsafe-member-access": {
- "count": 4
- }
- },
"src/view/screens/Feeds.tsx": {
"@typescript-eslint/no-floating-promises": {
"count": 3
diff --git a/src/components/forms/InputGroup.tsx b/src/components/forms/InputGroup.tsx
deleted file mode 100644
index aabe7e5f20..0000000000
--- a/src/components/forms/InputGroup.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import {Children, cloneElement, Fragment, isValidElement} from 'react'
-import {View} from 'react-native'
-
-import {atoms, useTheme} from '#/alf'
-
-/**
- * NOT FINISHED, just here as a reference
- */
-export function InputGroup(props: React.PropsWithChildren<{}>) {
- const t = useTheme()
- const children = Children.toArray(props.children)
- const total = children.length
- return (
-
- {children.map((child, i) => {
- return isValidElement(child) ? (
-
- {i > 0 ? (
-
- ) : null}
- {cloneElement(child, {
- // @ts-ignore
- style: [
- // @ts-ignore
- ...(Array.isArray(child.props?.style)
- ? // @ts-ignore
- child.props.style
- : // @ts-ignore
- [child.props.style || {}]),
- {
- borderTopLeftRadius: i > 0 ? 0 : undefined,
- borderTopRightRadius: i > 0 ? 0 : undefined,
- borderBottomLeftRadius: i < total - 1 ? 0 : undefined,
- borderBottomRightRadius: i < total - 1 ? 0 : undefined,
- borderBottomWidth: i < total - 1 ? 0 : undefined,
- },
- ],
- })}
-
- ) : null
- })}
-
- )
-}
diff --git a/src/features/liveEvents/components/LiveEventFeedOptionsMenu.tsx b/src/features/liveEvents/components/LiveEventFeedOptionsMenu.tsx
deleted file mode 100644
index c01a7febc4..0000000000
--- a/src/features/liveEvents/components/LiveEventFeedOptionsMenu.tsx
+++ /dev/null
@@ -1,170 +0,0 @@
-import {View} from 'react-native'
-import {msg} from '@lingui/core/macro'
-import {useLingui} from '@lingui/react'
-import {Trans} from '@lingui/react/macro'
-
-import {useCleanError} from '#/lib/hooks/useCleanError'
-import {atoms as a, web} from '#/alf'
-import {Admonition} from '#/components/Admonition'
-import {Button, ButtonIcon, ButtonText} from '#/components/Button'
-import * as Dialog from '#/components/Dialog'
-import {Loader} from '#/components/Loader'
-import * as Toast from '#/components/Toast'
-import {Span, Text} from '#/components/Typography'
-import {IS_NATIVE} from '#/env'
-import {useUpdateLiveEventPreferences} from '#/features/liveEvents/preferences'
-import {
- type LiveEventFeed,
- type LiveEventFeedMetricContext,
-} from '#/features/liveEvents/types'
-
-export {useDialogControl} from '#/components/Dialog'
-
-export function LiveEventFeedOptionsMenu({
- control,
- feed,
- metricContext,
-}: {
- control: Dialog.DialogControlProps
- feed: LiveEventFeed
- metricContext: LiveEventFeedMetricContext
-}) {
- const {_} = useLingui()
- return (
-
-
-
-
-
-
-
- )
-}
-
-function Inner({
- control,
- feed,
- metricContext,
-}: {
- control: Dialog.DialogControlProps
- feed: LiveEventFeed
- metricContext: LiveEventFeedMetricContext
-}) {
- const {_} = useLingui()
- const {
- isPending,
- mutate: update,
- error: rawError,
- variables,
- } = useUpdateLiveEventPreferences({
- feed,
- metricContext,
- onUpdateSuccess({undoAction}) {
- Toast.show(
-
-
-
- Your live event preferences have been updated.
-
- {undoAction && (
- {
- if (undoAction) {
- update(undoAction)
- }
- }}>
- Undo
-
- )}
- ,
- {type: 'success'},
- )
-
- /*
- * If there is no `undoAction`, it means that the action was already
- * undone, and therefore the menu would have been closed prior to the
- * undo happening.
- */
- if (undoAction) {
- control.close()
- }
- },
- })
- const cleanError = useCleanError()
- const error = rawError ? cleanError(rawError) : undefined
-
- const isHidingFeed = variables?.type === 'hideFeed' && isPending
- const isHidingAllFeeds = variables?.type === 'toggleHideAllFeeds' && isPending
-
- return (
-
-
-
- Live event options
-
-
-
-
- Live events appear occasionally when something exciting is
- happening. If you'd like, you can hide this particular event, or all
- events for this placement in your app interface.
-
-
-
-
-
- If you choose to hide all events, you can always re-enable them from{' '}
- Settings → Content & Media.
-
-
-
-
-
-
-
- {IS_NATIVE && (
-
- )}
-
-
- {error && (
-
- {error.clean || error.raw || _(msg`An unknown error occurred.`)}
-
- )}
-
- )
-}
diff --git a/src/features/liveEvents/components/LiveEventFeedsSettingsToggle.tsx b/src/features/liveEvents/components/LiveEventFeedsSettingsToggle.tsx
deleted file mode 100644
index f22655063a..0000000000
--- a/src/features/liveEvents/components/LiveEventFeedsSettingsToggle.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-import {msg} from '@lingui/core/macro'
-import {useLingui} from '@lingui/react'
-import {Trans} from '@lingui/react/macro'
-
-import * as SettingsList from '#/screens/Settings/components/SettingsList'
-import * as Toggle from '#/components/forms/Toggle'
-import {Live_Stroke2_Corner0_Rounded as LiveIcon} from '#/components/icons/Live'
-import {
- useLiveEventPreferences,
- useUpdateLiveEventPreferences,
-} from '#/features/liveEvents/preferences'
-
-export function LiveEventFeedsSettingsToggle() {
- const {_} = useLingui()
- const {data: prefs} = useLiveEventPreferences()
- const {
- isPending,
- data: updatedPrefs,
- mutate: update,
- } = useUpdateLiveEventPreferences({
- metricContext: 'settings',
- })
- const hideAllFeeds = !!(updatedPrefs || prefs)?.hideAllFeeds
-
- return (
- {
- if (!isPending) {
- update({type: 'toggleHideAllFeeds'})
- }
- }}>
-
-
-
- Show live events in your Discover Feed
-
-
-
-
- )
-}
diff --git a/src/lib/currency.ts b/src/lib/currency.ts
deleted file mode 100644
index 9ba97ddce9..0000000000
--- a/src/lib/currency.ts
+++ /dev/null
@@ -1,302 +0,0 @@
-import {useMemo} from 'react'
-
-import {deviceLocales} from '#/locale/deviceLocales'
-import {useLanguagePrefs} from '#/state/preferences'
-import {useGeolocation} from '#/geolocation'
-
-/**
- * From react-native-localize
- *
- * MIT License
- * Copyright (c) 2017-present, Mathieu Acthernoene
- *
- * @see https://github.com/zoontek/react-native-localize/blob/master/LICENSE
- * @see https://github.com/zoontek/react-native-localize/blob/ee5bf25e0bb8f3b8e4f3fd055f67ad46269c81ea/src/constants.ts
- */
-export const countryCodeToCurrency: Record = {
- ad: 'eur',
- ae: 'aed',
- af: 'afn',
- ag: 'xcd',
- ai: 'xcd',
- al: 'all',
- am: 'amd',
- an: 'ang',
- ao: 'aoa',
- ar: 'ars',
- as: 'usd',
- at: 'eur',
- au: 'aud',
- aw: 'awg',
- ax: 'eur',
- az: 'azn',
- ba: 'bam',
- bb: 'bbd',
- bd: 'bdt',
- be: 'eur',
- bf: 'xof',
- bg: 'bgn',
- bh: 'bhd',
- bi: 'bif',
- bj: 'xof',
- bl: 'eur',
- bm: 'bmd',
- bn: 'bnd',
- bo: 'bob',
- bq: 'usd',
- br: 'brl',
- bs: 'bsd',
- bt: 'btn',
- bv: 'nok',
- bw: 'bwp',
- by: 'byn',
- bz: 'bzd',
- ca: 'cad',
- cc: 'aud',
- cd: 'cdf',
- cf: 'xaf',
- cg: 'xaf',
- ch: 'chf',
- ci: 'xof',
- ck: 'nzd',
- cl: 'clp',
- cm: 'xaf',
- cn: 'cny',
- co: 'cop',
- cr: 'crc',
- cu: 'cup',
- cv: 'cve',
- cw: 'ang',
- cx: 'aud',
- cy: 'eur',
- cz: 'czk',
- de: 'eur',
- dj: 'djf',
- dk: 'dkk',
- dm: 'xcd',
- do: 'dop',
- dz: 'dzd',
- ec: 'usd',
- ee: 'eur',
- eg: 'egp',
- eh: 'mad',
- er: 'ern',
- es: 'eur',
- et: 'etb',
- fi: 'eur',
- fj: 'fjd',
- fk: 'fkp',
- fm: 'usd',
- fo: 'dkk',
- fr: 'eur',
- ga: 'xaf',
- gb: 'gbp',
- gd: 'xcd',
- ge: 'gel',
- gf: 'eur',
- gg: 'gbp',
- gh: 'ghs',
- gi: 'gip',
- gl: 'dkk',
- gm: 'gmd',
- gn: 'gnf',
- gp: 'eur',
- gq: 'xaf',
- gr: 'eur',
- gs: 'gbp',
- gt: 'gtq',
- gu: 'usd',
- gw: 'xof',
- gy: 'gyd',
- hk: 'hkd',
- hm: 'aud',
- hn: 'hnl',
- hr: 'hrk',
- ht: 'htg',
- hu: 'huf',
- id: 'idr',
- ie: 'eur',
- il: 'ils',
- im: 'gbp',
- in: 'inr',
- io: 'usd',
- iq: 'iqd',
- ir: 'irr',
- is: 'isk',
- it: 'eur',
- je: 'gbp',
- jm: 'jmd',
- jo: 'jod',
- jp: 'jpy',
- ke: 'kes',
- kg: 'kgs',
- kh: 'khr',
- ki: 'aud',
- km: 'kmf',
- kn: 'xcd',
- kp: 'kpw',
- kr: 'krw',
- kw: 'kwd',
- ky: 'kyd',
- kz: 'kzt',
- la: 'lak',
- lb: 'lbp',
- lc: 'xcd',
- li: 'chf',
- lk: 'lkr',
- lr: 'lrd',
- ls: 'lsl',
- lt: 'eur',
- lu: 'eur',
- lv: 'eur',
- ly: 'lyd',
- ma: 'mad',
- mc: 'eur',
- md: 'mdl',
- me: 'eur',
- mf: 'eur',
- mg: 'mga',
- mh: 'usd',
- mk: 'mkd',
- ml: 'xof',
- mm: 'mmk',
- mn: 'mnt',
- mo: 'mop',
- mp: 'usd',
- mq: 'eur',
- mr: 'mro',
- ms: 'xcd',
- mt: 'eur',
- mu: 'mur',
- mv: 'mvr',
- mw: 'mwk',
- mx: 'mxn',
- my: 'myr',
- mz: 'mzn',
- na: 'nad',
- nc: 'xpf',
- ne: 'xof',
- nf: 'aud',
- ng: 'ngn',
- ni: 'nio',
- nl: 'eur',
- no: 'nok',
- np: 'npr',
- nr: 'aud',
- nu: 'nzd',
- nz: 'nzd',
- om: 'omr',
- pa: 'pab',
- pe: 'pen',
- pf: 'xpf',
- pg: 'pgk',
- ph: 'php',
- pk: 'pkr',
- pl: 'pln',
- pm: 'eur',
- pn: 'nzd',
- pr: 'usd',
- ps: 'ils',
- pt: 'eur',
- pw: 'usd',
- py: 'pyg',
- qa: 'qar',
- re: 'eur',
- ro: 'ron',
- rs: 'rsd',
- ru: 'rub',
- rw: 'rwf',
- sa: 'sar',
- sb: 'sbd',
- sc: 'scr',
- sd: 'sdg',
- se: 'sek',
- sg: 'sgd',
- sh: 'shp',
- si: 'eur',
- sj: 'nok',
- sk: 'eur',
- sl: 'sll',
- sm: 'eur',
- sn: 'xof',
- so: 'sos',
- sr: 'srd',
- ss: 'ssp',
- st: 'std',
- sv: 'svc',
- sx: 'ang',
- sy: 'syp',
- sz: 'szl',
- tc: 'usd',
- td: 'xaf',
- tf: 'eur',
- tg: 'xof',
- th: 'thb',
- tj: 'tjs',
- tk: 'nzd',
- tl: 'usd',
- tm: 'tmt',
- tn: 'tnd',
- to: 'top',
- tr: 'try',
- tt: 'ttd',
- tv: 'aud',
- tw: 'twd',
- tz: 'tzs',
- ua: 'uah',
- ug: 'ugx',
- um: 'usd',
- us: 'usd',
- uy: 'uyu',
- uz: 'uzs',
- va: 'eur',
- vc: 'xcd',
- ve: 'vef',
- vg: 'usd',
- vi: 'usd',
- vn: 'vnd',
- vu: 'vuv',
- wf: 'xpf',
- ws: 'wst',
- ye: 'yer',
- yt: 'eur',
- za: 'zar',
- zm: 'zmw',
- zw: 'zwl',
-}
-
-/**
- * Best-guess currency formatting.
- *
- * Attempts to use `getLocales` from `expo-localization` if available,
- * otherwise falls back to the `persisted.appLanguage` setting, and geolocation
- * API for region.
- */
-export function useFormatCurrency(
- options?: Parameters[1],
-) {
- const geolocation = useGeolocation()
- const {appLanguage} = useLanguagePrefs()
- return useMemo(() => {
- const locale = deviceLocales.at(0)
- const languageTag = locale?.languageTag || appLanguage || 'en-US'
- const countryCode = (
- locale?.regionCode ||
- geolocation?.countryCode ||
- 'us'
- ).toLowerCase()
- const currency = countryCodeToCurrency[countryCode] || 'usd'
- const format = new Intl.NumberFormat(languageTag, {
- ...(options || {}),
- style: 'currency',
- currency: currency,
- }).format
-
- return {
- format,
- currency,
- countryCode,
- languageTag,
- }
- }, [geolocation, appLanguage, options])
-}
diff --git a/src/lib/custom-animations/ShrinkAndPop.ts b/src/lib/custom-animations/ShrinkAndPop.ts
deleted file mode 100644
index ea2386c14e..0000000000
--- a/src/lib/custom-animations/ShrinkAndPop.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import {withDelay, withSequence, withTiming} from 'react-native-reanimated'
-
-export function ShrinkAndPop() {
- 'worklet'
-
- const animations = {
- opacity: withDelay(125, withTiming(0, {duration: 125})),
- transform: [
- {
- scale: withSequence(
- withTiming(0.7, {duration: 75}),
- withTiming(1.1, {duration: 150}),
- ),
- },
- ],
- }
-
- const initialValues = {
- opacity: 1,
- transform: [{scale: 1}],
- }
-
- return {
- animations,
- initialValues,
- }
-}
diff --git a/src/lib/hooks/useTabFocusEffect.ts b/src/lib/hooks/useTabFocusEffect.ts
deleted file mode 100644
index a54a3af73f..0000000000
--- a/src/lib/hooks/useTabFocusEffect.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import {useEffect, useState} from 'react'
-import {useNavigation} from '@react-navigation/native'
-
-import {getTabState, TabState} from '#/lib/routes/helpers'
-
-export function useTabFocusEffect(
- tabName: string,
- cb: (isInside: boolean) => void,
-) {
- const [isInside, setIsInside] = useState(false)
-
- // get root navigator state
- let nav = useNavigation()
- while (nav.getParent()) {
- nav = nav.getParent()
- }
- const state = nav.getState()
-
- useEffect(() => {
- // check if inside
- let v = getTabState(state, tabName) !== TabState.Outside
- if (v !== isInside) {
- // fire
- setIsInside(v)
- cb(v)
- }
- }, [state, isInside, setIsInside, tabName, cb])
-}
diff --git a/src/lib/hooks/useTimer.ts b/src/lib/hooks/useTimer.ts
deleted file mode 100644
index 8793ac5475..0000000000
--- a/src/lib/hooks/useTimer.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import {useCallback, useEffect, useRef} from 'react'
-
-/**
- * Helper hook to run persistent timers on views
- */
-export function useTimer(time: number, handler: () => void) {
- const timer = useRef(undefined)
-
- // function to restart the timer
- const reset = useCallback(() => {
- if (timer.current) {
- clearTimeout(timer.current)
- }
- timer.current = setTimeout(handler, time)
- }, [time, timer, handler])
-
- // function to cancel the timer
- const cancel = useCallback(() => {
- if (timer.current) {
- clearTimeout(timer.current)
- timer.current = undefined
- }
- }, [timer])
-
- // start the timer immediately
- useEffect(() => {
- reset()
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [])
-
- return [reset, cancel]
-}
diff --git a/src/lib/media/avatar-generator.tsx b/src/lib/media/avatar-generator.tsx
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/src/screens/Bookmarks/index.tsx b/src/screens/Bookmarks.tsx
similarity index 94%
rename from src/screens/Bookmarks/index.tsx
rename to src/screens/Bookmarks.tsx
index 16d25dcd05..fdeb91777c 100644
--- a/src/screens/Bookmarks/index.tsx
+++ b/src/screens/Bookmarks.tsx
@@ -14,13 +14,13 @@ import {
useNavigation,
} from '@react-navigation/native'
-import {useCleanError} from '#/lib/hooks/useCleanError'
import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender'
import {usePostViewTracking} from '#/lib/hooks/usePostViewTracking'
import {
type CommonNavigatorParams,
type NativeStackScreenProps,
} from '#/lib/routes/types'
+import {cleanError} from '#/lib/strings/errors'
import {useBookmarkMutation} from '#/state/queries/bookmarks/useBookmarkMutation'
import {useBookmarksQuery} from '#/state/queries/bookmarks/useBookmarksQuery'
import {Post} from '#/view/com/post/Post'
@@ -92,7 +92,6 @@ type ListItem =
function BookmarksInner() {
const initialNumToRender = useInitialNumToRender()
- const cleanError = useCleanError()
const [isPTRing, setIsPTRing] = useState(false)
const trackPostView = usePostViewTracking('Bookmarks')
const {
@@ -104,10 +103,6 @@ function BookmarksInner() {
error,
refetch,
} = useBookmarksQuery()
- const cleanedError = useMemo(() => {
- const {raw, clean} = cleanError(error)
- return clean || raw
- }, [error, cleanError])
const onRefresh = useCallback(async () => {
setIsPTRing(true)
@@ -174,10 +169,10 @@ function BookmarksInner() {
renderItem={renderItem}
keyExtractor={keyExtractor}
refreshing={isPTRing}
- onRefresh={onRefresh}
- onEndReached={onEndReached}
+ onRefresh={() => void onRefresh()}
+ onEndReached={() => void onEndReached()}
onEndReachedThreshold={4}
- onItemSeen={item => {
+ onItemSeen={(item: ListItem) => {
if (item.type === 'bookmark') {
trackPostView(item.bookmark.item)
}
@@ -185,7 +180,7 @@ function BookmarksInner() {
ListFooterComponent={
@@ -209,7 +204,6 @@ function BookmarkNotFound({
const t = useTheme()
const {_} = useLingui()
const {mutateAsync: bookmark} = useBookmarkMutation()
- const cleanError = useCleanError()
const remove = async () => {
try {
@@ -217,9 +211,8 @@ function BookmarkNotFound({
toast.show(_(msg`Removed from saved posts`), {
type: 'info',
})
- } catch (e: any) {
- const {raw, clean} = cleanError(e)
- toast.show(clean || raw || e, {
+ } catch (err) {
+ toast.show(cleanError(err), {
type: 'error',
})
}
@@ -259,7 +252,7 @@ function BookmarkNotFound({
label={_(msg`Remove from saved posts`)}
size="tiny"
color="secondary"
- onPress={remove}>
+ onPress={() => void remove()}>
Remove
diff --git a/src/screens/Bookmarks/components/EmptyState.tsx b/src/screens/Bookmarks/components/EmptyState.tsx
deleted file mode 100644
index cf70e7385c..0000000000
--- a/src/screens/Bookmarks/components/EmptyState.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-import {View} from 'react-native'
-import {msg} from '@lingui/core/macro'
-import {useLingui} from '@lingui/react'
-import {Trans} from '@lingui/react/macro'
-
-import {atoms as a, useTheme} from '#/alf'
-import {ButtonText} from '#/components/Button'
-import {BookmarkDeleteLarge} from '#/components/icons/Bookmark'
-import {Link} from '#/components/Link'
-import {Text} from '#/components/Typography'
-
-export function EmptyState() {
- const t = useTheme()
- const {_} = useLingui()
-
- return (
-
-
-
-
- Nothing saved yet
-
-
-
-
-
-
- Go home
-
-
-
-
-
- )
-}
diff --git a/src/state/queries/suggested-feeds.ts b/src/state/queries/suggested-feeds.ts
deleted file mode 100644
index 9344cf628d..0000000000
--- a/src/state/queries/suggested-feeds.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import {type AppBskyFeedGetSuggestedFeeds} from '@atproto/api'
-import {
- type InfiniteData,
- type QueryKey,
- useInfiniteQuery,
-} from '@tanstack/react-query'
-
-import {STALE} from '#/state/queries'
-import {useAgent} from '#/state/session'
-
-const suggestedFeedsQueryKeyRoot = 'suggestedFeeds'
-export const suggestedFeedsQueryKey = [suggestedFeedsQueryKeyRoot]
-
-export function useSuggestedFeedsQuery() {
- const agent = useAgent()
- return useInfiniteQuery<
- AppBskyFeedGetSuggestedFeeds.OutputSchema,
- Error,
- InfiniteData,
- QueryKey,
- string | undefined
- >({
- staleTime: STALE.HOURS.ONE,
- queryKey: suggestedFeedsQueryKey,
- queryFn: async ({pageParam}) => {
- const res = await agent.app.bsky.feed.getSuggestedFeeds({
- limit: 10,
- cursor: pageParam,
- })
- return res.data
- },
- initialPageParam: undefined,
- getNextPageParam: lastPage => lastPage.cursor,
- })
-}
diff --git a/src/state/shell/post-progress.tsx b/src/state/shell/post-progress.tsx
deleted file mode 100644
index 894e479cce..0000000000
--- a/src/state/shell/post-progress.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import {createContext, useContext} from 'react'
-
-interface PostProgressState {
- progress: number
- status: 'pending' | 'success' | 'error' | 'idle'
- error?: string
-}
-
-const PostProgressContext = createContext({
- progress: 0,
- status: 'idle',
-})
-PostProgressContext.displayName = 'PostProgressContext'
-
-export function Provider() {}
-
-export function usePostProgress() {
- return useContext(PostProgressContext)
-}
diff --git a/src/state/shell/starter-pack.tsx b/src/state/shell/starter-pack.tsx
deleted file mode 100644
index 149be21c87..0000000000
--- a/src/state/shell/starter-pack.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-import {createContext, useContext, useState} from 'react'
-
-type StateContext =
- | {
- uri: string
- isClip?: boolean
- }
- | undefined
-type SetContext = (v: StateContext) => void
-
-const stateContext = createContext(undefined)
-stateContext.displayName = 'ActiveStarterPackStateContext'
-const setContext = createContext((_: StateContext) => {})
-setContext.displayName = 'ActiveStarterPackSetContext'
-
-export function Provider({children}: {children: React.ReactNode}) {
- const [state, setState] = useState()
-
- return (
-
- {children}
-
- )
-}
-
-export const useActiveStarterPack = () => useContext(stateContext)
-export const useSetActiveStarterPack = () => useContext(setContext)
diff --git a/src/view/com/composer/KeyboardAccessory.tsx b/src/view/com/composer/KeyboardAccessory.tsx
deleted file mode 100644
index ae5a54275c..0000000000
--- a/src/view/com/composer/KeyboardAccessory.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import {View} from 'react-native'
-import {KeyboardStickyView} from 'react-native-keyboard-controller'
-import {useSafeAreaInsets} from 'react-native-safe-area-context'
-
-import {atoms as a, useTheme} from '#/alf'
-import {IS_WEB} from '#/env'
-
-export function KeyboardAccessory({children}: {children: React.ReactNode}) {
- const t = useTheme()
- const {bottom} = useSafeAreaInsets()
-
- const style = [
- a.flex_row,
- a.py_xs,
- a.pl_sm,
- a.pr_xl,
- a.align_center,
- a.border_t,
- t.atoms.border_contrast_medium,
- t.atoms.bg,
- ]
-
- // todo: when iPad support is added, it should also not use the KeyboardStickyView
- if (IS_WEB) {
- return {children}
- }
-
- return (
-
- {children}
-
- )
-}
diff --git a/src/view/com/util/ViewSelector.tsx b/src/view/com/util/ViewSelector.tsx
deleted file mode 100644
index 98d78a38cd..0000000000
--- a/src/view/com/util/ViewSelector.tsx
+++ /dev/null
@@ -1,238 +0,0 @@
-import {
- forwardRef,
- type JSX,
- useCallback,
- useEffect,
- useImperativeHandle,
- useMemo,
- useRef,
- useState,
-} from 'react'
-import {
- type NativeScrollEvent,
- type NativeSyntheticEvent,
- Pressable,
- RefreshControl,
- ScrollView,
- StyleSheet,
- View,
-} from 'react-native'
-
-import {useColorSchemeStyle} from '#/lib/hooks/useColorSchemeStyle'
-import {usePalette} from '#/lib/hooks/usePalette'
-import {clamp} from '#/lib/numbers'
-import {colors, s} from '#/lib/styles'
-import {IS_ANDROID} from '#/env'
-import {Text} from './text/Text'
-import {FlatList_INTERNAL} from './Views'
-
-const HEADER_ITEM = {_reactKey: '__header__'}
-const SELECTOR_ITEM = {_reactKey: '__selector__'}
-const STICKY_HEADER_INDICES = [1]
-
-export type ViewSelectorHandle = {
- scrollToTop: () => void
-}
-
-export const ViewSelector = forwardRef<
- ViewSelectorHandle,
- {
- sections: string[]
- items: any[]
- refreshing?: boolean
- swipeEnabled?: boolean
- renderHeader?: () => JSX.Element
- renderItem: (item: any) => JSX.Element
- ListFooterComponent?:
- | React.ComponentType
- | React.ReactElement
- | null
- | undefined
- onSelectView?: (viewIndex: number) => void
- onScroll?: (event: NativeSyntheticEvent) => void
- onRefresh?: () => void
- onEndReached?: (info: {distanceFromEnd: number}) => void
- }
->(function ViewSelectorImpl(
- {
- sections,
- items,
- refreshing,
- renderHeader,
- renderItem,
- ListFooterComponent,
- onSelectView,
- onScroll,
- onRefresh,
- onEndReached,
- },
- ref,
-) {
- const pal = usePalette('default')
- const [selectedIndex, setSelectedIndex] = useState(0)
- const flatListRef = useRef(null)
-
- // events
- // =
-
- const keyExtractor = useCallback((item: any) => item._reactKey, [])
-
- const onPressSelection = useCallback(
- (index: number) => setSelectedIndex(clamp(index, 0, sections.length)),
- [setSelectedIndex, sections],
- )
- useEffect(() => {
- onSelectView?.(selectedIndex)
- }, [selectedIndex, onSelectView])
-
- useImperativeHandle(ref, () => ({
- scrollToTop: () => {
- flatListRef.current?.scrollToOffset({offset: 0})
- },
- }))
-
- // rendering
- // =
-
- const renderItemInternal = useCallback(
- ({item}: {item: any}) => {
- if (item === HEADER_ITEM) {
- if (renderHeader) {
- return renderHeader()
- }
- return
- } else if (item === SELECTOR_ITEM) {
- return (
-
- )
- } else {
- return renderItem(item)
- }
- },
- [sections, selectedIndex, onPressSelection, renderHeader, renderItem],
- )
-
- const data = useMemo(() => [HEADER_ITEM, SELECTOR_ITEM, ...items], [items])
- return (
-
- }
- onEndReachedThreshold={0.6}
- contentContainerStyle={s.contentContainer}
- removeClippedSubviews={true}
- scrollIndicatorInsets={{right: 1}} // fixes a bug where the scroll indicator is on the middle of the screen https://github.com/bluesky-social/social-app/pull/464
- />
- )
-})
-
-export function Selector({
- selectedIndex,
- items,
- onSelect,
-}: {
- selectedIndex: number
- items: string[]
- onSelect?: (index: number) => void
-}) {
- const pal = usePalette('default')
- const borderColor = useColorSchemeStyle(
- {borderColor: colors.black},
- {borderColor: colors.white},
- )
-
- const onPressItem = (index: number) => {
- onSelect?.(index)
- }
-
- return (
-
-
-
- {items.map((item, i) => {
- const selected = i === selectedIndex
- return (
- onPressItem(i)}
- accessibilityLabel={item}
- accessibilityHint={`Selects ${item}`}
- // TODO: Modify the component API such that lint fails
- // at the invocation site as well
- >
-
-
- {item}
-
-
-
- )
- })}
-
-
-
- )
-}
-
-const styles = StyleSheet.create({
- outer: {
- flexDirection: 'row',
- paddingHorizontal: 14,
- },
- item: {
- marginRight: 14,
- paddingHorizontal: 10,
- paddingTop: 8,
- paddingBottom: 12,
- },
- itemSelected: {
- borderBottomWidth: 3,
- },
- label: {
- fontWeight: '600',
- },
- labelSelected: {
- fontWeight: '600',
- },
- underline: {
- position: 'absolute',
- height: 4,
- bottom: 0,
- },
-})
diff --git a/src/view/screens/Debug.tsx b/src/view/screens/Debug.tsx
deleted file mode 100644
index bc31b586b3..0000000000
--- a/src/view/screens/Debug.tsx
+++ /dev/null
@@ -1,387 +0,0 @@
-import {useState} from 'react'
-import {ScrollView, View} from 'react-native'
-import {msg} from '@lingui/core/macro'
-import {useLingui} from '@lingui/react'
-
-import {usePalette} from '#/lib/hooks/usePalette'
-import {
- type CommonNavigatorParams,
- type NativeStackScreenProps,
-} from '#/lib/routes/types'
-import {s} from '#/lib/styles'
-import {type PaletteColorName, ThemeProvider} from '#/lib/ThemeContext'
-import {EmptyState} from '#/view/com/util/EmptyState'
-import {ErrorMessage} from '#/view/com/util/error/ErrorMessage'
-import {ErrorScreen} from '#/view/com/util/error/ErrorScreen'
-import {Button} from '#/view/com/util/forms/Button'
-import * as LoadingPlaceholder from '#/view/com/util/LoadingPlaceholder'
-import {Text} from '#/view/com/util/text/Text'
-import {ViewHeader} from '#/view/com/util/ViewHeader'
-import {ViewSelector} from '#/view/com/util/ViewSelector'
-import {HashtagWide_Stroke1_Corner0_Rounded as HashtagWideIcon} from '#/components/icons/Hashtag'
-import * as Layout from '#/components/Layout'
-import * as Toast from '#/components/Toast'
-
-const MAIN_VIEWS = ['Base', 'Controls', 'Error', 'Notifs']
-
-export const DebugScreen = ({}: NativeStackScreenProps<
- CommonNavigatorParams,
- 'Debug'
->) => {
- const [colorScheme, setColorScheme] = useState<'light' | 'dark'>('light')
- const onToggleColorScheme = () => {
- setColorScheme(colorScheme === 'light' ? 'dark' : 'light')
- }
- return (
-
-
-
-
-
- )
-}
-
-function DebugInner({}: {
- colorScheme: 'light' | 'dark'
- onToggleColorScheme: () => void
-}) {
- const [currentView, setCurrentView] = useState(0)
- const pal = usePalette('default')
- const {_} = useLingui()
-
- const renderItem = (item: any) => {
- return (
-
- {item.currentView === 3 ? (
-
- ) : item.currentView === 2 ? (
-
- ) : item.currentView === 1 ? (
-
- ) : (
-
- )}
-
- )
- }
-
- const items = [{currentView}]
-
- return (
-
-
-
-
- )
-}
-
-function Heading({label}: {label: string}) {
- const pal = usePalette('default')
- return (
-
-
- {label}
-
-
- )
-}
-
-function BaseView() {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )
-}
-
-function ControlsView() {
- return (
-
-
-
-
-
- )
-}
-
-function ErrorView() {
- return (
-
-
- {}}
- />
-
-
-
-
-
-
-
-
- {}}
- />
-
-
- {}}
- numberOfLines={1}
- />
-
-
- )
-}
-
-function NotifsView() {
- const triggerPush = () => {
- // TODO: implement local notification for testing
- }
- const triggerToast = () => {
- Toast.show('The task has been completed')
- }
- const triggerToast2 = () => {
- Toast.show('The task has been completed successfully and with no problems')
- }
- return (
-
-
-
-
-
-
-
- )
-}
-
-function PaletteView({palette}: {palette: PaletteColorName}) {
- const defaultPal = usePalette('default')
- const pal = usePalette(palette)
- return (
-
- {palette} colors
- Light text
- Link text
- {palette !== 'default' && (
-
- Inverted text
-
- )}
-
- )
-}
-
-function TypographyView() {
- const pal = usePalette('default')
- return (
-
-
- '2xl-thin' lorem ipsum dolor
-
-
- '2xl' lorem ipsum dolor
-
-
- '2xl-medium' lorem ipsum dolor
-
-
- '2xl-bold' lorem ipsum dolor
-
-
- '2xl-heavy' lorem ipsum dolor
-
-
- 'xl-thin' lorem ipsum dolor
-
-
- 'xl' lorem ipsum dolor
-
-
- 'xl-medium' lorem ipsum dolor
-
-
- 'xl-bold' lorem ipsum dolor
-
-
- 'xl-heavy' lorem ipsum dolor
-
-
- 'lg-thin' lorem ipsum dolor
-
-
- 'lg' lorem ipsum dolor
-
-
- 'lg-medium' lorem ipsum dolor
-
-
- 'lg-bold' lorem ipsum dolor
-
-
- 'lg-heavy' lorem ipsum dolor
-
-
- 'md-thin' lorem ipsum dolor
-
-
- 'md' lorem ipsum dolor
-
-
- 'md-medium' lorem ipsum dolor
-
-
- 'md-bold' lorem ipsum dolor
-
-
- 'md-heavy' lorem ipsum dolor
-
-
- 'sm-thin' lorem ipsum dolor
-
-
- 'sm' lorem ipsum dolor
-
-
- 'sm-medium' lorem ipsum dolor
-
-
- 'sm-bold' lorem ipsum dolor
-
-
- 'sm-heavy' lorem ipsum dolor
-
-
- 'xs-thin' lorem ipsum dolor
-
-
- 'xs' lorem ipsum dolor
-
-
- 'xs-medium' lorem ipsum dolor
-
-
- 'xs-bold' lorem ipsum dolor
-
-
- 'xs-heavy' lorem ipsum dolor
-
-
-
- 'title-2xl' lorem ipsum dolor
-
-
- 'title-xl' lorem ipsum dolor
-
-
- 'title-lg' lorem ipsum dolor
-
-
- 'title' lorem ipsum dolor
-
-
- Button
-
-
- Button-lg
-
-
- )
-}
-
-function EmptyStateView() {
- const {_} = useLingui()
-
- return (
-
- )
-}
-
-function LoadingPlaceholderView() {
- return (
- <>
-
-
- >
- )
-}
-
-function ButtonsView() {
- const defaultPal = usePalette('default')
- const buttonStyles = {marginRight: 5}
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )
-}