mirror of https://github.com/tooot-app/app
Rewrite header buttons
This commit is contained in:
parent
da79674548
commit
bd5601f8f9
|
@ -1,52 +1,51 @@
|
|||
import { Feather } from '@expo/vector-icons'
|
||||
import React from 'react'
|
||||
import React, { useMemo } from 'react'
|
||||
import { Pressable, StyleSheet, Text } from 'react-native'
|
||||
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import { Feather } from '@expo/vector-icons'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
|
||||
export interface Props {
|
||||
type?: 'icon' | 'text'
|
||||
content?: string
|
||||
|
||||
type PropsBase = {
|
||||
onPress: () => void
|
||||
}
|
||||
|
||||
export interface PropsText extends PropsBase {
|
||||
text: string
|
||||
icon?: any
|
||||
}
|
||||
|
||||
export interface PropsIcon extends PropsBase {
|
||||
text?: string
|
||||
icon: any
|
||||
}
|
||||
|
||||
const HeaderLeft: React.FC<PropsText | PropsIcon> = ({
|
||||
onPress,
|
||||
text,
|
||||
icon
|
||||
}) => {
|
||||
const HeaderLeft: React.FC<Props> = ({ type = 'icon', content, onPress }) => {
|
||||
const { theme } = useTheme()
|
||||
|
||||
const children = useMemo(() => {
|
||||
switch (type) {
|
||||
case 'icon':
|
||||
return (
|
||||
<Feather
|
||||
name={content || ('chevron-left' as any)}
|
||||
color={theme.primary}
|
||||
size={StyleConstants.Spacing.M * 1.25}
|
||||
/>
|
||||
)
|
||||
case 'text':
|
||||
return (
|
||||
<Text
|
||||
style={[styles.text, { color: theme.primary }]}
|
||||
children={content}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}, [theme])
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
onPress={onPress}
|
||||
children={children}
|
||||
style={[
|
||||
styles.base,
|
||||
{
|
||||
backgroundColor: theme.backgroundGradientStart,
|
||||
...(icon && { height: 44, width: 44, marginLeft: -9 })
|
||||
...(type === 'icon' && { height: 44, width: 44, marginLeft: -9 })
|
||||
}
|
||||
]}
|
||||
>
|
||||
{text ? (
|
||||
<Text style={[styles.text, { color: theme.primary }]}>{text}</Text>
|
||||
) : (
|
||||
<Feather
|
||||
name={icon || 'chevron-left'}
|
||||
color={theme.primary}
|
||||
size={StyleConstants.Spacing.L}
|
||||
/>
|
||||
)}
|
||||
</Pressable>
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,62 +1,86 @@
|
|||
import React, { useMemo } from 'react'
|
||||
import { Pressable, StyleSheet, Text, View } from 'react-native'
|
||||
import { Chase } from 'react-native-animated-spinkit'
|
||||
import { Feather } from '@expo/vector-icons'
|
||||
import React from 'react'
|
||||
import { Pressable, StyleSheet, Text } from 'react-native'
|
||||
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
|
||||
type PropsBase = {
|
||||
export interface Props {
|
||||
type?: 'icon' | 'text'
|
||||
content?: string
|
||||
|
||||
loading?: boolean
|
||||
disabled?: boolean
|
||||
|
||||
onPress: () => void
|
||||
}
|
||||
|
||||
export interface PropsText extends PropsBase {
|
||||
text: string
|
||||
icon?: any
|
||||
}
|
||||
|
||||
export interface PropsIcon extends PropsBase {
|
||||
text?: string
|
||||
icon: any
|
||||
}
|
||||
|
||||
const HeaderRight: React.FC<PropsText | PropsIcon> = ({
|
||||
const HeaderRight: React.FC<Props> = ({
|
||||
type = 'icon',
|
||||
content,
|
||||
loading,
|
||||
disabled,
|
||||
onPress,
|
||||
text,
|
||||
icon
|
||||
onPress
|
||||
}) => {
|
||||
const { theme } = useTheme()
|
||||
|
||||
const loadingSpinkit = useMemo(
|
||||
() => (
|
||||
<View style={{ position: 'absolute' }}>
|
||||
<Chase
|
||||
size={StyleConstants.Font.Size.M * 1.25}
|
||||
color={theme.secondary}
|
||||
/>
|
||||
</View>
|
||||
),
|
||||
[theme]
|
||||
)
|
||||
|
||||
const children = useMemo(() => {
|
||||
switch (type) {
|
||||
case 'icon':
|
||||
return (
|
||||
<>
|
||||
<Feather
|
||||
name={content as any}
|
||||
color={disabled ? theme.secondary : theme.primary}
|
||||
size={StyleConstants.Spacing.M * 1.25}
|
||||
style={{ opacity: loading ? 0 : 1 }}
|
||||
/>
|
||||
{loading && loadingSpinkit}
|
||||
</>
|
||||
)
|
||||
case 'text':
|
||||
return (
|
||||
<>
|
||||
<Text
|
||||
style={[
|
||||
styles.text,
|
||||
{
|
||||
color: disabled ? theme.secondary : theme.primary,
|
||||
opacity: loading ? 0 : 1
|
||||
}
|
||||
]}
|
||||
children={content}
|
||||
/>
|
||||
{loading && loadingSpinkit}
|
||||
</>
|
||||
)
|
||||
}
|
||||
}, [theme, loading, disabled])
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
{...(!disabled && { onPress })}
|
||||
{...(!disabled && !loading && { onPress })}
|
||||
children={children}
|
||||
style={[
|
||||
styles.base,
|
||||
{
|
||||
backgroundColor: theme.backgroundGradientStart,
|
||||
...(icon && { height: 44, width: 44, marginRight: -9 })
|
||||
...(type === 'icon' && { height: 44, width: 44, marginRight: -9 })
|
||||
}
|
||||
]}
|
||||
>
|
||||
{text && (
|
||||
<Text
|
||||
style={[
|
||||
styles.text,
|
||||
{ color: disabled ? theme.secondary : theme.primary }
|
||||
]}
|
||||
>
|
||||
{text}
|
||||
</Text>
|
||||
)}
|
||||
{icon && (
|
||||
<Feather
|
||||
name={icon}
|
||||
color={disabled ? theme.secondary : theme.primary}
|
||||
size={StyleConstants.Spacing.L}
|
||||
/>
|
||||
)}
|
||||
</Pressable>
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ const Timelines: React.FC<Props> = ({ name, content }) => {
|
|||
</View>
|
||||
),
|
||||
headerRight: () => (
|
||||
<HeaderRight icon='search' onPress={onPressSearch} />
|
||||
<HeaderRight content='search' onPress={onPressSearch} />
|
||||
)
|
||||
})
|
||||
}}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useCallback, useMemo } from 'react'
|
||||
import { ActionSheetIOS, Pressable, StyleSheet, Text, View } from 'react-native'
|
||||
import { InfiniteData, useMutation, useQueryClient } from 'react-query'
|
||||
import { useMutation, useQueryClient } from 'react-query'
|
||||
import { Feather } from '@expo/vector-icons'
|
||||
|
||||
import client from '@api/client'
|
||||
|
@ -11,8 +11,6 @@ import { useNavigation } from '@react-navigation/native'
|
|||
import getCurrentTab from '@utils/getCurrentTab'
|
||||
import { findIndex } from 'lodash'
|
||||
import { TimelineData } from '../../Timeline'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { getLocalAccountId } from '@root/utils/slices/instancesSlice'
|
||||
|
||||
const fireMutation = async ({
|
||||
id,
|
||||
|
|
|
@ -34,12 +34,7 @@ const ScreenMe: React.FC = () => {
|
|||
component={ScreenMeConversations}
|
||||
options={({ navigation }: any) => ({
|
||||
headerTitle: t('meConversations:heading'),
|
||||
headerLeft: () => (
|
||||
<HeaderLeft
|
||||
icon='chevron-left'
|
||||
onPress={() => navigation.goBack()}
|
||||
/>
|
||||
)
|
||||
headerLeft: () => <HeaderLeft onPress={() => navigation.goBack()} />
|
||||
})}
|
||||
/>
|
||||
<Stack.Screen
|
||||
|
@ -47,12 +42,7 @@ const ScreenMe: React.FC = () => {
|
|||
component={ScreenMeBookmarks}
|
||||
options={({ navigation }: any) => ({
|
||||
headerTitle: t('meBookmarks:heading'),
|
||||
headerLeft: () => (
|
||||
<HeaderLeft
|
||||
icon='chevron-left'
|
||||
onPress={() => navigation.goBack()}
|
||||
/>
|
||||
)
|
||||
headerLeft: () => <HeaderLeft onPress={() => navigation.goBack()} />
|
||||
})}
|
||||
/>
|
||||
<Stack.Screen
|
||||
|
@ -60,12 +50,7 @@ const ScreenMe: React.FC = () => {
|
|||
component={ScreenMeFavourites}
|
||||
options={({ navigation }: any) => ({
|
||||
headerTitle: t('meFavourites:heading'),
|
||||
headerLeft: () => (
|
||||
<HeaderLeft
|
||||
icon='chevron-left'
|
||||
onPress={() => navigation.goBack()}
|
||||
/>
|
||||
)
|
||||
headerLeft: () => <HeaderLeft onPress={() => navigation.goBack()} />
|
||||
})}
|
||||
/>
|
||||
<Stack.Screen
|
||||
|
@ -73,12 +58,7 @@ const ScreenMe: React.FC = () => {
|
|||
component={ScreenMeLists}
|
||||
options={({ navigation }: any) => ({
|
||||
headerTitle: t('meLists:heading'),
|
||||
headerLeft: () => (
|
||||
<HeaderLeft
|
||||
icon='chevron-left'
|
||||
onPress={() => navigation.goBack()}
|
||||
/>
|
||||
)
|
||||
headerLeft: () => <HeaderLeft onPress={() => navigation.goBack()} />
|
||||
})}
|
||||
/>
|
||||
<Stack.Screen
|
||||
|
@ -86,12 +66,7 @@ const ScreenMe: React.FC = () => {
|
|||
component={ScreenMeListsList}
|
||||
options={({ route, navigation }: any) => ({
|
||||
headerTitle: t('meListsList:heading', { list: route.params.title }),
|
||||
headerLeft: () => (
|
||||
<HeaderLeft
|
||||
icon='chevron-left'
|
||||
onPress={() => navigation.goBack()}
|
||||
/>
|
||||
)
|
||||
headerLeft: () => <HeaderLeft onPress={() => navigation.goBack()} />
|
||||
})}
|
||||
/>
|
||||
<Stack.Screen
|
||||
|
@ -99,12 +74,7 @@ const ScreenMe: React.FC = () => {
|
|||
component={ScreenMeSettings}
|
||||
options={({ navigation }: any) => ({
|
||||
headerTitle: t('meSettings:heading'),
|
||||
headerLeft: () => (
|
||||
<HeaderLeft
|
||||
icon='chevron-left'
|
||||
onPress={() => navigation.goBack()}
|
||||
/>
|
||||
)
|
||||
headerLeft: () => <HeaderLeft onPress={() => navigation.goBack()} />
|
||||
})}
|
||||
/>
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ const ScreenSharedAccount: React.FC<Props> = ({
|
|||
navigation.setOptions({
|
||||
headerRight: () => (
|
||||
<HeaderRight
|
||||
icon='more-horizontal'
|
||||
content='more-horizontal'
|
||||
onPress={() => setBottomSheetVisible(true)}
|
||||
/>
|
||||
)
|
||||
|
|
|
@ -540,6 +540,8 @@ const Compose: React.FC<Props> = ({ route: { params }, navigation }) => {
|
|||
const headerLeft = useCallback(
|
||||
() => (
|
||||
<HeaderLeft
|
||||
type='text'
|
||||
content='退出编辑'
|
||||
onPress={() =>
|
||||
Alert.alert('确认取消编辑?', '', [
|
||||
{ text: '继续编辑', style: 'cancel' },
|
||||
|
@ -550,7 +552,6 @@ const Compose: React.FC<Props> = ({ route: { params }, navigation }) => {
|
|||
}
|
||||
])
|
||||
}
|
||||
text='退出编辑'
|
||||
/>
|
||||
),
|
||||
[]
|
||||
|
@ -571,16 +572,15 @@ const Compose: React.FC<Props> = ({ route: { params }, navigation }) => {
|
|||
[totalTextCount]
|
||||
)
|
||||
const headerRight = useCallback(
|
||||
() =>
|
||||
isSubmitting ? (
|
||||
<ActivityIndicator />
|
||||
) : (
|
||||
<HeaderRight
|
||||
onPress={async () => tootPost()}
|
||||
text={params?.type ? postButtonText[params.type] : '发嘟嘟'}
|
||||
disabled={rawCount < 1 || totalTextCount > 500}
|
||||
/>
|
||||
),
|
||||
() => (
|
||||
<HeaderRight
|
||||
type='text'
|
||||
content={params?.type ? postButtonText[params.type] : '发嘟嘟'}
|
||||
onPress={async () => tootPost()}
|
||||
loading={isSubmitting}
|
||||
disabled={rawCount < 1 || totalTextCount > 500}
|
||||
/>
|
||||
),
|
||||
[isSubmitting, rawCount, totalTextCount]
|
||||
)
|
||||
|
||||
|
@ -605,7 +605,6 @@ const Compose: React.FC<Props> = ({ route: { params }, navigation }) => {
|
|||
</Stack.Screen>
|
||||
</Stack.Navigator>
|
||||
</SafeAreaView>
|
||||
<Toast ref={(ref: any) => Toast.setRef(ref)} config={toastConfig} />
|
||||
</KeyboardAvoidingView>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -230,11 +230,16 @@ const ComposeEditAttachment: React.FC<Props> = ({
|
|||
options={{
|
||||
title: '编辑附件',
|
||||
headerLeft: () => (
|
||||
<HeaderLeft text='取消' onPress={() => navigation.goBack()} />
|
||||
<HeaderLeft
|
||||
type='text'
|
||||
content='取消'
|
||||
onPress={() => navigation.goBack()}
|
||||
/>
|
||||
),
|
||||
headerRight: () => (
|
||||
<HeaderRight
|
||||
text='应用'
|
||||
type='text'
|
||||
content='应用'
|
||||
onPress={() => {
|
||||
const formData = new FormData()
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ const ScreenSharedImagesViewer: React.FC<Props> = ({
|
|||
contentStyle: { backgroundColor: 'black' },
|
||||
headerStyle: { backgroundColor: 'black' },
|
||||
headerLeft: () => (
|
||||
<HeaderLeft icon='x' onPress={() => navigation.goBack()} />
|
||||
<HeaderLeft content='x' onPress={() => navigation.goBack()} />
|
||||
),
|
||||
headerCenter: () => (
|
||||
<Text style={styles.headerCenter}>
|
||||
|
@ -102,7 +102,7 @@ const ScreenSharedImagesViewer: React.FC<Props> = ({
|
|||
),
|
||||
headerRight: () => (
|
||||
<HeaderRight
|
||||
icon='share'
|
||||
content='share'
|
||||
onPress={() =>
|
||||
ActionSheetIOS.showShareActionSheetWithOptions(
|
||||
{
|
||||
|
|
|
@ -242,7 +242,11 @@ const ScreenSharedSearch: React.FC = () => {
|
|||
/>
|
||||
</View>
|
||||
<View style={styles.searchCancel}>
|
||||
<HeaderRight text='取消' onPress={() => navigation.goBack()} />
|
||||
<HeaderRight
|
||||
type='text'
|
||||
content='取消'
|
||||
onPress={() => navigation.goBack()}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<SectionList
|
||||
|
|
|
@ -26,12 +26,7 @@ const sharedScreens = (Stack: any) => {
|
|||
backgroundColor: `rgba(255, 255, 255, 0)`
|
||||
},
|
||||
headerCenter: () => null,
|
||||
headerLeft: () => (
|
||||
<HeaderLeft
|
||||
icon='chevron-left'
|
||||
onPress={() => navigation.goBack()}
|
||||
/>
|
||||
)
|
||||
headerLeft: () => <HeaderLeft onPress={() => navigation.goBack()} />
|
||||
}
|
||||
}}
|
||||
/>,
|
||||
|
@ -41,9 +36,7 @@ const sharedScreens = (Stack: any) => {
|
|||
component={ScreenSharedHashtag}
|
||||
options={({ route, navigation }: any) => ({
|
||||
title: `#${decodeURIComponent(route.params.hashtag)}`,
|
||||
headerLeft: () => (
|
||||
<HeaderLeft icon='chevron-left' onPress={() => navigation.goBack()} />
|
||||
)
|
||||
headerLeft: () => <HeaderLeft onPress={() => navigation.goBack()} />
|
||||
})}
|
||||
/>,
|
||||
<Stack.Screen
|
||||
|
@ -52,9 +45,7 @@ const sharedScreens = (Stack: any) => {
|
|||
component={ScreenSharedToot}
|
||||
options={({ navigation }: any) => ({
|
||||
title: t('sharedToot:heading'),
|
||||
headerLeft: () => (
|
||||
<HeaderLeft icon='chevron-left' onPress={() => navigation.goBack()} />
|
||||
)
|
||||
headerLeft: () => <HeaderLeft onPress={() => navigation.goBack()} />
|
||||
})}
|
||||
/>,
|
||||
<Stack.Screen
|
||||
|
|
Loading…
Reference in New Issue