mirror of https://github.com/tooot-app/app
Updates
This commit is contained in:
parent
b679b56a0e
commit
7be25ae516
|
@ -74,7 +74,7 @@ const renderNode = ({
|
|||
)
|
||||
}
|
||||
} else {
|
||||
const domain = href.split(new RegExp(/:\/\/(.*?)\//))
|
||||
const domain = href.split(new RegExp(/:\/\/(.[^\/]+)/))
|
||||
return (
|
||||
<Text
|
||||
key={index}
|
||||
|
|
|
@ -19,7 +19,6 @@ export interface Props {
|
|||
toot?: Mastodon.Status
|
||||
account?: string
|
||||
disableRefresh?: boolean
|
||||
scrollEnabled?: boolean
|
||||
}
|
||||
|
||||
const Timeline: React.FC<Props> = ({
|
||||
|
@ -28,8 +27,7 @@ const Timeline: React.FC<Props> = ({
|
|||
list,
|
||||
toot,
|
||||
account,
|
||||
disableRefresh = false,
|
||||
scrollEnabled = true
|
||||
disableRefresh = false
|
||||
}) => {
|
||||
setFocusHandler(handleFocus => {
|
||||
const handleAppStateChange = (appState: string) => {
|
||||
|
@ -160,7 +158,6 @@ const Timeline: React.FC<Props> = ({
|
|||
renderItem={flRenderItem}
|
||||
onEndReached={flOnEndReach}
|
||||
keyExtractor={flKeyExtrator}
|
||||
scrollEnabled={scrollEnabled} // For timeline in Account view
|
||||
ListFooterComponent={flFooter}
|
||||
ListEmptyComponent={flItemEmptyComponent}
|
||||
ItemSeparatorComponent={flItemSeparatorComponent}
|
||||
|
|
|
@ -44,7 +44,7 @@ const TimelineDefault: React.FC<Props> = ({
|
|||
const tootOnPress = useCallback(
|
||||
() =>
|
||||
!isRemotePublic &&
|
||||
navigation.navigate('Screen-Shared-Toot', {
|
||||
navigation.push('Screen-Shared-Toot', {
|
||||
toot: actualStatus
|
||||
}),
|
||||
[]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useCallback } from 'react'
|
||||
import { Image, Pressable, StyleSheet } from 'react-native'
|
||||
import { useNavigation } from '@react-navigation/native'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useNavigation } from '@react-navigation/native'
|
||||
|
||||
export interface Props {
|
||||
queryKey?: App.QueryKey
|
||||
|
@ -13,7 +13,7 @@ const TimelineAvatar: React.FC<Props> = ({ queryKey, account }) => {
|
|||
// Need to fix go back root
|
||||
const onPress = useCallback(() => {
|
||||
queryKey &&
|
||||
navigation.navigate('Screen-Shared-Account', {
|
||||
navigation.push('Screen-Shared-Account', {
|
||||
id: account.id
|
||||
})
|
||||
}, [])
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useRef } from 'react'
|
||||
import { ScrollView } from 'react-native'
|
||||
import React, { useRef, useState } from 'react'
|
||||
import { Animated, ScrollView } from 'react-native'
|
||||
import { useSelector } from 'react-redux'
|
||||
|
||||
import { getLocalUrl } from '@utils/slices/instancesSlice'
|
||||
|
@ -10,6 +10,8 @@ import Collections from '@screens/Me/Root/Collections'
|
|||
import Settings from '@screens/Me/Root/Settings'
|
||||
import Logout from '@screens/Me/Root/Logout'
|
||||
import { useScrollToTop } from '@react-navigation/native'
|
||||
import { AccountState } from '../Shared/Account'
|
||||
import AccountNav from '../Shared/Account/Nav'
|
||||
|
||||
const ScreenMeRoot: React.FC = () => {
|
||||
const localRegistered = useSelector(getLocalUrl)
|
||||
|
@ -17,13 +19,34 @@ const ScreenMeRoot: React.FC = () => {
|
|||
const scrollRef = useRef<ScrollView>(null)
|
||||
useScrollToTop(scrollRef)
|
||||
|
||||
const scrollY = useRef(new Animated.Value(0)).current
|
||||
const [data, setData] = useState<Mastodon.Account>()
|
||||
|
||||
return (
|
||||
<ScrollView ref={scrollRef} keyboardShouldPersistTaps='handled'>
|
||||
{localRegistered ? <MyInfo /> : <Login />}
|
||||
{localRegistered && <Collections />}
|
||||
<Settings />
|
||||
{localRegistered && <Logout />}
|
||||
</ScrollView>
|
||||
<>
|
||||
{localRegistered && data ? (
|
||||
<AccountNav
|
||||
accountState={{ headerRatio: 0.4 } as AccountState}
|
||||
scrollY={scrollY}
|
||||
account={data}
|
||||
/>
|
||||
) : null}
|
||||
<ScrollView
|
||||
ref={scrollRef}
|
||||
keyboardShouldPersistTaps='handled'
|
||||
bounces={false}
|
||||
onScroll={Animated.event(
|
||||
[{ nativeEvent: { contentOffset: { y: scrollY } } }],
|
||||
{ useNativeDriver: false }
|
||||
)}
|
||||
scrollEventThrottle={8}
|
||||
>
|
||||
{localRegistered ? <MyInfo setData={setData} /> : <Login />}
|
||||
{localRegistered && <Collections />}
|
||||
<Settings />
|
||||
{localRegistered && <Logout />}
|
||||
</ScrollView>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React from 'react'
|
||||
import React, { useEffect } from 'react'
|
||||
import { useQuery } from 'react-query'
|
||||
|
||||
import { accountFetch } from '@utils/fetches/accountFetch'
|
||||
|
@ -6,14 +6,28 @@ import AccountHeader from '@screens/Shared/Account/Header'
|
|||
import AccountInformation from '@screens/Shared/Account/Information'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { getLocalAccountId } from '@utils/slices/instancesSlice'
|
||||
import { AccountState } from '@root/screens/Shared/Account'
|
||||
|
||||
const MyInfo: React.FC = () => {
|
||||
export interface Props {
|
||||
setData: React.Dispatch<React.SetStateAction<Mastodon.Account | undefined>>
|
||||
}
|
||||
|
||||
const MyInfo: React.FC<Props> = ({ setData }) => {
|
||||
const localAccountId = useSelector(getLocalAccountId)
|
||||
const { data } = useQuery(['Account', { id: localAccountId }], accountFetch)
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
setData(data)
|
||||
}
|
||||
}, [data])
|
||||
|
||||
return (
|
||||
<>
|
||||
<AccountHeader uri={data?.header} limitHeight />
|
||||
<AccountHeader
|
||||
accountState={{ headerRatio: 0.4 } as AccountState}
|
||||
account={data}
|
||||
limitHeight
|
||||
/>
|
||||
<AccountInformation account={data} />
|
||||
</>
|
||||
)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { createContext, Dispatch, useReducer, useRef } from 'react'
|
||||
import React, { useReducer, useRef } from 'react'
|
||||
import { Animated, ScrollView } from 'react-native'
|
||||
|
||||
// import * as relationshipsSlice from 'src/stacks/common/relationshipsSlice'
|
||||
|
@ -62,11 +62,6 @@ const accountReducer = (
|
|||
throw new Error('Unexpected action')
|
||||
}
|
||||
}
|
||||
type ContextType = {
|
||||
accountState: AccountState
|
||||
accountDispatch: Dispatch<AccountAction>
|
||||
}
|
||||
export const AccountContext = createContext<ContextType>({} as ContextType)
|
||||
|
||||
const ScreenSharedAccount: React.FC<Props> = ({
|
||||
route: {
|
||||
|
@ -83,23 +78,38 @@ const ScreenSharedAccount: React.FC<Props> = ({
|
|||
)
|
||||
|
||||
return (
|
||||
<AccountContext.Provider value={{ accountState, accountDispatch }}>
|
||||
<AccountNav scrollY={scrollY} account={data} />
|
||||
<AccountSegmentedControl scrollY={scrollY} />
|
||||
<>
|
||||
<AccountNav
|
||||
accountState={accountState}
|
||||
scrollY={scrollY}
|
||||
account={data}
|
||||
/>
|
||||
<AccountSegmentedControl
|
||||
accountState={accountState}
|
||||
accountDispatch={accountDispatch}
|
||||
scrollY={scrollY}
|
||||
/>
|
||||
<ScrollView
|
||||
contentContainerStyle={{ zIndex: 99 }}
|
||||
bounces={false}
|
||||
onScroll={Animated.event(
|
||||
[{ nativeEvent: { contentOffset: { y: scrollY } } }],
|
||||
{ useNativeDriver: false }
|
||||
)}
|
||||
scrollEventThrottle={16}
|
||||
scrollEventThrottle={8}
|
||||
>
|
||||
<AccountHeader uri={data?.header} />
|
||||
<AccountInformation account={data} />
|
||||
<AccountToots id={id} />
|
||||
<AccountHeader
|
||||
accountState={accountState}
|
||||
accountDispatch={accountDispatch}
|
||||
account={data}
|
||||
/>
|
||||
<AccountInformation accountDispatch={accountDispatch} account={data} />
|
||||
<AccountToots
|
||||
accountState={accountState}
|
||||
accountDispatch={accountDispatch}
|
||||
id={id}
|
||||
/>
|
||||
</ScrollView>
|
||||
</AccountContext.Provider>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,25 +1,39 @@
|
|||
import React, { useContext, useEffect, useRef } from 'react'
|
||||
import React, { Dispatch, useEffect, useRef, useState } from 'react'
|
||||
import { Animated, Dimensions, Image, StyleSheet } from 'react-native'
|
||||
import { AccountContext } from '../Account'
|
||||
import { AccountAction, AccountState } from '../Account'
|
||||
|
||||
export interface Props {
|
||||
uri?: Mastodon.Account['header']
|
||||
accountState: AccountState
|
||||
accountDispatch?: Dispatch<AccountAction>
|
||||
account?: Mastodon.Account
|
||||
limitHeight?: boolean
|
||||
}
|
||||
|
||||
const AccountHeader: React.FC<Props> = ({ uri, limitHeight = false }) => {
|
||||
const { accountState, accountDispatch } = useContext(AccountContext)
|
||||
const AccountHeader: React.FC<Props> = ({
|
||||
accountState,
|
||||
accountDispatch,
|
||||
account,
|
||||
limitHeight = false
|
||||
}) => {
|
||||
const [imageShown, setImageShown] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
if (uri) {
|
||||
if (uri.includes('/headers/original/missing.png')) {
|
||||
if (account?.header) {
|
||||
if (account.header.includes('/headers/original/missing.png')) {
|
||||
animateNewSize(accountState.headerRatio)
|
||||
} else {
|
||||
if (account.header !== account.header_static) {
|
||||
setImageShown(false)
|
||||
}
|
||||
Image.getSize(
|
||||
uri,
|
||||
account.header,
|
||||
(width, height) => {
|
||||
if (!limitHeight) {
|
||||
accountDispatch({ type: 'headerRatio', payload: height / width })
|
||||
accountDispatch &&
|
||||
accountDispatch({
|
||||
type: 'headerRatio',
|
||||
payload: height / width
|
||||
})
|
||||
}
|
||||
animateNewSize(
|
||||
limitHeight ? accountState.headerRatio : height / width
|
||||
|
@ -30,10 +44,12 @@ const AccountHeader: React.FC<Props> = ({ uri, limitHeight = false }) => {
|
|||
}
|
||||
)
|
||||
}
|
||||
} else {
|
||||
animateNewSize(accountState.headerRatio)
|
||||
}
|
||||
}, [uri])
|
||||
}, [account])
|
||||
|
||||
const theImage = imageShown ? (
|
||||
<Image source={{ uri: account?.header }} style={styles.image} />
|
||||
) : null
|
||||
|
||||
const windowWidth = Dimensions.get('window').width
|
||||
const imageHeight = useRef(
|
||||
|
@ -44,12 +60,16 @@ const AccountHeader: React.FC<Props> = ({ uri, limitHeight = false }) => {
|
|||
toValue: windowWidth * ratio,
|
||||
duration: 350,
|
||||
useNativeDriver: false
|
||||
}).start()
|
||||
}).start(({ finished }) => {
|
||||
if (finished) {
|
||||
setImageShown(true)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<Animated.View style={[styles.imageContainer, { height: imageHeight }]}>
|
||||
<Image source={{ uri: uri }} style={styles.image} />
|
||||
{theImage}
|
||||
</Animated.View>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { createRef, useContext, useEffect, useState } from 'react'
|
||||
import React, { createRef, Dispatch, useEffect, useState } from 'react'
|
||||
import { Animated, Image, StyleSheet, Text, View } from 'react-native'
|
||||
import { createShimmerPlaceholder } from 'react-native-shimmer-placeholder'
|
||||
import { Feather } from '@expo/vector-icons'
|
||||
|
@ -9,14 +9,14 @@ import { StyleConstants } from '@utils/styles/constants'
|
|||
import { useTranslation } from 'react-i18next'
|
||||
import Emojis from '@components/Timelines/Timeline/Shared/Emojis'
|
||||
import { LinearGradient } from 'expo-linear-gradient'
|
||||
import { AccountContext } from '../Account'
|
||||
import { AccountAction } from '../Account'
|
||||
|
||||
export interface Props {
|
||||
accountDispatch?: Dispatch<AccountAction>
|
||||
account: Mastodon.Account | undefined
|
||||
}
|
||||
|
||||
const AccountInformation: React.FC<Props> = ({ account }) => {
|
||||
const { accountDispatch } = useContext(AccountContext)
|
||||
const AccountInformation: React.FC<Props> = ({ accountDispatch, account }) => {
|
||||
const { t } = useTranslation('sharedAccount')
|
||||
const { theme } = useTheme()
|
||||
const [avatarLoaded, setAvatarLoaded] = useState(false)
|
||||
|
@ -48,6 +48,7 @@ const AccountInformation: React.FC<Props> = ({ account }) => {
|
|||
<View
|
||||
style={styles.information}
|
||||
onLayout={({ nativeEvent }) =>
|
||||
accountDispatch &&
|
||||
accountDispatch({
|
||||
type: 'informationLayout',
|
||||
payload: {
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import Emojis from '@root/components/Timelines/Timeline/Shared/Emojis'
|
||||
import { StyleConstants } from '@root/utils/styles/constants'
|
||||
import { useTheme } from '@root/utils/styles/ThemeManager'
|
||||
import React, { useContext } from 'react'
|
||||
import React from 'react'
|
||||
import { Animated, Dimensions, StyleSheet, Text, View } from 'react-native'
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
||||
import { AccountContext } from '../Account'
|
||||
import { AccountState } from '../Account'
|
||||
|
||||
export interface Props {
|
||||
accountState: AccountState
|
||||
scrollY: Animated.Value
|
||||
account: Mastodon.Account | undefined
|
||||
}
|
||||
|
||||
const AccountNav: React.FC<Props> = ({ scrollY, account }) => {
|
||||
const { accountState } = useContext(AccountContext)
|
||||
const AccountNav: React.FC<Props> = ({ accountState, scrollY, account }) => {
|
||||
const { theme } = useTheme()
|
||||
const headerHeight = useSafeAreaInsets().top + 44
|
||||
|
||||
|
|
|
@ -1,18 +1,23 @@
|
|||
import SegmentedControl from '@react-native-community/segmented-control'
|
||||
import { StyleConstants } from '@root/utils/styles/constants'
|
||||
import { useTheme } from '@root/utils/styles/ThemeManager'
|
||||
import React, { useContext } from 'react'
|
||||
import React, { Dispatch } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Animated, StyleSheet } from 'react-native'
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
||||
import { AccountContext } from '../Account'
|
||||
import { AccountAction, AccountState } from '../Account'
|
||||
|
||||
export interface Props {
|
||||
accountState: AccountState
|
||||
accountDispatch: Dispatch<AccountAction>
|
||||
scrollY: Animated.Value
|
||||
}
|
||||
|
||||
const AccountSegmentedControl: React.FC<Props> = ({ scrollY }) => {
|
||||
const { accountState, accountDispatch } = useContext(AccountContext)
|
||||
const AccountSegmentedControl: React.FC<Props> = ({
|
||||
accountState,
|
||||
accountDispatch,
|
||||
scrollY
|
||||
}) => {
|
||||
const { t } = useTranslation('sharedAccount')
|
||||
const { mode, theme } = useTheme()
|
||||
|
||||
|
@ -69,12 +74,10 @@ const AccountSegmentedControl: React.FC<Props> = ({ scrollY }) => {
|
|||
const styles = StyleSheet.create({
|
||||
base: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
right: 0,
|
||||
zIndex: 99,
|
||||
borderTopWidth: StyleSheet.hairlineWidth,
|
||||
padding: StyleConstants.Spacing.Global.PagePadding
|
||||
padding: StyleConstants.Spacing.Global.PagePadding,
|
||||
paddingBottom: StyleConstants.Spacing.Global.PagePadding * 3
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -1,32 +1,29 @@
|
|||
import React, { useCallback, useContext, useState } from 'react'
|
||||
import React, { Dispatch, useCallback, useState } from 'react'
|
||||
import { Dimensions, StyleSheet } from 'react-native'
|
||||
import { TabView, SceneMap } from 'react-native-tab-view'
|
||||
import { SceneMap, TabView } from 'react-native-tab-view'
|
||||
|
||||
import Timeline from '@components/Timelines/Timeline'
|
||||
import { AccountContext } from '../Account'
|
||||
import { AccountAction, AccountState } from '../Account'
|
||||
import { StyleConstants } from '@root/utils/styles/constants'
|
||||
|
||||
export interface Props {
|
||||
accountState: AccountState
|
||||
accountDispatch: Dispatch<AccountAction>
|
||||
id: Mastodon.Account['id']
|
||||
}
|
||||
|
||||
const AccountToots: React.FC<Props> = ({ id }) => {
|
||||
const { accountState, accountDispatch } = useContext(AccountContext)
|
||||
|
||||
const AccountToots: React.FC<Props> = ({
|
||||
accountState,
|
||||
accountDispatch,
|
||||
id
|
||||
}) => {
|
||||
const [routes] = useState([
|
||||
{ key: 'Account_Default' },
|
||||
{ key: 'Account_All' },
|
||||
{ key: 'Account_Media' }
|
||||
])
|
||||
const singleScene = useCallback(
|
||||
({ route }) => (
|
||||
<Timeline
|
||||
page={route.key}
|
||||
account={id}
|
||||
disableRefresh
|
||||
scrollEnabled={false}
|
||||
/>
|
||||
),
|
||||
({ route }) => <Timeline page={route.key} account={id} disableRefresh />,
|
||||
[]
|
||||
)
|
||||
const renderScene = SceneMap({
|
||||
|
|
|
@ -51,6 +51,7 @@ const ScreenSharedWebview: React.FC<Props> = ({
|
|||
{() => (
|
||||
<>
|
||||
<WebView
|
||||
allowsBackForwardNavigationGestures
|
||||
ref={webview}
|
||||
source={{ uri }}
|
||||
decelerationRate='normal'
|
||||
|
|
Loading…
Reference in New Issue