import Button from '@components/Button' import haptics from '@components/haptics' import { HeaderLeft, HeaderRight } from '@components/Header' import Icon from '@components/Icon' import { displayMessage } from '@components/Message' import CustomText from '@components/Text' import Timeline from '@components/Timeline' import SegmentedControl from '@react-native-segmented-control/segmented-control' import { useScrollToTop } from '@react-navigation/native' import { NativeStackScreenProps } from '@react-navigation/native-stack' import apiGeneral from '@utils/api/general' import { TabPublicStackParamList } from '@utils/navigation/navigators' import { useInstanceQuery } from '@utils/queryHooks/instance' import { QueryKeyTimeline } from '@utils/queryHooks/timeline' import { getGlobalStorage, setGlobalStorage, useGlobalStorage } from '@utils/storage/actions' import { StorageGlobal } from '@utils/storage/global' import { StyleConstants } from '@utils/styles/constants' import layoutAnimation from '@utils/styles/layoutAnimation' import { isLargeDevice } from '@utils/styles/scaling' import { useTheme } from '@utils/styles/ThemeManager' import { debounce } from 'lodash' import { useCallback, useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { Dimensions, FlatList, Platform, Pressable, TextInput, View } from 'react-native' import { SceneMap, TabView } from 'react-native-tab-view' import { Placeholder, PlaceholderLine } from 'rn-placeholder' import * as DropdownMenu from 'zeego/dropdown-menu' const Explore = ({ route: { key: page } }: { route: { key: 'Explore' } }) => { const { t } = useTranslation(['common', 'componentInstance', 'screenTabs']) const { colors, mode } = useTheme() const [loading, setLoading] = useState(false) const [addingRemote, setAddingRemote] = useState(false) const [domain, setDomain] = useState('') const [domainValid, setDomainValid] = useState() const instanceQuery = useInstanceQuery({ domain, options: { enabled: false, retry: false, keepPreviousData: false, cacheTime: 1000 * 30, onError: () => setLoading(false), onSuccess: () => { if (!!remotes?.find(r => r.domain === domain)) { displayMessage({ type: 'warning', message: t('screenTabs:tabs.public.exploring.errors.existed') }) } apiGeneral({ method: 'get', domain: domain, url: 'api/v1/timelines/public', params: { local: 'true', limit: 1 } }) .then(({ body }) => { setLoading(false) if (Array.isArray(body)) { setDomainValid(true) } else { displayMessage({ type: 'danger', message: t('screenTabs:tabs.public.exploring.errors.notAvailable') }) setDomainValid(false) } }) .catch(() => { displayMessage({ type: 'danger', message: t('screenTabs:tabs.public.exploring.errors.notAvailable') }) setLoading(false) setDomainValid(false) }) } } }) const debounceFetch = useCallback( debounce(() => { setLoading(true) instanceQuery.refetch() }, 1000), [] ) const [accountActive] = useGlobalStorage.string('account.active') const [remoteActive, setRemoteActive] = useGlobalStorage.string('remote.active') const [remotes, setRemotes] = useGlobalStorage.object('remotes') const flRef = useRef(null) const queryKey: QueryKeyTimeline = [ 'Timeline', { page, ...(remoteActive && { domain: remoteActive }) } ] const info = ({ heading, content, lines, potentialWidth = 6 }: { heading: string content?: string lines?: number potentialWidth?: number }) => ( {content ? ( ) : ( Array.from({ length: lines || 1 }).map((_, index) => ( )) )} ) useScrollToTop(flRef) return ( { setDomain('') setAddingRemote(false) layoutAnimation().then(() => flRef.current?.scrollToOffset({ animated: true, offset: 0 }) ) }} /> {}} /> { setDomain(text.replace(/^http(s)?\:\/\//i, '')) setDomainValid(undefined) debounceFetch() }} autoCapitalize='none' clearButtonMode='never' keyboardType='url' textContentType='URL' onSubmitEditing={() => instanceQuery.refetch()} placeholder={' ' + t('componentInstance:server.textInput.placeholder')} placeholderTextColor={colors.secondary} returnKeyType='go' keyboardAppearance={mode} autoCorrect={false} spellCheck={false} autoFocus />