mirror of
https://github.com/tooot-app/app
synced 2025-02-18 04:40:57 +01:00
Updates
This commit is contained in:
parent
284d6e46e0
commit
2df172d026
2
src/@types/react-navigation.d.ts
vendored
2
src/@types/react-navigation.d.ts
vendored
@ -52,7 +52,7 @@ declare namespace Nav {
|
||||
} & SharedStackParamList
|
||||
|
||||
type MeStackParamList = {
|
||||
'Screen-Me-Root': undefined
|
||||
'Screen-Me-Root': { navigateAway?: 'Screen-Me-Settings-UpdateRemote' }
|
||||
'Screen-Me-Bookmarks': undefined
|
||||
'Screen-Me-Conversations': undefined
|
||||
'Screen-Me-Favourites': undefined
|
||||
|
@ -242,13 +242,6 @@ const Index: React.FC<Props> = ({ localCorrupt }) => {
|
||||
}),
|
||||
[localActiveIndex]
|
||||
)
|
||||
const tabScreenNotificationsOptions = useMemo(
|
||||
() => ({
|
||||
tabBarBadge: prevNotification && prevNotification.unread ? '' : undefined
|
||||
}),
|
||||
[theme, prevNotification]
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
<StatusBar barStyle={barStyle[mode]} />
|
||||
@ -280,13 +273,22 @@ const Index: React.FC<Props> = ({ localCorrupt }) => {
|
||||
name='Screen-Notifications'
|
||||
component={ScreenNotifications}
|
||||
listeners={tabScreenNotificationsListeners}
|
||||
options={{
|
||||
tabBarBadgeStyle: {
|
||||
transform: [{ scale: 0.5 }],
|
||||
backgroundColor: theme.red
|
||||
},
|
||||
...tabScreenNotificationsOptions
|
||||
}}
|
||||
options={
|
||||
prevNotification && prevNotification.unread
|
||||
? {
|
||||
tabBarBadge: '',
|
||||
tabBarBadgeStyle: {
|
||||
transform: [{ scale: 0.5 }],
|
||||
backgroundColor: theme.red
|
||||
}
|
||||
}
|
||||
: {
|
||||
tabBarBadgeStyle: {
|
||||
transform: [{ scale: 0.5 }],
|
||||
backgroundColor: theme.red
|
||||
}
|
||||
}
|
||||
}
|
||||
/>
|
||||
<Tab.Screen name='Screen-Me' component={ScreenMe} />
|
||||
</Tab.Navigator>
|
||||
|
61
src/components/CustomRefreshControl.tsx
Normal file
61
src/components/CustomRefreshControl.tsx
Normal file
@ -0,0 +1,61 @@
|
||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||
import React, { useRef } from 'react'
|
||||
import { RefreshControl } from 'react-native'
|
||||
import { InfiniteData, useQueryClient } from 'react-query'
|
||||
|
||||
export interface Props {
|
||||
queryKey: QueryKeyTimeline
|
||||
isFetchingPreviousPage: boolean
|
||||
isFetching: boolean
|
||||
fetchPreviousPage: () => void
|
||||
refetch: () => void
|
||||
}
|
||||
|
||||
const CustomRefreshControl = React.memo(
|
||||
({
|
||||
queryKey,
|
||||
isFetchingPreviousPage,
|
||||
isFetching,
|
||||
fetchPreviousPage,
|
||||
refetch
|
||||
}: Props) => {
|
||||
const queryClient = useQueryClient()
|
||||
const refreshCount = useRef(0)
|
||||
|
||||
return (
|
||||
<RefreshControl
|
||||
refreshing={
|
||||
refreshCount.current < 2 ? isFetchingPreviousPage : isFetching
|
||||
}
|
||||
onRefresh={async () => {
|
||||
if (refreshCount.current < 2) {
|
||||
await fetchPreviousPage()
|
||||
refreshCount.current++
|
||||
} else {
|
||||
queryClient.setQueryData<InfiniteData<any> | undefined>(
|
||||
queryKey,
|
||||
data => {
|
||||
if (data) {
|
||||
return {
|
||||
pages: data.pages.slice(1),
|
||||
pageParams: data.pageParams.slice(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
await refetch()
|
||||
refreshCount.current = 0
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)
|
||||
},
|
||||
(prev, next) => {
|
||||
let skipUpdate = true
|
||||
skipUpdate = prev.isFetchingPreviousPage === next.isFetchingPreviousPage
|
||||
skipUpdate = prev.isFetching === next.isFetching
|
||||
return skipUpdate
|
||||
}
|
||||
)
|
||||
|
||||
export default CustomRefreshControl
|
@ -3,16 +3,12 @@ import openLink from '@components/openLink'
|
||||
import ParseEmojis from '@components/Parse/Emojis'
|
||||
import { useNavigation, useRoute } from '@react-navigation/native'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import layoutAnimation from '@utils/styles/layoutAnimation'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import { LinearGradient } from 'expo-linear-gradient'
|
||||
import React, { useCallback, useState } from 'react'
|
||||
import { Pressable, Text, View } from 'react-native'
|
||||
import HTMLView from 'react-native-htmlview'
|
||||
import Animated, {
|
||||
useAnimatedStyle,
|
||||
useDerivedValue,
|
||||
withTiming
|
||||
} from 'react-native-reanimated'
|
||||
|
||||
// Prevent going to the same hashtag multiple times
|
||||
const renderNode = ({
|
||||
@ -197,70 +193,36 @@ const ParseHTML: React.FC<Props> = ({
|
||||
({ children }) => {
|
||||
const lineHeight = StyleConstants.Font.LineHeight[size]
|
||||
|
||||
const [lines, setLines] = useState<number | undefined>(undefined)
|
||||
const [heightOriginal, setHeightOriginal] = useState<number>()
|
||||
const [heightTruncated, setHeightTruncated] = useState<number>()
|
||||
const [expandAllow, setExpandAllow] = useState(false)
|
||||
const [expanded, setExpanded] = useState(false)
|
||||
|
||||
const viewHeight = useDerivedValue(() => {
|
||||
if (expandAllow) {
|
||||
if (expanded) {
|
||||
return heightOriginal as number
|
||||
} else {
|
||||
return heightTruncated as number
|
||||
}
|
||||
} else {
|
||||
return heightOriginal as number
|
||||
const onTextLayout = useCallback(({ nativeEvent }) => {
|
||||
if (
|
||||
nativeEvent.lines &&
|
||||
nativeEvent.lines.length === numberOfLines + 1
|
||||
) {
|
||||
setExpandAllow(true)
|
||||
}
|
||||
}, [heightOriginal, heightTruncated, expandAllow, expanded])
|
||||
const ViewHeight = useAnimatedStyle(() => {
|
||||
return {
|
||||
height: expandAllow
|
||||
? expanded
|
||||
? withTiming(viewHeight.value)
|
||||
: withTiming(viewHeight.value)
|
||||
: viewHeight.value
|
||||
}
|
||||
})
|
||||
|
||||
const onLayout = useCallback(
|
||||
({ nativeEvent }) => {
|
||||
if (!heightOriginal) {
|
||||
setHeightOriginal(nativeEvent.layout.height)
|
||||
setLines(numberOfLines === 0 ? 1 : numberOfLines)
|
||||
} else {
|
||||
if (!heightTruncated) {
|
||||
setHeightTruncated(nativeEvent.layout.height)
|
||||
setLines(undefined)
|
||||
} else {
|
||||
if (heightOriginal > heightTruncated) {
|
||||
setExpandAllow(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
[heightOriginal, heightTruncated]
|
||||
)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<View>
|
||||
<Animated.View style={[ViewHeight, { overflow: 'hidden' }]}>
|
||||
<Animated.Text
|
||||
children={children}
|
||||
onLayout={onLayout}
|
||||
numberOfLines={lines}
|
||||
style={{
|
||||
...StyleConstants.FontStyle[size],
|
||||
color: theme.primary,
|
||||
height: expandAllow ? heightOriginal : undefined
|
||||
}}
|
||||
/>
|
||||
</Animated.View>
|
||||
<Text
|
||||
children={children}
|
||||
onTextLayout={onTextLayout}
|
||||
numberOfLines={expanded ? 999 : numberOfLines + 1}
|
||||
style={{
|
||||
...StyleConstants.FontStyle[size],
|
||||
color: theme.primary
|
||||
}}
|
||||
/>
|
||||
{expandAllow ? (
|
||||
<Pressable
|
||||
onPress={() => setExpanded(!expanded)}
|
||||
style={{ marginTop: expanded ? 0 : -lineHeight * 1.25 }}
|
||||
onPress={() => {
|
||||
layoutAnimation()
|
||||
setExpanded(!expanded)
|
||||
}}
|
||||
style={{ marginTop: expanded ? 0 : -lineHeight * 2.25 }}
|
||||
>
|
||||
<LinearGradient
|
||||
colors={[
|
||||
@ -301,4 +263,5 @@ const ParseHTML: React.FC<Props> = ({
|
||||
)
|
||||
}
|
||||
|
||||
export default ParseHTML
|
||||
// export default ParseHTML
|
||||
export default React.memo(ParseHTML, () => true)
|
||||
|
@ -9,18 +9,12 @@ import { useScrollToTop } from '@react-navigation/native'
|
||||
import { localUpdateNotification } from '@utils/slices/instancesSlice'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import React, { useCallback, useEffect, useMemo, useRef } from 'react'
|
||||
import { RefreshControl, StyleSheet } from 'react-native'
|
||||
import { StyleSheet } from 'react-native'
|
||||
import { FlatList } from 'react-native-gesture-handler'
|
||||
import { InfiniteData } from 'react-query'
|
||||
import { useDispatch } from 'react-redux'
|
||||
import { QueryKeyTimeline, useTimelineQuery } from '@utils/queryHooks/timeline'
|
||||
import { findIndex } from 'lodash'
|
||||
|
||||
type TimelineData =
|
||||
| InfiniteData<{
|
||||
toots: Mastodon.Status[]
|
||||
}>
|
||||
| undefined
|
||||
import CustomRefreshControl from '@components/CustomRefreshControl'
|
||||
|
||||
export interface Props {
|
||||
page: App.Pages
|
||||
@ -54,6 +48,7 @@ const Timeline: React.FC<Props> = ({
|
||||
data,
|
||||
refetch,
|
||||
isSuccess,
|
||||
isFetching,
|
||||
hasPreviousPage,
|
||||
fetchPreviousPage,
|
||||
isFetchingPreviousPage,
|
||||
@ -122,10 +117,6 @@ const Timeline: React.FC<Props> = ({
|
||||
case 'Notifications':
|
||||
return <TimelineNotifications notification={item} queryKey={queryKey} />
|
||||
default:
|
||||
// if (item.poll) {
|
||||
// console.log('Timeline')
|
||||
// console.log(item.poll)
|
||||
// }
|
||||
return (
|
||||
<TimelineDefault
|
||||
item={item}
|
||||
@ -167,12 +158,15 @@ const Timeline: React.FC<Props> = ({
|
||||
)
|
||||
const refreshControl = useMemo(
|
||||
() => (
|
||||
<RefreshControl
|
||||
refreshing={isFetchingPreviousPage}
|
||||
onRefresh={() => fetchPreviousPage()}
|
||||
<CustomRefreshControl
|
||||
queryKey={queryKey}
|
||||
isFetchingPreviousPage={isFetchingNextPage}
|
||||
isFetching={isFetching}
|
||||
fetchPreviousPage={fetchPreviousPage}
|
||||
refetch={refetch}
|
||||
/>
|
||||
),
|
||||
[isFetchingPreviousPage]
|
||||
[isFetchingPreviousPage, isFetching]
|
||||
)
|
||||
const onScrollToIndexFailed = useCallback(error => {
|
||||
const offset = error.averageItemLength * error.index
|
||||
@ -219,6 +213,4 @@ const styles = StyleSheet.create({
|
||||
}
|
||||
})
|
||||
|
||||
// Timeline.whyDidYouRender = true
|
||||
|
||||
export default Timeline
|
||||
|
@ -15,7 +15,7 @@ import { Pressable, StyleSheet, View } from 'react-native'
|
||||
import { useSelector } from 'react-redux'
|
||||
|
||||
export interface Props {
|
||||
item: Mastodon.Status
|
||||
item: Mastodon.Status & { isPinned?: boolean }
|
||||
queryKey?: QueryKeyTimeline
|
||||
highlighted?: boolean
|
||||
disableDetails?: boolean
|
||||
@ -61,7 +61,6 @@ const TimelineDefault: React.FC<Props> = ({
|
||||
<TimelineHeaderDefault
|
||||
queryKey={disableOnPress ? undefined : queryKey}
|
||||
status={actualStatus}
|
||||
sameAccount={actualStatus.account.id === localAccount?.id}
|
||||
/>
|
||||
</View>
|
||||
|
||||
|
@ -17,7 +17,10 @@ const TimelineHeader = React.memo(
|
||||
<Text
|
||||
style={{ color: theme.blue }}
|
||||
onPress={() => {
|
||||
navigation.navigate('Screen-Me')
|
||||
navigation.navigate('Screen-Me', {
|
||||
screen: 'Screen-Me-Root',
|
||||
params: { navigateAway: 'Screen-Me-Settings-UpdateRemote' }
|
||||
})
|
||||
}}
|
||||
>
|
||||
前往设置{' '}
|
||||
|
@ -61,7 +61,10 @@ const TimelineNotifications: React.FC<Props> = ({
|
||||
>
|
||||
<View style={styles.header}>
|
||||
<TimelineAvatar queryKey={queryKey} account={actualAccount} />
|
||||
<TimelineHeaderNotification notification={notification} />
|
||||
<TimelineHeaderNotification
|
||||
queryKey={queryKey}
|
||||
notification={notification}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{notification.status ? (
|
||||
|
@ -32,6 +32,17 @@ const TimelineActions: React.FC<Props> = ({ queryKey, status, reblog }) => {
|
||||
const mutation = useTimelineMutation({
|
||||
queryClient,
|
||||
onMutate: true,
|
||||
onSuccess: (_, params) => {
|
||||
const theParams = params as MutationVarsTimelineUpdateStatusProperty
|
||||
if (
|
||||
(queryKey[1].page === 'Bookmarks' &&
|
||||
theParams.payload.property === 'bookmarked') ||
|
||||
(queryKey[1].page === 'Favourites' &&
|
||||
theParams.payload.property === 'favourited')
|
||||
) {
|
||||
queryClient.invalidateQueries(queryKey)
|
||||
}
|
||||
},
|
||||
onError: (err: any, params, oldData) => {
|
||||
const correctParam = params as MutationVarsTimelineUpdateStatusProperty
|
||||
haptics('Error')
|
||||
|
@ -15,10 +15,8 @@ const TimelineCard: React.FC<Props> = ({ card }) => {
|
||||
|
||||
const [imageLoaded, setImageLoaded] = useState(false)
|
||||
useEffect(() => {
|
||||
const preFetch = () => Image.getSize(card.image, () => setImageLoaded(true))
|
||||
|
||||
if (card.image) {
|
||||
preFetch()
|
||||
Image.getSize(card.image, () => setImageLoaded(true))
|
||||
}
|
||||
}, [])
|
||||
const cardVisual = useMemo(() => {
|
||||
|
@ -15,7 +15,7 @@ export interface Props {
|
||||
setBottomSheetVisible: React.Dispatch<React.SetStateAction<boolean>>
|
||||
}
|
||||
|
||||
const HeaderDefaultActionsAccount: React.FC<Props> = ({
|
||||
const HeaderActionsAccount: React.FC<Props> = ({
|
||||
queryKey,
|
||||
account,
|
||||
setBottomSheetVisible
|
||||
@ -121,4 +121,4 @@ const HeaderDefaultActionsAccount: React.FC<Props> = ({
|
||||
)
|
||||
}
|
||||
|
||||
export default HeaderDefaultActionsAccount
|
||||
export default HeaderActionsAccount
|
@ -17,7 +17,7 @@ export interface Props {
|
||||
setBottomSheetVisible: React.Dispatch<React.SetStateAction<boolean>>
|
||||
}
|
||||
|
||||
const HeaderDefaultActionsDomain: React.FC<Props> = ({
|
||||
const HeaderActionsDomain: React.FC<Props> = ({
|
||||
queryKey,
|
||||
domain,
|
||||
setBottomSheetVisible
|
||||
@ -77,4 +77,4 @@ const HeaderDefaultActionsDomain: React.FC<Props> = ({
|
||||
)
|
||||
}
|
||||
|
||||
export default HeaderDefaultActionsDomain
|
||||
export default HeaderActionsDomain
|
@ -17,7 +17,7 @@ export interface Props {
|
||||
setBottomSheetVisible: React.Dispatch<React.SetStateAction<boolean>>
|
||||
}
|
||||
|
||||
const HeaderDefaultActionsStatus: React.FC<Props> = ({
|
||||
const HeaderActionsStatus: React.FC<Props> = ({
|
||||
queryKey,
|
||||
status,
|
||||
setBottomSheetVisible
|
||||
@ -156,4 +156,4 @@ const HeaderDefaultActionsStatus: React.FC<Props> = ({
|
||||
)
|
||||
}
|
||||
|
||||
export default HeaderDefaultActionsStatus
|
||||
export default HeaderActionsStatus
|
@ -0,0 +1,93 @@
|
||||
import BottomSheet from '@components/BottomSheet'
|
||||
import Icon from '@components/Icon'
|
||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||
import { getLocalAccount, getLocalUrl } from '@utils/slices/instancesSlice'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
import { Pressable, StyleSheet } from 'react-native'
|
||||
import { useSelector } from 'react-redux'
|
||||
import HeaderActionsAccount from './ActionsAccount'
|
||||
import HeaderActionsDomain from './ActionsDomain'
|
||||
import HeaderActionsStatus from './ActionsStatus'
|
||||
|
||||
export interface Props {
|
||||
queryKey: QueryKeyTimeline
|
||||
status: Mastodon.Status
|
||||
}
|
||||
|
||||
const HeaderActions = React.memo(
|
||||
({ queryKey, status }: Props) => {
|
||||
const { theme } = useTheme()
|
||||
|
||||
const localAccount = useSelector(getLocalAccount)
|
||||
const sameAccount = localAccount?.id === status.account.id
|
||||
|
||||
const localDomain = useSelector(getLocalUrl)
|
||||
const statusDomain = status.uri
|
||||
? status.uri.split(new RegExp(/\/\/(.*?)\//))[1]
|
||||
: ''
|
||||
const sameDomain = localDomain === statusDomain
|
||||
|
||||
const [modalVisible, setBottomSheetVisible] = useState(false)
|
||||
const onPress = useCallback(() => setBottomSheetVisible(true), [])
|
||||
const children = useMemo(
|
||||
() => (
|
||||
<Icon
|
||||
name='MoreHorizontal'
|
||||
color={theme.secondary}
|
||||
size={StyleConstants.Font.Size.M + 2}
|
||||
/>
|
||||
),
|
||||
[]
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Pressable style={styles.base} onPress={onPress} children={children} />
|
||||
{modalVisible && (
|
||||
<BottomSheet
|
||||
visible={modalVisible}
|
||||
handleDismiss={() => setBottomSheetVisible(false)}
|
||||
>
|
||||
{!sameAccount && (
|
||||
<HeaderActionsAccount
|
||||
queryKey={queryKey}
|
||||
account={status.account}
|
||||
setBottomSheetVisible={setBottomSheetVisible}
|
||||
/>
|
||||
)}
|
||||
|
||||
{sameAccount && (
|
||||
<HeaderActionsStatus
|
||||
queryKey={queryKey}
|
||||
status={status}
|
||||
setBottomSheetVisible={setBottomSheetVisible}
|
||||
/>
|
||||
)}
|
||||
|
||||
{!sameDomain && (
|
||||
<HeaderActionsDomain
|
||||
queryKey={queryKey}
|
||||
domain={statusDomain}
|
||||
setBottomSheetVisible={setBottomSheetVisible}
|
||||
/>
|
||||
)}
|
||||
</BottomSheet>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
},
|
||||
() => true
|
||||
)
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
base: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
paddingBottom: StyleConstants.Spacing.S
|
||||
}
|
||||
})
|
||||
|
||||
export default HeaderActions
|
@ -1,53 +1,20 @@
|
||||
import BottomSheet from '@components/BottomSheet'
|
||||
import Icon from '@components/Icon'
|
||||
import { getLocalUrl } from '@utils/slices/instancesSlice'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import HeaderDefaultActionsAccount from '@components/Timelines/Timeline/Shared/HeaderDefault/ActionsAccount'
|
||||
import HeaderDefaultActionsDomain from '@components/Timelines/Timeline/Shared/HeaderDefault/ActionsDomain'
|
||||
import HeaderDefaultActionsStatus from '@components/Timelines/Timeline/Shared/HeaderDefault/ActionsStatus'
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
import { Pressable, StyleSheet, View } from 'react-native'
|
||||
import { useSelector } from 'react-redux'
|
||||
import React from 'react'
|
||||
import { 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'
|
||||
|
||||
export interface Props {
|
||||
queryKey?: QueryKeyTimeline
|
||||
status: Mastodon.Status
|
||||
sameAccount: boolean
|
||||
}
|
||||
|
||||
const TimelineHeaderDefault: React.FC<Props> = ({
|
||||
queryKey,
|
||||
status,
|
||||
sameAccount
|
||||
}) => {
|
||||
const domain = status.uri
|
||||
? status.uri.split(new RegExp(/\/\/(.*?)\//))[1]
|
||||
: ''
|
||||
const { theme } = useTheme()
|
||||
|
||||
const localDomain = useSelector(getLocalUrl)
|
||||
const [modalVisible, setBottomSheetVisible] = useState(false)
|
||||
|
||||
const onPressAction = useCallback(() => setBottomSheetVisible(true), [])
|
||||
|
||||
const pressableAction = useMemo(
|
||||
() => (
|
||||
<Icon
|
||||
name='MoreHorizontal'
|
||||
color={theme.secondary}
|
||||
size={StyleConstants.Font.Size.M + 2}
|
||||
/>
|
||||
),
|
||||
[]
|
||||
)
|
||||
|
||||
const TimelineHeaderDefault: React.FC<Props> = ({ queryKey, status }) => {
|
||||
return (
|
||||
<View style={styles.base}>
|
||||
<View style={styles.accountAndMeta}>
|
||||
@ -60,44 +27,7 @@ const TimelineHeaderDefault: React.FC<Props> = ({
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{queryKey && (
|
||||
<Pressable
|
||||
style={styles.action}
|
||||
onPress={onPressAction}
|
||||
children={pressableAction}
|
||||
/>
|
||||
)}
|
||||
|
||||
{queryKey && modalVisible && (
|
||||
<BottomSheet
|
||||
visible={modalVisible}
|
||||
handleDismiss={() => setBottomSheetVisible(false)}
|
||||
>
|
||||
{!sameAccount && (
|
||||
<HeaderDefaultActionsAccount
|
||||
queryKey={queryKey}
|
||||
account={status.account}
|
||||
setBottomSheetVisible={setBottomSheetVisible}
|
||||
/>
|
||||
)}
|
||||
|
||||
{sameAccount && (
|
||||
<HeaderDefaultActionsStatus
|
||||
queryKey={queryKey}
|
||||
status={status}
|
||||
setBottomSheetVisible={setBottomSheetVisible}
|
||||
/>
|
||||
)}
|
||||
|
||||
{domain !== localDomain && (
|
||||
<HeaderDefaultActionsDomain
|
||||
queryKey={queryKey}
|
||||
domain={domain}
|
||||
setBottomSheetVisible={setBottomSheetVisible}
|
||||
/>
|
||||
)}
|
||||
</BottomSheet>
|
||||
)}
|
||||
{queryKey ? <HeaderActions queryKey={queryKey} status={status} /> : null}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@ -118,12 +48,6 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
created_at: {
|
||||
...StyleConstants.FontStyle.S
|
||||
},
|
||||
action: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
paddingBottom: StyleConstants.Spacing.S
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { RelationshipOutgoing } from '@components/Relationship'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import React from 'react'
|
||||
import React, { useMemo } from 'react'
|
||||
import { StyleSheet, View } from 'react-native'
|
||||
import HeaderSharedAccount from './HeaderShared/Account'
|
||||
import HeaderSharedApplication from './HeaderShared/Application'
|
||||
@ -8,15 +8,41 @@ 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'
|
||||
|
||||
export interface Props {
|
||||
queryKey: QueryKeyTimeline
|
||||
notification: Mastodon.Notification
|
||||
}
|
||||
|
||||
const TimelineHeaderNotification: React.FC<Props> = ({ notification }) => {
|
||||
const TimelineHeaderNotification: React.FC<Props> = ({
|
||||
queryKey,
|
||||
notification
|
||||
}) => {
|
||||
const actions = useMemo(() => {
|
||||
switch (notification.type) {
|
||||
case 'follow':
|
||||
return <RelationshipOutgoing id={notification.account.id} />
|
||||
case 'follow_request':
|
||||
return <RelationshipIncoming id={notification.account.id} />
|
||||
default:
|
||||
return notification.status ? (
|
||||
<HeaderActions queryKey={queryKey} status={notification.status} />
|
||||
) : null
|
||||
}
|
||||
}, [notification.type])
|
||||
return (
|
||||
<View style={styles.base}>
|
||||
<View style={styles.accountAndMeta}>
|
||||
<View
|
||||
style={{
|
||||
flex:
|
||||
notification.type === 'follow' ||
|
||||
notification.type === 'follow_request'
|
||||
? 1
|
||||
: 4
|
||||
}}
|
||||
>
|
||||
<HeaderSharedAccount
|
||||
account={
|
||||
notification.status
|
||||
@ -38,16 +64,17 @@ const TimelineHeaderNotification: React.FC<Props> = ({ notification }) => {
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{notification.type === 'follow' && (
|
||||
<View style={styles.relationship}>
|
||||
<RelationshipOutgoing id={notification.account.id} />
|
||||
</View>
|
||||
)}
|
||||
{notification.type === 'follow_request' && (
|
||||
<View style={styles.relationship}>
|
||||
<RelationshipIncoming id={notification.account.id} />
|
||||
</View>
|
||||
)}
|
||||
<View
|
||||
style={[
|
||||
styles.relationship,
|
||||
notification.type === 'follow' ||
|
||||
notification.type === 'follow_request'
|
||||
? { flexShrink: 1 }
|
||||
: { flex: 1 }
|
||||
]}
|
||||
>
|
||||
{actions}
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@ -55,13 +82,7 @@ const TimelineHeaderNotification: React.FC<Props> = ({ notification }) => {
|
||||
const styles = StyleSheet.create({
|
||||
base: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'flex-start'
|
||||
},
|
||||
accountAndMeta: {
|
||||
flex: 1,
|
||||
flexGrow: 1
|
||||
flexDirection: 'row'
|
||||
},
|
||||
meta: {
|
||||
flexDirection: 'row',
|
||||
@ -70,7 +91,6 @@ const styles = StyleSheet.create({
|
||||
marginBottom: StyleConstants.Spacing.S
|
||||
},
|
||||
relationship: {
|
||||
flexShrink: 1,
|
||||
marginLeft: StyleConstants.Spacing.M
|
||||
}
|
||||
})
|
||||
|
@ -8,15 +8,29 @@ import accountReducer from '@screens/Shared/Account/utils/reducer'
|
||||
import accountInitialState from '@screens/Shared/Account/utils/initialState'
|
||||
import AccountContext from '@screens/Shared/Account/utils/createContext'
|
||||
import { getLocalActiveIndex } from '@utils/slices/instancesSlice'
|
||||
import React, { useReducer, useRef, useState } from 'react'
|
||||
import React, { useEffect, useReducer, useRef, useState } from 'react'
|
||||
import { useSelector } from 'react-redux'
|
||||
import Animated, {
|
||||
useAnimatedScrollHandler,
|
||||
useSharedValue
|
||||
} from 'react-native-reanimated'
|
||||
import ComponentInstance from '@components/Instance'
|
||||
import { StackScreenProps } from '@react-navigation/stack'
|
||||
|
||||
const ScreenMeRoot: React.FC = () => {
|
||||
const ScreenMeRoot: React.FC<StackScreenProps<
|
||||
Nav.MeStackParamList,
|
||||
'Screen-Me-Root'
|
||||
>> = ({
|
||||
route: {
|
||||
params: { navigateAway }
|
||||
},
|
||||
navigation
|
||||
}) => {
|
||||
useEffect(() => {
|
||||
if (navigateAway) {
|
||||
navigation.navigate(navigateAway)
|
||||
}
|
||||
}, [navigateAway])
|
||||
const localActiveIndex = useSelector(getLocalActiveIndex)
|
||||
|
||||
const scrollRef = useRef<Animated.ScrollView>(null)
|
||||
|
@ -1,6 +1,6 @@
|
||||
import BottomSheet from '@components/BottomSheet'
|
||||
import { HeaderRight } from '@components/Header'
|
||||
import HeaderDefaultActionsAccount from '@components/Timelines/Timeline/Shared/HeaderDefault/ActionsAccount'
|
||||
import HeaderActionsAccount from '@components/Timelines/Timeline/Shared/HeaderActions/ActionsAccount'
|
||||
import { useAccountQuery } from '@utils/queryHooks/account'
|
||||
import { getLocalAccount } from '@utils/slices/instancesSlice'
|
||||
import React, { useEffect, useReducer, useState } from 'react'
|
||||
@ -77,7 +77,7 @@ const ScreenSharedAccount: React.FC<SharedAccountProp> = ({
|
||||
>
|
||||
{/* 添加到列表 */}
|
||||
{localAccount?.id !== account.id && (
|
||||
<HeaderDefaultActionsAccount
|
||||
<HeaderActionsAccount
|
||||
account={account}
|
||||
setBottomSheetVisible={setBottomSheetVisible}
|
||||
/>
|
||||
|
@ -381,7 +381,8 @@ const useTimelineMutation = ({
|
||||
onSettled,
|
||||
...(typeof onSuccess === 'function'
|
||||
? { onSuccess }
|
||||
: {
|
||||
: onSuccess
|
||||
? {
|
||||
onSuccess: (data, params) => {
|
||||
queryClient.cancelQueries(params.queryKey)
|
||||
|
||||
@ -397,7 +398,8 @@ const useTimelineMutation = ({
|
||||
break
|
||||
}
|
||||
}
|
||||
}),
|
||||
}
|
||||
: undefined),
|
||||
...(onMutate && {
|
||||
onMutate: params => {
|
||||
queryClient.cancelQueries(params.queryKey)
|
||||
|
@ -11,7 +11,6 @@ const updateStatus = ({
|
||||
}) => {
|
||||
switch (payload.property) {
|
||||
case 'poll':
|
||||
console.log(payload.data)
|
||||
if (reblog) {
|
||||
item.reblog!.poll = payload.data
|
||||
} else {
|
||||
|
@ -19,7 +19,7 @@ export const ManageThemeContext = createContext<ContextType>({
|
||||
|
||||
export const useTheme = () => useContext(ManageThemeContext)
|
||||
|
||||
const useColorSchemeDelay = (delay = 250) => {
|
||||
const useColorSchemeDelay = (delay = 500) => {
|
||||
const [colorScheme, setColorScheme] = React.useState(
|
||||
Appearance.getColorScheme()
|
||||
)
|
||||
|
@ -23,15 +23,15 @@ const themeColors: {
|
||||
} = {
|
||||
primary: {
|
||||
light: 'rgb(18, 18, 18)',
|
||||
dark: 'rgb(218, 218, 218)'
|
||||
dark: 'rgb(180, 180, 180)'
|
||||
},
|
||||
primaryOverlay: {
|
||||
light: 'rgb(250, 250, 250)',
|
||||
dark: 'rgb(218, 218, 218)'
|
||||
dark: 'rgb(180, 180, 180)'
|
||||
},
|
||||
secondary: {
|
||||
light: 'rgb(135, 135, 135)',
|
||||
dark: 'rgb(135, 135, 135)'
|
||||
dark: 'rgb(130, 130, 130)'
|
||||
},
|
||||
disabled: {
|
||||
light: 'rgb(200, 200, 200)',
|
||||
@ -48,30 +48,30 @@ const themeColors: {
|
||||
|
||||
background: {
|
||||
light: 'rgb(250, 250, 250)',
|
||||
dark: 'rgb(18, 18, 18)'
|
||||
dark: 'rgb(25, 25, 25)'
|
||||
},
|
||||
backgroundGradientStart: {
|
||||
light: 'rgba(250, 250, 250, 0.5)',
|
||||
dark: 'rgba(18, 18, 18, 0.5)'
|
||||
dark: 'rgba(25, 25, 25, 0.5)'
|
||||
},
|
||||
backgroundGradientEnd: {
|
||||
light: 'rgba(250, 250, 250, 1)',
|
||||
dark: 'rgba(18, 18, 18, 1)'
|
||||
dark: 'rgba(25, 25, 25, 1)'
|
||||
},
|
||||
backgroundOverlay: {
|
||||
light: 'rgba(18, 18, 18, 0.5)',
|
||||
light: 'rgba(25, 25, 25, 0.5)',
|
||||
dark: 'rgba(0, 0, 0, 0.5)'
|
||||
},
|
||||
border: {
|
||||
light: 'rgba(18, 18, 18, 0.3)',
|
||||
light: 'rgba(25, 25, 25, 0.3)',
|
||||
dark: 'rgba(255, 255, 255, 0.3)'
|
||||
},
|
||||
shimmerDefault: {
|
||||
light: 'rgba(18, 18, 18, 0.05)',
|
||||
light: 'rgba(25, 25, 25, 0.05)',
|
||||
dark: 'rgba(250, 250, 250, 0.05)'
|
||||
},
|
||||
shimmerHighlight: {
|
||||
light: 'rgba(18, 18, 18, 0.15)',
|
||||
light: 'rgba(25, 25, 25, 0.15)',
|
||||
dark: 'rgba(250, 250, 250, 0.15)'
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user