This commit is contained in:
Zhiyuan Zheng 2021-03-14 00:47:55 +01:00
parent 32a7d23dc9
commit 5fe6cd59f9
No known key found for this signature in database
GPG Key ID: 078A93AB607D85E0
12 changed files with 141 additions and 144 deletions

View File

@ -93,7 +93,7 @@ private_lane :build_ios do
) )
when "production" when "production"
prepare_appstore_ios prepare_appstore_ios
match( type: "appstore", readonly: true ) match( type: "appstore", readonly: true, include_bitcode: true )
build_ios_app( export_method: "app-store" ) build_ios_app( export_method: "app-store" )
end end
end end

View File

@ -1,3 +1,2 @@
scheme "tooot" scheme "tooot"
workspace "./ios/tooot.xcworkspace" workspace "./ios/tooot.xcworkspace"
clean true

View File

@ -73,7 +73,7 @@
"react-native-htmlview": "^0.16.0", "react-native-htmlview": "^0.16.0",
"react-native-reanimated": "^2.0.0-rc.2", "react-native-reanimated": "^2.0.0-rc.2",
"react-native-safe-area-context": "3.1.9", "react-native-safe-area-context": "3.1.9",
"react-native-screens": "~2.17.1", "react-native-screens": "~2.18.1",
"react-native-svg": "12.1.0", "react-native-svg": "12.1.0",
"react-native-swipe-list-view": "^3.2.6", "react-native-swipe-list-view": "^3.2.6",
"react-native-tab-view": "^2.15.2", "react-native-tab-view": "^2.15.2",

View File

@ -88,7 +88,7 @@ declare namespace Nav {
account: Mastodon.Account account: Mastodon.Account
initialType: 'following' | 'followers' initialType: 'following' | 'followers'
} }
'Tab-Shared-Search': undefined 'Tab-Shared-Search': { text: string | undefined }
'Tab-Shared-Toot': { 'Tab-Shared-Toot': {
toot: Mastodon.Status toot: Mastodon.Status
rootQueryKey: any rootQueryKey: any

View File

@ -60,7 +60,7 @@ const apiGeneral = async <T = unknown>({
}) })
.catch(error => { .catch(error => {
if (sentry) { if (sentry) {
Sentry.Native.captureException(error, error) Sentry.Native.captureException(error, { extra: error })
} }
if (error.response) { if (error.response) {

View File

@ -43,7 +43,10 @@ const TabLocal = React.memo(
content='Search' content='Search'
onPress={() => { onPress={() => {
analytics('search_tap', { page: 'Local' }) analytics('search_tap', { page: 'Local' })
navigation.navigate('Tab-Local', { screen: 'Tab-Shared-Search' }) navigation.navigate('Tab-Local', {
screen: 'Tab-Shared-Search',
params: { text: undefined }
})
}} }}
/> />
) )

View File

@ -3,7 +3,9 @@ import { HeaderRight } from '@components/Header'
import Timeline from '@components/Timeline' import Timeline from '@components/Timeline'
import TimelineDefault from '@components/Timeline/Default' import TimelineDefault from '@components/Timeline/Default'
import SegmentedControl from '@react-native-community/segmented-control' import SegmentedControl from '@react-native-community/segmented-control'
import { BottomTabScreenProps } from '@react-navigation/bottom-tabs'
import { useNavigation } from '@react-navigation/native' import { useNavigation } from '@react-navigation/native'
import { ScreenTabsParamList } from '@screens/Tabs'
import sharedScreens from '@screens/Tabs/Shared/sharedScreens' import sharedScreens from '@screens/Tabs/Shared/sharedScreens'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline' import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import { getInstanceActive } from '@utils/slices/instancesSlice' import { getInstanceActive } from '@utils/slices/instancesSlice'
@ -16,13 +18,17 @@ import { TabView } from 'react-native-tab-view'
import ViewPagerAdapter from 'react-native-tab-view-viewpager-adapter' import ViewPagerAdapter from 'react-native-tab-view-viewpager-adapter'
import { useSelector } from 'react-redux' import { useSelector } from 'react-redux'
export type TabPublicProps = BottomTabScreenProps<
ScreenTabsParamList,
'Tab-Public'
>
const Stack = createNativeStackNavigator<Nav.TabPublicStackParamList>() const Stack = createNativeStackNavigator<Nav.TabPublicStackParamList>()
const TabPublic = React.memo( const TabPublic = React.memo(
() => { ({ navigation }: TabPublicProps) => {
const { t, i18n } = useTranslation() const { t, i18n } = useTranslation()
const { mode } = useTheme() const { mode } = useTheme()
const navigation = useNavigation()
const instanceActive = useSelector(getInstanceActive) const instanceActive = useSelector(getInstanceActive)
const [segment, setSegment] = useState(0) const [segment, setSegment] = useState(0)
@ -64,7 +70,10 @@ const TabPublic = React.memo(
content='Search' content='Search'
onPress={() => { onPress={() => {
analytics('search_tap', { page: pages[segment].key }) analytics('search_tap', { page: pages[segment].key })
navigation.navigate('Tab-Public', { screen: 'Tab-Shared-Search' }) navigation.navigate('Tab-Public', {
screen: 'Tab-Shared-Search',
params: { text: undefined }
})
}} }}
/> />
) )
@ -86,7 +95,7 @@ const TabPublic = React.memo(
} }
}) => { }) => {
const queryKey: QueryKeyTimeline = ['Timeline', { page }] const queryKey: QueryKeyTimeline = ['Timeline', { page }]
const renderItem = ({ item }) => ( const renderItem = ({ item }: any) => (
<TimelineDefault item={item} queryKey={queryKey} /> <TimelineDefault item={item} queryKey={queryKey} />
) )
return <Timeline queryKey={queryKey} customProps={{ renderItem }} /> return <Timeline queryKey={queryKey} customProps={{ renderItem }} />

View File

@ -5,7 +5,7 @@ import TimelineDefault from '@components/Timeline/Default'
import { useSearchQuery } from '@utils/queryHooks/search' import { useSearchQuery } from '@utils/queryHooks/search'
import { StyleConstants } from '@utils/styles/constants' import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback, useEffect, useMemo, useState } from 'react' import React, { useCallback, useMemo } from 'react'
import { Trans, useTranslation } from 'react-i18next' import { Trans, useTranslation } from 'react-i18next'
import { import {
KeyboardAvoidingView, KeyboardAvoidingView,
@ -16,31 +16,26 @@ import {
View View
} from 'react-native' } from 'react-native'
import { Circle } from 'react-native-animated-spinkit' import { Circle } from 'react-native-animated-spinkit'
import { SharedSearchProp } from './sharedScreens'
export interface Props { const TabSharedSearch: React.FC<SharedSearchProp> = ({
searchTerm: string | undefined route: {
} params: { text }
}
const TabSharedSearch: React.FC<Props> = ({ searchTerm }) => { }) => {
const { t } = useTranslation('sharedSearch') const { t } = useTranslation('sharedSearch')
const { theme } = useTheme() const { theme } = useTheme()
const { status, data, refetch } = useSearchQuery({
term: searchTerm,
options: { enabled: false }
})
const [setctionData, setSectionData] = useState<
{ title: string; data: any }[]
>([])
const mapKeyToTranslations = { const mapKeyToTranslations = {
accounts: t('content.sections.accounts'), accounts: t('content.sections.accounts'),
hashtags: t('content.sections.hashtags'), hashtags: t('content.sections.hashtags'),
statuses: t('content.sections.statuses') statuses: t('content.sections.statuses')
} }
useEffect( const { status, data } = useSearchQuery({
() => term: text,
data && options: {
setSectionData( enabled: text !== undefined,
select: data =>
Object.keys(data as Mastodon.Results) Object.keys(data as Mastodon.Results)
.map(key => ({ .map(key => ({
title: key, title: key,
@ -58,17 +53,8 @@ const TabSharedSearch: React.FC<Props> = ({ searchTerm }) => {
return 0 return 0
} }
}) })
),
[data]
)
useEffect(() => {
if (searchTerm) {
refetch()
} else {
setSectionData([])
} }
}, [searchTerm]) })
const listEmpty = useMemo(() => { const listEmpty = useMemo(() => {
return ( return (
@ -145,13 +131,13 @@ const TabSharedSearch: React.FC<Props> = ({ searchTerm }) => {
<Text style={[styles.sectionFooterText, { color: theme.secondary }]}> <Text style={[styles.sectionFooterText, { color: theme.secondary }]}>
<Trans <Trans
i18nKey='sharedSearch:content.notFound' i18nKey='sharedSearch:content.notFound'
values={{ searchTerm, type: translation }} values={{ searchTerm: text, type: translation }}
components={{ bold: <Text style={styles.emptyFontBold} /> }} components={{ bold: <Text style={styles.emptyFontBold} /> }}
/> />
</Text> </Text>
</View> </View>
) : null, ) : null,
[searchTerm] [text]
) )
const listItem = useCallback(({ item, section }) => { const listItem = useCallback(({ item, section }) => {
switch (section.title) { switch (section.title) {
@ -175,7 +161,7 @@ const TabSharedSearch: React.FC<Props> = ({ searchTerm }) => {
style={styles.base} style={styles.base}
renderItem={listItem} renderItem={listItem}
stickySectionHeadersEnabled stickySectionHeadersEnabled
sections={setctionData} sections={data || []}
ListEmptyComponent={listEmpty} ListEmptyComponent={listEmpty}
keyboardShouldPersistTaps='always' keyboardShouldPersistTaps='always'
renderSectionHeader={sectionHeader} renderSectionHeader={sectionHeader}

View File

@ -11,15 +11,14 @@ import TabSharedToot from '@screens/Tabs/Shared/Toot'
import { StyleConstants } from '@utils/styles/constants' import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import { debounce } from 'lodash' import { debounce } from 'lodash'
import React, { useCallback, useState } from 'react' import React from 'react'
import { Trans, useTranslation } from 'react-i18next' import { Trans, useTranslation } from 'react-i18next'
import { Platform, StyleSheet, Text, View } from 'react-native' import { Platform, StyleSheet, Text, TextInput, View } from 'react-native'
import { TextInput } from 'react-native-gesture-handler' import { NativeStackNavigationOptions } from 'react-native-screens/lib/typescript/native-stack'
import { import {
NativeStackNavigationEventMap, NativeStackNavigationEventMap,
NativeStackNavigationOptions,
NativeStackNavigatorProps NativeStackNavigatorProps
} from 'react-native-screens/lib/typescript/types' } from 'react-native-screens/lib/typescript/native-stack/types'
export type BaseScreens = export type BaseScreens =
| Nav.TabLocalStackParamList | Nav.TabLocalStackParamList
@ -60,25 +59,12 @@ const sharedScreens = (
StackNavigationState<Record<string, object | undefined>>, StackNavigationState<Record<string, object | undefined>>,
NativeStackNavigationOptions, NativeStackNavigationOptions,
NativeStackNavigationEventMap, NativeStackNavigationEventMap,
({ ({ ...rest }: NativeStackNavigatorProps) => JSX.Element
initialRouteName,
children,
screenOptions,
...rest
}: NativeStackNavigatorProps) => JSX.Element
> >
) => { ) => {
const { mode, theme } = useTheme() const { mode, theme } = useTheme()
const { t } = useTranslation() const { t } = useTranslation()
const [searchTerm, setSearchTerm] = useState<string>()
const onChangeText = useCallback(
debounce(text => setSearchTerm(text), 1000, {
trailing: true
}),
[]
)
return [ return [
<Stack.Screen <Stack.Screen
key='Tab-Shared-Account' key='Tab-Shared-Account'
@ -158,54 +144,61 @@ const sharedScreens = (
<Stack.Screen <Stack.Screen
key='Tab-Shared-Search' key='Tab-Shared-Search'
name='Tab-Shared-Search' name='Tab-Shared-Search'
component={TabSharedSearch}
options={({ navigation }: SharedSearchProp) => ({ options={({ navigation }: SharedSearchProp) => ({
headerLeft: () => <HeaderLeft onPress={() => navigation.goBack()} />, headerLeft: () => <HeaderLeft onPress={() => navigation.goBack()} />,
// https://github.com/react-navigation/react-navigation/issues/6746#issuecomment-583897436 headerCenter: () => {
headerCenter: () => ( const onChangeText = debounce(
<View style={styles.searchBar}> (text: string) => navigation.setParams({ text }),
<TextInput 1000,
editable={false} {
children={ trailing: true
<Text }
style={[ )
styles.textInput, return (
{ <View style={styles.searchBar}>
color: theme.primary <TextInput
} editable={false}
]} children={
children={t('sharedSearch:content.header.prefix')} <Text
/> style={[
} styles.textInput,
/> {
<TextInput color: theme.primary
keyboardAppearance={mode} }
style={[ ]}
styles.textInput, children={t('sharedSearch:content.header.prefix')}
{ />
flex: 1,
color: theme.primary,
paddingLeft: StyleConstants.Spacing.XS
} }
]} />
autoFocus <TextInput
onChangeText={onChangeText} keyboardAppearance={mode}
autoCapitalize='none' style={[
autoCorrect={false} styles.textInput,
clearButtonMode='never' {
keyboardType='web-search' flex: 1,
onSubmitEditing={({ nativeEvent: { text } }) => color: theme.primary,
setSearchTerm(text) paddingLeft: StyleConstants.Spacing.XS
} }
placeholder={t('sharedSearch:content.header.placeholder')} ]}
placeholderTextColor={theme.secondary} autoFocus
returnKeyType='go' onChangeText={onChangeText}
/> autoCapitalize='none'
</View> autoCorrect={false}
) clearButtonMode='never'
keyboardType='web-search'
onSubmitEditing={({ nativeEvent: { text } }) =>
navigation.setParams({ text })
}
placeholder={t('sharedSearch:content.header.placeholder')}
placeholderTextColor={theme.secondary}
returnKeyType='go'
/>
</View>
)
}
})} })}
> />,
{() => <TabSharedSearch searchTerm={searchTerm} />}
</Stack.Screen>,
<Stack.Screen <Stack.Screen
key='Tab-Shared-Toot' key='Tab-Shared-Toot'
name='Tab-Shared-Toot' name='Tab-Shared-Toot'

View File

@ -42,43 +42,45 @@ const pushUseConnect = ({
expoToken expoToken
}, },
sentry: true sentry: true
}).catch(() => { }).catch(error => {
displayMessage({ if (error.status == 410) {
mode, displayMessage({
type: 'error', mode,
duration: 'long', type: 'error',
message: t('meSettingsPush:error.message'), duration: 'long',
description: t('meSettingsPush:error.description'), message: t('meSettingsPush:error.message'),
onPress: () => { description: t('meSettingsPush:error.description'),
navigationRef.current?.navigate('Screen-Tabs', { onPress: () => {
screen: 'Tab-Me', navigationRef.current?.navigate('Screen-Tabs', {
params: { screen: 'Tab-Me',
screen: 'Tab-Me-Root' params: {
} screen: 'Tab-Me-Root'
}) }
navigationRef.current?.navigate('Screen-Tabs', { })
screen: 'Tab-Me', navigationRef.current?.navigate('Screen-Tabs', {
params: { screen: 'Tab-Me',
screen: 'Tab-Me-Settings' params: {
} screen: 'Tab-Me-Settings'
}) }
} })
}) }
})
dispatch(disableAllPushes()) dispatch(disableAllPushes())
instances.forEach(instance => { instances.forEach(instance => {
if (instance.push.global.value) { if (instance.push.global.value) {
apiGeneral<{}>({ apiGeneral<{}>({
method: 'delete', method: 'delete',
domain: instance.url, domain: instance.url,
url: 'api/v1/push/subscription', url: 'api/v1/push/subscription',
headers: { headers: {
Authorization: `Bearer ${instance.token}` Authorization: `Bearer ${instance.token}`
} }
}).catch(() => console.log('error!!!')) }).catch(() => console.log('error!!!'))
} }
}) })
}
}) })
} }

View File

@ -194,7 +194,12 @@ const useTimelineQuery = <TData = TimelineData>({
> >
}) => { }) => {
const queryKey: QueryKeyTimeline = ['Timeline', { ...queryKeyParams }] const queryKey: QueryKeyTimeline = ['Timeline', { ...queryKeyParams }]
return useInfiniteQuery(queryKey, queryFunction, options) return useInfiniteQuery(queryKey, queryFunction, {
refetchOnMount: false,
refetchOnReconnect: false,
refetchOnWindowFocus: false,
...options
})
} }
// --- Separator --- // --- Separator ---

View File

@ -8716,10 +8716,10 @@ react-native-safe-area-view@^0.14.9:
dependencies: dependencies:
hoist-non-react-statics "^2.3.1" hoist-non-react-statics "^2.3.1"
react-native-screens@~2.17.1: react-native-screens@~2.18.1:
version "2.17.1" version "2.18.1"
resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-2.17.1.tgz#c3c0ac750af48741c5b1635511e6af2a27b74309" resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-2.18.1.tgz#47b9991c6f762d00d0ed3233e5283d523e859885"
integrity sha512-B4gD5e4csvlVwlhf+RNqjQZ9mHTwe/iL3rXondgZxnKz4oW0QAmtLnLRKOrYVxoaJaF9Fy7jhjo//24/472APQ== integrity sha512-r5WZLpmx2hHjC1RgMdPq5YpSU9tEhBpUaZ5M1SUtNIONyiLqQVxabhRCINdebIk4depJiIl7yw2Q85zJyeX6fw==
react-native-svg@12.1.0: react-native-svg@12.1.0:
version "12.1.0" version "12.1.0"