1
0
mirror of https://github.com/tooot-app/app synced 2025-06-05 22:19:13 +02:00

iOS almost working

This commit is contained in:
Zhiyuan Zheng
2021-01-30 01:29:15 +01:00
parent 9c36052c2a
commit 247f7a7982
126 changed files with 1829 additions and 1341 deletions

View File

@ -21,12 +21,12 @@ const ComponentAccount: React.FC<Props> = ({
}) => {
const { theme } = useTheme()
const navigation = useNavigation<
StackNavigationProp<Nav.LocalStackParamList>
StackNavigationProp<Nav.TabLocalStackParamList>
>()
const onPress = useCallback(() => {
analytics('search_account_press', { page: origin })
navigation.push('Screen-Shared-Account', { account })
navigation.push('Tab-Shared-Account', { account })
}, [])
return (

View File

@ -1,129 +0,0 @@
import React from 'react'
import { Dimensions, Modal, StyleSheet, View } from 'react-native'
import { useSafeAreaInsets } from 'react-native-safe-area-context'
import { useTheme } from '@utils/styles/ThemeManager'
import { StyleConstants } from '@utils/styles/constants'
import Button from '@components/Button'
import {
PanGestureHandler,
State,
TapGestureHandler
} from 'react-native-gesture-handler'
import Animated, {
Extrapolate,
interpolate,
runOnJS,
useAnimatedGestureHandler,
useAnimatedStyle,
useSharedValue,
withTiming
} from 'react-native-reanimated'
import analytics from './analytics'
export interface Props {
children: React.ReactNode
visible: boolean
handleDismiss: () => void
}
const BottomSheet: React.FC<Props> = ({ children, visible, handleDismiss }) => {
const { theme } = useTheme()
const insets = useSafeAreaInsets()
const screenHeight = Dimensions.get('screen').height
const panY = useSharedValue(0)
const styleTop = useAnimatedStyle(() => {
return {
top: interpolate(
panY.value,
[0, screenHeight],
[0, screenHeight],
Extrapolate.CLAMP
)
}
})
const callDismiss = () => {
analytics('bottomsheet_swipe_close')
handleDismiss()
}
const onGestureEvent = useAnimatedGestureHandler({
onActive: ({ translationY }) => {
panY.value = translationY
},
onEnd: ({ velocityY }) => {
if (velocityY > 500) {
runOnJS(callDismiss)()
} else {
panY.value = withTiming(0)
}
}
})
return (
<Modal animated animationType='fade' visible={visible} transparent>
<TapGestureHandler
onHandlerStateChange={({ nativeEvent }) => {
if (nativeEvent.state === State.ACTIVE) {
callDismiss()
}
}}
>
<Animated.View
style={[styles.overlay, { backgroundColor: theme.backgroundOverlay }]}
>
<PanGestureHandler onGestureEvent={onGestureEvent}>
<Animated.View
style={[
styles.container,
styleTop,
{
backgroundColor: theme.background,
paddingBottom: insets.bottom || StyleConstants.Spacing.L
}
]}
>
<View
style={[
styles.handle,
{ backgroundColor: theme.primaryOverlay }
]}
/>
{children}
<Button
type='text'
content='取消'
onPress={() => {
analytics('bottomsheet_cancel')
handleDismiss()
}}
style={styles.button}
/>
</Animated.View>
</PanGestureHandler>
</Animated.View>
</TapGestureHandler>
</Modal>
)
}
const styles = StyleSheet.create({
overlay: {
flex: 1,
justifyContent: 'flex-end'
},
container: {
paddingTop: StyleConstants.Spacing.M
},
handle: {
alignSelf: 'center',
width: StyleConstants.Spacing.S * 8,
height: StyleConstants.Spacing.S / 2,
borderRadius: 100,
top: -StyleConstants.Spacing.M * 2
},
button: {
marginHorizontal: StyleConstants.Spacing.Global.PagePadding * 2
}
})
export default BottomSheet

View File

@ -9,9 +9,11 @@ import {
} from 'react-native'
import { Blurhash } from 'react-native-blurhash'
import FastImage from 'react-native-fast-image'
import { SharedElement } from 'react-navigation-shared-element'
import { useTheme } from '@utils/styles/ThemeManager'
export interface Props {
sharedElement?: string
hidden?: boolean
uri: { preview?: string; original: string; remote?: string }
blurhash?: string
@ -22,6 +24,7 @@ export interface Props {
}
const GracefullyImage: React.FC<Props> = ({
sharedElement,
hidden = false,
uri,
blurhash,
@ -36,11 +39,21 @@ const GracefullyImage: React.FC<Props> = ({
const children = useCallback(() => {
return (
<>
<FastImage
source={{ uri: uri.preview || uri.original || uri.remote }}
style={[styles.image, imageStyle]}
onLoad={() => setImageLoaded(true)}
/>
{sharedElement ? (
<SharedElement id={`image.${sharedElement}`} style={[styles.image]}>
<FastImage
source={{ uri: uri.preview || uri.original || uri.remote }}
style={[styles.image, imageStyle]}
onLoad={() => setImageLoaded(true)}
/>
</SharedElement>
) : (
<FastImage
source={{ uri: uri.preview || uri.original || uri.remote }}
style={[styles.image, imageStyle]}
onLoad={() => setImageLoaded(true)}
/>
)}
{blurhash && (hidden || !imageLoaded) ? (
<Blurhash
decodeAsync

View File

@ -19,12 +19,12 @@ const ComponentHashtag: React.FC<Props> = ({
}) => {
const { theme } = useTheme()
const navigation = useNavigation<
StackNavigationProp<Nav.LocalStackParamList>
StackNavigationProp<Nav.TabLocalStackParamList>
>()
const onPress = useCallback(() => {
analytics('search_account_press', { page: origin })
navigation.push('Screen-Shared-Hashtag', { hashtag: hashtag.name })
navigation.push('Tab-Shared-Hashtag', { hashtag: hashtag.name })
}, [])
return (

View File

@ -7,11 +7,17 @@ import { Pressable, StyleSheet, Text } from 'react-native'
export interface Props {
type?: 'icon' | 'text'
content?: string
native?: boolean
onPress: () => void
}
const HeaderLeft: React.FC<Props> = ({ type = 'icon', content, onPress }) => {
const HeaderLeft: React.FC<Props> = ({
type = 'icon',
content,
native = true,
onPress
}) => {
const { theme } = useTheme()
const children = useMemo(() => {
@ -42,7 +48,11 @@ const HeaderLeft: React.FC<Props> = ({ type = 'icon', content, onPress }) => {
styles.base,
{
backgroundColor: theme.backgroundGradientStart,
...(type === 'icon' && { height: 44, width: 44, marginLeft: -9 })
...(type === 'icon' && {
height: 44,
width: 44,
marginLeft: native ? -9 : 9
})
}
]}
/>

View File

@ -9,6 +9,7 @@ import { Chase } from 'react-native-animated-spinkit'
export interface Props {
type?: 'icon' | 'text'
content: string
native?: boolean
loading?: boolean
disabled?: boolean
@ -19,6 +20,7 @@ export interface Props {
const HeaderRight: React.FC<Props> = ({
type = 'icon',
content,
native = true,
loading,
disabled,
onPress
@ -88,7 +90,11 @@ const HeaderRight: React.FC<Props> = ({
styles.base,
{
backgroundColor: theme.backgroundGradientStart,
...(type === 'icon' && { height: 44, width: 44, marginRight: -9 })
...(type === 'icon' && {
height: 44,
width: 44,
marginRight: native ? -9 : 9
})
}
]}
/>

View File

@ -230,12 +230,6 @@ const ComponentInstance: React.FC<Props> = ({
content={instanceQuery.data?.title || undefined}
potentialWidth={2}
/>
<InstanceInfo
visible={instanceQuery.data?.short_description !== undefined}
header={t('server.information.description.heading')}
content={instanceQuery.data?.short_description || undefined}
potentialLines={5}
/>
<View style={styles.instanceStats}>
<InstanceInfo
style={styles.stat1}

View File

@ -58,7 +58,7 @@ const renderNode = ({
analytics('status_hashtag_press')
!disableDetails &&
differentTag &&
navigation.push('Screen-Shared-Hashtag', {
navigation.push('Tab-Shared-Hashtag', {
hashtag: tag[1] || tag[2]
})
}}
@ -86,7 +86,7 @@ const renderNode = ({
accountIndex !== -1 &&
!disableDetails &&
differentAccount &&
navigation.push('Screen-Shared-Account', {
navigation.push('Tab-Shared-Account', {
account: mentions[accountIndex]
})
}}
@ -115,7 +115,7 @@ const renderNode = ({
analytics('status_link_press')
!disableDetails && !shouldBeTag
? await openLink(href)
: navigation.push('Screen-Shared-Hashtag', {
: navigation.push('Tab-Shared-Hashtag', {
hashtag: content.substring(1)
})
}}

View File

@ -2,7 +2,7 @@ import { HeaderRight } from '@components/Header'
import Timeline from '@components/Timelines/Timeline'
import SegmentedControl from '@react-native-community/segmented-control'
import { useNavigation } from '@react-navigation/native'
import sharedScreens from '@screens/Shared/sharedScreens'
import sharedScreens from '@screens/Tabs/Shared/sharedScreens'
import { getLocalActiveIndex } from '@utils/slices/instancesSlice'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback, useMemo, useState } from 'react'
@ -14,7 +14,7 @@ import ViewPagerAdapter from 'react-native-tab-view-viewpager-adapter'
import { useSelector } from 'react-redux'
import analytics from './analytics'
const Stack = createNativeStackNavigator<Nav.RemoteStackParamList>()
const Stack = createNativeStackNavigator<Nav.TabPublicStackParamList>()
const Timelines: React.FC = () => {
const { t, i18n } = useTranslation()
@ -28,7 +28,7 @@ const Timelines: React.FC = () => {
const onPressSearch = useCallback(() => {
analytics('search_tap', { page: pages[segment].page })
navigation.navigate('Screen-Public', { screen: 'Screen-Shared-Search' })
navigation.navigate('Tab-Public', { screen: 'Tab-Shared-Search' })
}, [])
const routes = pages.map(p => ({ key: p.page }))

View File

@ -18,7 +18,6 @@ import TimelineConversation from './Timeline/Conversation'
import TimelineDefault from './Timeline/Default'
import TimelineEmpty from './Timeline/Empty'
import TimelineEnd from './Timeline/End'
import TimelineHeader from './Timeline/Header'
import TimelineNotifications from './Timeline/Notifications'
export interface Props {
@ -155,7 +154,6 @@ const Timeline: React.FC<Props> = ({
() => !disableInfinity && !isFetchingNextPage && fetchNextPage(),
[isFetchingNextPage]
)
const ListHeaderComponent = useCallback(() => <TimelineHeader />, [])
const ListFooterComponent = useCallback(
() => <TimelineEnd hasNextPage={!disableInfinity ? hasNextPage : false} />,
[hasNextPage]

View File

@ -76,13 +76,13 @@ const TimelineConversation: React.FC<Props> = ({
})
const navigation = useNavigation<
StackNavigationProp<Nav.LocalStackParamList>
StackNavigationProp<Nav.TabLocalStackParamList>
>()
const onPress = useCallback(() => {
analytics('timeline_conversation_press')
if (conversation.last_status) {
conversation.unread && mutate()
navigation.push('Screen-Shared-Toot', {
navigation.push('Tab-Shared-Toot', {
toot: conversation.last_status
})
}

View File

@ -36,7 +36,7 @@ const TimelineDefault: React.FC<Props> = ({
}) => {
const localAccount = useSelector(getLocalAccount)
const navigation = useNavigation<
StackNavigationProp<Nav.LocalStackParamList>
StackNavigationProp<Nav.TabLocalStackParamList>
>()
let actualStatus = item.reblog ? item.reblog : item
@ -47,7 +47,7 @@ const TimelineDefault: React.FC<Props> = ({
})
!disableOnPress &&
!highlighted &&
navigation.push('Screen-Shared-Toot', {
navigation.push('Tab-Shared-Toot', {
toot: actualStatus
})
}, [])

View File

@ -1,61 +0,0 @@
import analytics from '@components/analytics'
import { useNavigation } from '@react-navigation/native'
import Icon from '@root/components/Icon'
import { StyleConstants } from '@root/utils/styles/constants'
import { useTheme } from '@root/utils/styles/ThemeManager'
import { updatePublicRemoteNotice } from '@utils/slices/contextsSlice'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { StyleSheet, Text, View } from 'react-native'
import { useDispatch } from 'react-redux'
const TimelineHeader = React.memo(
() => {
const { t } = useTranslation('componentTimeline')
const dispatch = useDispatch()
const navigation = useNavigation()
const { theme } = useTheme()
return (
<View style={[styles.base, { borderColor: theme.border }]}>
<Text style={[styles.text, { color: theme.primary }]}>
{t('header.explanation')}
<Text
style={{ color: theme.blue }}
onPress={() => {
analytics('timeline_remote_header_press')
dispatch(updatePublicRemoteNotice(1))
navigation.navigate('Screen-Me', {
screen: 'Screen-Me-Root',
params: { navigateAway: 'Screen-Me-Settings-UpdateRemote' }
})
}}
>
{t('header.button')}
<Icon
name='ArrowRight'
size={StyleConstants.Font.Size.S}
color={theme.blue}
/>
</Text>
</Text>
</View>
)
},
() => true
)
const styles = StyleSheet.create({
base: {
margin: StyleConstants.Spacing.Global.PagePadding,
paddingHorizontal: StyleConstants.Spacing.M,
paddingVertical: StyleConstants.Spacing.S,
borderWidth: 1,
borderRadius: 6
},
text: {
...StyleConstants.FontStyle.S
}
})
export default TimelineHeader

View File

@ -29,7 +29,7 @@ const TimelineNotifications: React.FC<Props> = ({
}) => {
const localAccount = useSelector(getLocalAccount)
const navigation = useNavigation<
StackNavigationProp<Nav.LocalStackParamList>
StackNavigationProp<Nav.TabLocalStackParamList>
>()
const actualAccount = notification.status
? notification.status.account
@ -38,7 +38,7 @@ const TimelineNotifications: React.FC<Props> = ({
const onPress = useCallback(() => {
analytics('timeline_notification_press')
notification.status &&
navigation.push('Screen-Shared-Toot', {
navigation.push('Tab-Shared-Toot', {
toot: notification.status
})
}, [])

View File

@ -23,7 +23,7 @@ const TimelineActioned: React.FC<Props> = ({
const { t } = useTranslation('componentTimeline')
const { theme } = useTheme()
const navigation = useNavigation<
StackNavigationProp<Nav.LocalStackParamList>
StackNavigationProp<Nav.TabLocalStackParamList>
>()
const name = account.display_name || account.username
const iconColor = theme.primary
@ -34,7 +34,7 @@ const TimelineActioned: React.FC<Props> = ({
const onPress = useCallback(() => {
analytics('timeline_shared_actioned_press', { action })
navigation.push('Screen-Shared-Account', { account })
navigation.push('Tab-Shared-Account', { account })
}, [])
const children = useMemo(() => {

View File

@ -104,7 +104,7 @@ const TimelineActions: React.FC<Props> = ({
page: queryKey[1].page,
count: status.replies_count
})
navigation.navigate('Screen-Shared-Compose', {
navigation.navigate('Screen-Compose', {
type: 'reply',
incomingStatus: status,
accts,

View File

@ -40,7 +40,7 @@ const TimelineAttachment: React.FC<Props> = ({ status }) => {
})[] = []
const navigation = useNavigation()
const navigateToImagesViewer = (imageIndex: number) =>
navigation.navigate('Screen-Shared-ImagesViewer', {
navigation.navigate('Screen-ImagesViewer', {
imageUrls,
imageIndex
})

View File

@ -33,6 +33,7 @@ const AttachmentImage: React.FC<Props> = ({
original: image.url,
remote: image.remote_url
}}
sharedElement={image.url}
blurhash={image.blurhash}
onPress={onPress}
style={[

View File

@ -13,12 +13,14 @@ export interface Props {
const TimelineAvatar: React.FC<Props> = ({ queryKey, account }) => {
const navigation = useNavigation<
StackNavigationProp<Nav.LocalStackParamList>
StackNavigationProp<Nav.TabLocalStackParamList>
>()
// Need to fix go back root
const onPress = useCallback(() => {
analytics('timeline_shared_avatar_press', { page: queryKey[1].page })
queryKey && navigation.push('Screen-Shared-Account', { account })
analytics('timeline_shared_avatar_press', {
page: queryKey && queryKey[1].page
})
queryKey && navigation.push('Tab-Shared-Account', { account })
}, [])
return (

View File

@ -1,5 +1,5 @@
import analytics from '@components/analytics'
import BottomSheet from '@components/BottomSheet'
import BottomSheet from '@screens/Tabs/Shared/node_modules/@screens/Actions/BottomSheet'
import Icon from '@components/Icon'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import { getLocalAccount, getLocalUrl } from '@utils/slices/instancesSlice'

View File

@ -106,7 +106,7 @@ const HeaderActionsStatus: React.FC<Props> = ({
id: status.id
})
if (res.id) {
navigation.navigate('Screen-Shared-Compose', {
navigation.navigate('Screen-Compose', {
type: 'edit',
incomingStatus: res,
queryKey

View File

@ -1,13 +1,15 @@
import { StyleConstants } from '@utils/styles/constants'
import React from 'react'
import { StyleSheet, View } from 'react-native'
import { Pressable, StyleSheet, View } from 'react-native'
import HeaderSharedAccount from './HeaderShared/Account'
import HeaderSharedApplication from './HeaderShared/Application'
import HeaderSharedCreated from './HeaderShared/Created'
import HeaderSharedVisibility from './HeaderShared/Visibility'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import HeaderSharedMuted from './HeaderShared/Muted'
import HeaderActions from './HeaderActions/Root'
import { useNavigation } from '@react-navigation/native'
import Icon from '@components/Icon'
import { useTheme } from '@utils/styles/ThemeManager'
export interface Props {
queryKey?: QueryKeyTimeline
@ -15,6 +17,9 @@ export interface Props {
}
const TimelineHeaderDefault: React.FC<Props> = ({ queryKey, status }) => {
const navigation = useNavigation()
const { theme } = useTheme()
return (
<View style={styles.base}>
<View style={styles.accountAndMeta}>
@ -28,11 +33,28 @@ const TimelineHeaderDefault: React.FC<Props> = ({ queryKey, status }) => {
</View>
{queryKey ? (
<HeaderActions
queryKey={queryKey}
status={status}
url={status.url || status.uri}
type='status'
<Pressable
style={{
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
paddingBottom: StyleConstants.Spacing.S
}}
onPress={() =>
navigation.navigate('Screen-Actions', {
queryKey,
status,
url: status.url || status.uri,
type: 'status'
})
}
children={
<Icon
name='MoreHorizontal'
color={theme.secondary}
size={StyleConstants.Font.Size.L}
/>
}
/>
) : null}
</View>

View File

@ -8,8 +8,8 @@ import HeaderSharedCreated from './HeaderShared/Created'
import HeaderSharedVisibility from './HeaderShared/Visibility'
import RelationshipIncoming from '@root/components/Relationship/Incoming'
import HeaderSharedMuted from './HeaderShared/Muted'
import HeaderActions from './HeaderActions/Root'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import ScreenActions from '@screens/Actions'
export interface Props {
queryKey: QueryKeyTimeline
@ -28,7 +28,7 @@ const TimelineHeaderNotification: React.FC<Props> = ({
return <RelationshipIncoming id={notification.account.id} />
default:
return notification.status ? (
<HeaderActions queryKey={queryKey} status={notification.status} />
<ScreenActions queryKey={queryKey} status={notification.status} />
) : null
}
}, [notification.type])