mirror of
https://github.com/tooot-app/app
synced 2025-06-05 22:19:13 +02:00
Use svg icons instead of expo ones
Possibility to control `strokeWidth`
This commit is contained in:
12
App.tsx
12
App.tsx
@ -57,7 +57,7 @@ enableScreens()
|
|||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
startingLog('log', 'rendering App')
|
startingLog('log', 'rendering App')
|
||||||
const [appLoaded, setAppLoaded] = useState(false)
|
const [appLoaded, setAppLoaded] = useState(false)
|
||||||
const [localCorrupt, setLocalCorrupt] = useState(false)
|
const [localCorrupt, setLocalCorrupt] = useState<string>()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const onlineState = onlineManager.setEventListener(setOnline => {
|
const onlineState = onlineManager.setEventListener(setOnline => {
|
||||||
@ -118,16 +118,20 @@ const App: React.FC = () => {
|
|||||||
startingLog('log', 'local credential check passed')
|
startingLog('log', 'local credential check passed')
|
||||||
if (res.body.id !== store.getState().instances.local.account.id) {
|
if (res.body.id !== store.getState().instances.local.account.id) {
|
||||||
store.dispatch(resetLocal())
|
store.dispatch(resetLocal())
|
||||||
setLocalCorrupt(true)
|
setLocalCorrupt('')
|
||||||
}
|
}
|
||||||
setAppLoaded(true)
|
setAppLoaded(true)
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
startingLog('error', 'local credential check failed')
|
startingLog('error', 'local credential check failed')
|
||||||
if (error.status && typeof error.status === 'number') {
|
if (
|
||||||
|
error.status &&
|
||||||
|
typeof error.status === 'number' &&
|
||||||
|
error.status === 401
|
||||||
|
) {
|
||||||
store.dispatch(resetLocal())
|
store.dispatch(resetLocal())
|
||||||
setLocalCorrupt(true)
|
|
||||||
}
|
}
|
||||||
|
setLocalCorrupt(error.data.error)
|
||||||
setAppLoaded(true)
|
setAppLoaded(true)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
"test": "jest"
|
"test": "jest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@expo/vector-icons": "^12.0.0",
|
|
||||||
"@react-native-community/masked-view": "0.1.10",
|
"@react-native-community/masked-view": "0.1.10",
|
||||||
"@react-native-community/netinfo": "^5.9.9",
|
"@react-native-community/netinfo": "^5.9.9",
|
||||||
"@react-native-community/segmented-control": "2.2.1",
|
"@react-native-community/segmented-control": "2.2.1",
|
||||||
@ -50,6 +49,7 @@
|
|||||||
"react-native": "https://github.com/expo/react-native/archive/sdk-40.0.0.tar.gz",
|
"react-native": "https://github.com/expo/react-native/archive/sdk-40.0.0.tar.gz",
|
||||||
"react-native-animated-spinkit": "^1.4.2",
|
"react-native-animated-spinkit": "^1.4.2",
|
||||||
"react-native-expo-image-cache": "^4.1.0",
|
"react-native-expo-image-cache": "^4.1.0",
|
||||||
|
"react-native-feather": "^1.0.2",
|
||||||
"react-native-gesture-handler": "~1.8.0",
|
"react-native-gesture-handler": "~1.8.0",
|
||||||
"react-native-htmlview": "^0.16.0",
|
"react-native-htmlview": "^0.16.0",
|
||||||
"react-native-image-zoom-viewer": "^3.0.1",
|
"react-native-image-zoom-viewer": "^3.0.1",
|
||||||
|
2
src/@types/app.d.ts
vendored
2
src/@types/app.d.ts
vendored
@ -66,7 +66,7 @@ declare namespace QueryKey {
|
|||||||
{
|
{
|
||||||
hashtag?: Mastodon.Tag['name']
|
hashtag?: Mastodon.Tag['name']
|
||||||
list?: Mastodon.List['id']
|
list?: Mastodon.List['id']
|
||||||
toot?: Mastodon.Status
|
toot?: Mastodon.Status['id']
|
||||||
account?: Mastodon.Account['id']
|
account?: Mastodon.Account['id']
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
3
src/@types/untyped.d.ts
vendored
3
src/@types/untyped.d.ts
vendored
@ -1,3 +1,4 @@
|
|||||||
declare module 'gl-react-blurhash'
|
declare module 'gl-react-blurhash'
|
||||||
declare module 'react-native-toast-message'
|
declare module 'react-native-feather'
|
||||||
declare module 'react-native-htmlview'
|
declare module 'react-native-htmlview'
|
||||||
|
declare module 'react-native-toast-message'
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import client from '@api/client'
|
import client from '@api/client'
|
||||||
import { Feather } from '@expo/vector-icons'
|
import Icon from '@components/Icon'
|
||||||
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
|
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
|
||||||
import {
|
import {
|
||||||
NavigationContainer,
|
NavigationContainer,
|
||||||
@ -37,7 +37,7 @@ export type RootStackParamList = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
localCorrupt: boolean
|
localCorrupt?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const Index: React.FC<Props> = ({ localCorrupt }) => {
|
const Index: React.FC<Props> = ({ localCorrupt }) => {
|
||||||
@ -71,7 +71,7 @@ const Index: React.FC<Props> = ({ localCorrupt }) => {
|
|||||||
? toast({
|
? toast({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
message: '登录已过期',
|
message: '登录已过期',
|
||||||
description: '请重新登录',
|
description: localCorrupt.length ? localCorrupt : undefined,
|
||||||
autoHide: false
|
autoHide: false
|
||||||
})
|
})
|
||||||
: undefined
|
: undefined
|
||||||
@ -171,27 +171,27 @@ const Index: React.FC<Props> = ({ localCorrupt }) => {
|
|||||||
let updateColor: string = color
|
let updateColor: string = color
|
||||||
switch (route.name) {
|
switch (route.name) {
|
||||||
case 'Screen-Local':
|
case 'Screen-Local':
|
||||||
name = 'home'
|
name = 'Home'
|
||||||
break
|
break
|
||||||
case 'Screen-Public':
|
case 'Screen-Public':
|
||||||
name = 'globe'
|
name = 'Globe'
|
||||||
!focused && (updateColor = theme.secondary)
|
!focused && (updateColor = theme.secondary)
|
||||||
break
|
break
|
||||||
case 'Screen-Post':
|
case 'Screen-Post':
|
||||||
name = 'plus'
|
name = 'Plus'
|
||||||
break
|
break
|
||||||
case 'Screen-Notifications':
|
case 'Screen-Notifications':
|
||||||
name = 'bell'
|
name = 'Bell'
|
||||||
break
|
break
|
||||||
case 'Screen-Me':
|
case 'Screen-Me':
|
||||||
name = focused ? 'meh' : 'smile'
|
name = focused ? 'Meh' : 'Smile'
|
||||||
!focused && (updateColor = theme.secondary)
|
!focused && (updateColor = theme.secondary)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
name = 'alert-octagon'
|
name = 'AlertOctagon'
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
return <Feather name={name} size={size} color={updateColor} />
|
return <Icon name={name} size={size} color={updateColor} />
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
[]
|
[]
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
import { Feather } from '@expo/vector-icons'
|
import Icon from '@components/Icon'
|
||||||
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
|
import layoutAnimation from '@utils/styles/layoutAnimation'
|
||||||
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import React, { useEffect, useMemo } from 'react'
|
import React, { useEffect, useMemo } from 'react'
|
||||||
import {
|
import {
|
||||||
Pressable,
|
Pressable,
|
||||||
@ -9,9 +12,6 @@ import {
|
|||||||
ViewStyle
|
ViewStyle
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import { Chase } from 'react-native-animated-spinkit'
|
import { Chase } from 'react-native-animated-spinkit'
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
|
||||||
import layoutAnimation from '@root/utils/styles/layoutAnimation'
|
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
style?: StyleProp<ViewStyle>
|
style?: StyleProp<ViewStyle>
|
||||||
@ -23,6 +23,7 @@ export interface Props {
|
|||||||
destructive?: boolean
|
destructive?: boolean
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
|
|
||||||
|
strokeWidth?: number
|
||||||
size?: 'S' | 'M' | 'L'
|
size?: 'S' | 'M' | 'L'
|
||||||
spacing?: 'XS' | 'S' | 'M' | 'L'
|
spacing?: 'XS' | 'S' | 'M' | 'L'
|
||||||
round?: boolean
|
round?: boolean
|
||||||
@ -38,6 +39,7 @@ const Button: React.FC<Props> = ({
|
|||||||
loading = false,
|
loading = false,
|
||||||
destructive = false,
|
destructive = false,
|
||||||
disabled = false,
|
disabled = false,
|
||||||
|
strokeWidth,
|
||||||
size = 'M',
|
size = 'M',
|
||||||
spacing = 'S',
|
spacing = 'S',
|
||||||
round = false,
|
round = false,
|
||||||
@ -78,12 +80,12 @@ const Button: React.FC<Props> = ({
|
|||||||
case 'icon':
|
case 'icon':
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Feather
|
<Icon
|
||||||
name={content as any}
|
name={content}
|
||||||
size={StyleConstants.Font.Size[size] * (size === 'L' ? 1.25 : 1)}
|
|
||||||
color={colorContent}
|
color={colorContent}
|
||||||
|
strokeWidth={strokeWidth}
|
||||||
style={{ opacity: loading ? 0 : 1 }}
|
style={{ opacity: loading ? 0 : 1 }}
|
||||||
testID='icon'
|
size={StyleConstants.Font.Size[size] * (size === 'L' ? 1.25 : 1)}
|
||||||
/>
|
/>
|
||||||
{loading && loadingSpinkit}
|
{loading && loadingSpinkit}
|
||||||
</>
|
</>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import React, { useMemo } from 'react'
|
import Icon from '@components/Icon'
|
||||||
import { Pressable, StyleSheet, Text } from 'react-native'
|
|
||||||
import { Feather } from '@expo/vector-icons'
|
|
||||||
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, { useMemo } from 'react'
|
||||||
|
import { Pressable, StyleSheet, Text } from 'react-native'
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
type?: 'icon' | 'text'
|
type?: 'icon' | 'text'
|
||||||
@ -18,9 +18,9 @@ const HeaderLeft: React.FC<Props> = ({ type = 'icon', content, onPress }) => {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case 'icon':
|
case 'icon':
|
||||||
return (
|
return (
|
||||||
<Feather
|
<Icon
|
||||||
name={content || ('chevron-left' as any)}
|
|
||||||
color={theme.primary}
|
color={theme.primary}
|
||||||
|
name={content || 'ChevronLeft'}
|
||||||
size={StyleConstants.Spacing.M * 1.25}
|
size={StyleConstants.Spacing.M * 1.25}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
|
import Icon from '@components/Icon'
|
||||||
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import React, { useMemo } from 'react'
|
import React, { useMemo } from 'react'
|
||||||
import { Pressable, StyleSheet, Text, View } from 'react-native'
|
import { Pressable, StyleSheet, Text, View } from 'react-native'
|
||||||
import { Chase } from 'react-native-animated-spinkit'
|
import { Chase } from 'react-native-animated-spinkit'
|
||||||
import { Feather } from '@expo/vector-icons'
|
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
type?: 'icon' | 'text'
|
type?: 'icon' | 'text'
|
||||||
content?: string
|
content: string
|
||||||
|
|
||||||
loading?: boolean
|
loading?: boolean
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
@ -41,11 +41,11 @@ const HeaderRight: React.FC<Props> = ({
|
|||||||
case 'icon':
|
case 'icon':
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Feather
|
<Icon
|
||||||
name={content as any}
|
name={content}
|
||||||
color={disabled ? theme.secondary : theme.primary}
|
|
||||||
size={StyleConstants.Spacing.M * 1.25}
|
|
||||||
style={{ opacity: loading ? 0 : 1 }}
|
style={{ opacity: loading ? 0 : 1 }}
|
||||||
|
size={StyleConstants.Spacing.M * 1.25}
|
||||||
|
color={disabled ? theme.secondary : theme.primary}
|
||||||
/>
|
/>
|
||||||
{loading && loadingSpinkit}
|
{loading && loadingSpinkit}
|
||||||
</>
|
</>
|
||||||
|
45
src/components/Icon.tsx
Normal file
45
src/components/Icon.tsx
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import React, { createElement } from 'react'
|
||||||
|
import { StyleProp, View, ViewStyle } from 'react-native'
|
||||||
|
import * as FeatherIcon from 'react-native-feather'
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
name: string
|
||||||
|
size: number
|
||||||
|
color: string
|
||||||
|
strokeWidth?: number
|
||||||
|
inline?: boolean // When used in line of text, need to drag it down
|
||||||
|
style?: StyleProp<ViewStyle>
|
||||||
|
}
|
||||||
|
|
||||||
|
const Icon: React.FC<Props> = ({
|
||||||
|
name,
|
||||||
|
size,
|
||||||
|
color,
|
||||||
|
strokeWidth = 2,
|
||||||
|
inline = false,
|
||||||
|
style
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
style,
|
||||||
|
{
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginBottom: inline ? -size * 0.125 : undefined
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{createElement(FeatherIcon[name], {
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
|
color,
|
||||||
|
strokeWidth
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Icon
|
@ -1,4 +1,4 @@
|
|||||||
import { Feather } from '@expo/vector-icons'
|
import Icon from '@components/Icon'
|
||||||
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 { ColorDefinitions } from '@utils/styles/themes'
|
import { ColorDefinitions } from '@utils/styles/themes'
|
||||||
@ -18,7 +18,7 @@ export interface Props {
|
|||||||
switchDisabled?: boolean
|
switchDisabled?: boolean
|
||||||
switchOnValueChange?: () => void
|
switchOnValueChange?: () => void
|
||||||
|
|
||||||
iconBack?: 'chevron-right' | 'check'
|
iconBack?: 'ChevronRight' | 'Check'
|
||||||
iconBackColor?: ColorDefinitions
|
iconBackColor?: ColorDefinitions
|
||||||
|
|
||||||
loading?: boolean
|
loading?: boolean
|
||||||
@ -63,7 +63,7 @@ const MenuRow: React.FC<Props> = ({
|
|||||||
<View style={styles.core}>
|
<View style={styles.core}>
|
||||||
<View style={styles.front}>
|
<View style={styles.front}>
|
||||||
{iconFront && (
|
{iconFront && (
|
||||||
<Feather
|
<Icon
|
||||||
name={iconFront}
|
name={iconFront}
|
||||||
size={StyleConstants.Font.Size.M + 2}
|
size={StyleConstants.Font.Size.M + 2}
|
||||||
color={theme[iconFrontColor]}
|
color={theme[iconFrontColor]}
|
||||||
@ -116,7 +116,7 @@ const MenuRow: React.FC<Props> = ({
|
|||||||
) : null}
|
) : null}
|
||||||
{iconBack ? (
|
{iconBack ? (
|
||||||
<>
|
<>
|
||||||
<Feather
|
<Icon
|
||||||
name={iconBack}
|
name={iconBack}
|
||||||
size={StyleConstants.Font.Size.M + 2}
|
size={StyleConstants.Font.Size.M + 2}
|
||||||
color={theme[iconBackColor]}
|
color={theme[iconBackColor]}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
import Icon from '@components/Icon'
|
||||||
import openLink from '@components/openLink'
|
import openLink from '@components/openLink'
|
||||||
import ParseEmojis from '@components/Parse/Emojis'
|
import ParseEmojis from '@components/Parse/Emojis'
|
||||||
import { Feather } from '@expo/vector-icons'
|
|
||||||
import { useNavigation } from '@react-navigation/native'
|
import { useNavigation } from '@react-navigation/native'
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
import layoutAnimation from '@utils/styles/layoutAnimation'
|
import layoutAnimation from '@utils/styles/layoutAnimation'
|
||||||
@ -96,10 +96,11 @@ const renderNode = ({
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
{!shouldBeTag ? (
|
{!shouldBeTag ? (
|
||||||
<Feather
|
<Icon
|
||||||
name='external-link'
|
inline
|
||||||
size={StyleConstants.Font.Size[size]}
|
|
||||||
color={theme.blue}
|
color={theme.blue}
|
||||||
|
name='ExternalLink'
|
||||||
|
size={StyleConstants.Font.Size[size]}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
{content || (showFullLink ? href : domain[1])}
|
{content || (showFullLink ? href : domain[1])}
|
||||||
@ -166,37 +167,45 @@ const ParseHTML: React.FC<Props> = ({
|
|||||||
|
|
||||||
const [heightOriginal, setHeightOriginal] = useState<number>()
|
const [heightOriginal, setHeightOriginal] = useState<number>()
|
||||||
const [heightTruncated, setHeightTruncated] = useState<number>()
|
const [heightTruncated, setHeightTruncated] = useState<number>()
|
||||||
const [allowExpand, setAllowExpand] = useState(
|
const [allowExpand, setAllowExpand] = useState(false)
|
||||||
numberOfLines === 0 ? true : undefined
|
|
||||||
)
|
|
||||||
const [showAllText, setShowAllText] = useState(false)
|
const [showAllText, setShowAllText] = useState(false)
|
||||||
|
|
||||||
const calNumberOfLines = useMemo(() => {
|
const calNumberOfLines = useMemo(() => {
|
||||||
if (heightOriginal) {
|
if (numberOfLines === 0) {
|
||||||
if (!heightTruncated) {
|
// For spoilers without calculation
|
||||||
return numberOfLines
|
return showAllText ? undefined : 1
|
||||||
} else {
|
} else {
|
||||||
if (allowExpand && !showAllText) {
|
if (heightOriginal) {
|
||||||
|
if (!heightTruncated) {
|
||||||
return numberOfLines
|
return numberOfLines
|
||||||
} else {
|
} else {
|
||||||
return undefined
|
if (allowExpand && !showAllText) {
|
||||||
|
return numberOfLines
|
||||||
|
} else {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return undefined
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return undefined
|
|
||||||
}
|
}
|
||||||
}, [heightOriginal, heightTruncated, allowExpand, showAllText])
|
}, [heightOriginal, heightTruncated, allowExpand, showAllText])
|
||||||
|
|
||||||
const onLayout = useCallback(
|
const onLayout = useCallback(
|
||||||
({ nativeEvent }) => {
|
({ nativeEvent }) => {
|
||||||
if (!heightOriginal) {
|
if (numberOfLines === 0) {
|
||||||
setHeightOriginal(nativeEvent.layout.height)
|
// For spoilers without calculation
|
||||||
|
setAllowExpand(true)
|
||||||
} else {
|
} else {
|
||||||
if (!heightTruncated) {
|
if (!heightOriginal) {
|
||||||
setHeightTruncated(nativeEvent.layout.height)
|
setHeightOriginal(nativeEvent.layout.height)
|
||||||
} else {
|
} else {
|
||||||
if (heightOriginal > heightTruncated) {
|
if (!heightTruncated) {
|
||||||
setAllowExpand(true)
|
setHeightTruncated(nativeEvent.layout.height)
|
||||||
|
} else {
|
||||||
|
if (heightOriginal > heightTruncated) {
|
||||||
|
setAllowExpand(true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -214,7 +223,7 @@ const ParseHTML: React.FC<Props> = ({
|
|||||||
}}
|
}}
|
||||||
children={children}
|
children={children}
|
||||||
numberOfLines={calNumberOfLines}
|
numberOfLines={calNumberOfLines}
|
||||||
onLayout={allowExpand === undefined ? onLayout : undefined}
|
onLayout={onLayout}
|
||||||
/>
|
/>
|
||||||
{allowExpand ? (
|
{allowExpand ? (
|
||||||
<Pressable
|
<Pressable
|
||||||
|
@ -86,7 +86,7 @@ const Timelines: React.FC<Props> = ({ name, content }) => {
|
|||||||
</View>
|
</View>
|
||||||
),
|
),
|
||||||
headerRight: () => (
|
headerRight: () => (
|
||||||
<HeaderRight content='search' onPress={onPressSearch} />
|
<HeaderRight content='Search' onPress={onPressSearch} />
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
|
@ -24,10 +24,10 @@ export type TimelineData =
|
|||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
page: App.Pages
|
page: App.Pages
|
||||||
hashtag?: string
|
hashtag?: Mastodon.Tag['name']
|
||||||
list?: string
|
list?: Mastodon.List['id']
|
||||||
toot?: Mastodon.Status
|
toot?: Mastodon.Status['id']
|
||||||
account?: string
|
account?: Mastodon.Account['id']
|
||||||
disableRefresh?: boolean
|
disableRefresh?: boolean
|
||||||
disableInfinity?: boolean
|
disableInfinity?: boolean
|
||||||
}
|
}
|
||||||
@ -134,7 +134,7 @@ const Timeline: React.FC<Props> = ({
|
|||||||
flattenPinnedLength[0] && {
|
flattenPinnedLength[0] && {
|
||||||
pinnedLength: flattenPinnedLength[0]
|
pinnedLength: flattenPinnedLength[0]
|
||||||
})}
|
})}
|
||||||
{...(toot && toot.id === item.id && { highlighted: true })}
|
{...(toot === item.id && { highlighted: true })}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -144,7 +144,7 @@ const Timeline: React.FC<Props> = ({
|
|||||||
const ItemSeparatorComponent = useCallback(
|
const ItemSeparatorComponent = useCallback(
|
||||||
({ leadingItem }) => (
|
({ leadingItem }) => (
|
||||||
<TimelineSeparator
|
<TimelineSeparator
|
||||||
{...(toot && toot.id === leadingItem.id && { highlighted: true })}
|
{...(toot === leadingItem.id && { highlighted: true })}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
[]
|
[]
|
||||||
|
@ -44,6 +44,7 @@ const TimelineDefault: React.FC<Props> = ({
|
|||||||
}),
|
}),
|
||||||
[]
|
[]
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Pressable style={styles.statusView} onPress={onPress}>
|
<Pressable style={styles.statusView} onPress={onPress}>
|
||||||
{item.reblog ? (
|
{item.reblog ? (
|
||||||
@ -57,11 +58,11 @@ const TimelineDefault: React.FC<Props> = ({
|
|||||||
{...(!isRemotePublic && { queryKey })}
|
{...(!isRemotePublic && { queryKey })}
|
||||||
account={actualStatus.account}
|
account={actualStatus.account}
|
||||||
/>
|
/>
|
||||||
<TimelineHeaderDefault
|
{/* <TimelineHeaderDefault
|
||||||
{...(!isRemotePublic && { queryKey })}
|
{...(!isRemotePublic && { queryKey })}
|
||||||
status={actualStatus}
|
status={actualStatus}
|
||||||
sameAccount={actualStatus.account.id === localAccountId}
|
sameAccount={actualStatus.account.id === localAccountId}
|
||||||
/>
|
/> */}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import Button from '@components/Button'
|
import Button from '@components/Button'
|
||||||
import { Feather } from '@expo/vector-icons'
|
import Icon from '@components/Icon'
|
||||||
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, { useMemo } from 'react'
|
import React, { useMemo } from 'react'
|
||||||
@ -26,8 +26,8 @@ const TimelineEmpty: React.FC<Props> = ({ status, refetch }) => {
|
|||||||
case 'error':
|
case 'error':
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Feather
|
<Icon
|
||||||
name='frown'
|
name='Frown'
|
||||||
size={StyleConstants.Font.Size.L}
|
size={StyleConstants.Font.Size.L}
|
||||||
color={theme.primary}
|
color={theme.primary}
|
||||||
/>
|
/>
|
||||||
@ -44,8 +44,8 @@ const TimelineEmpty: React.FC<Props> = ({ status, refetch }) => {
|
|||||||
case 'success':
|
case 'success':
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Feather
|
<Icon
|
||||||
name='smartphone'
|
name='Smartphone'
|
||||||
size={StyleConstants.Font.Size.L}
|
size={StyleConstants.Font.Size.L}
|
||||||
color={theme.primary}
|
color={theme.primary}
|
||||||
/>
|
/>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
import Icon from '@components/Icon'
|
||||||
import { ParseEmojis } from '@components/Parse'
|
import { ParseEmojis } from '@components/Parse'
|
||||||
import { Feather } from '@expo/vector-icons'
|
|
||||||
import { useNavigation } from '@react-navigation/native'
|
import { useNavigation } from '@react-navigation/native'
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
@ -37,8 +37,8 @@ const TimelineActioned: React.FC<Props> = ({
|
|||||||
case 'pinned':
|
case 'pinned':
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Feather
|
<Icon
|
||||||
name='anchor'
|
name='Anchor'
|
||||||
size={StyleConstants.Font.Size.S}
|
size={StyleConstants.Font.Size.S}
|
||||||
color={iconColor}
|
color={iconColor}
|
||||||
style={styles.icon}
|
style={styles.icon}
|
||||||
@ -50,8 +50,8 @@ const TimelineActioned: React.FC<Props> = ({
|
|||||||
case 'favourite':
|
case 'favourite':
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Feather
|
<Icon
|
||||||
name='heart'
|
name='Heart'
|
||||||
size={StyleConstants.Font.Size.S}
|
size={StyleConstants.Font.Size.S}
|
||||||
color={iconColor}
|
color={iconColor}
|
||||||
style={styles.icon}
|
style={styles.icon}
|
||||||
@ -65,8 +65,8 @@ const TimelineActioned: React.FC<Props> = ({
|
|||||||
case 'follow':
|
case 'follow':
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Feather
|
<Icon
|
||||||
name='user-plus'
|
name='UserPlus'
|
||||||
size={StyleConstants.Font.Size.S}
|
size={StyleConstants.Font.Size.S}
|
||||||
color={iconColor}
|
color={iconColor}
|
||||||
style={styles.icon}
|
style={styles.icon}
|
||||||
@ -80,8 +80,8 @@ const TimelineActioned: React.FC<Props> = ({
|
|||||||
case 'poll':
|
case 'poll':
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Feather
|
<Icon
|
||||||
name='bar-chart-2'
|
name='BarChart2'
|
||||||
size={StyleConstants.Font.Size.S}
|
size={StyleConstants.Font.Size.S}
|
||||||
color={iconColor}
|
color={iconColor}
|
||||||
style={styles.icon}
|
style={styles.icon}
|
||||||
@ -93,8 +93,8 @@ const TimelineActioned: React.FC<Props> = ({
|
|||||||
case 'reblog':
|
case 'reblog':
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Feather
|
<Icon
|
||||||
name='repeat'
|
name='Repeat'
|
||||||
size={StyleConstants.Font.Size.S}
|
size={StyleConstants.Font.Size.S}
|
||||||
color={iconColor}
|
color={iconColor}
|
||||||
style={styles.icon}
|
style={styles.icon}
|
||||||
@ -118,12 +118,13 @@ const TimelineActioned: React.FC<Props> = ({
|
|||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
actioned: {
|
actioned: {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
marginBottom: StyleConstants.Spacing.S,
|
marginBottom: StyleConstants.Spacing.S,
|
||||||
paddingLeft: StyleConstants.Avatar.M - StyleConstants.Font.Size.S,
|
paddingLeft: StyleConstants.Avatar.M - StyleConstants.Font.Size.S,
|
||||||
paddingRight: StyleConstants.Spacing.Global.PagePadding
|
paddingRight: StyleConstants.Spacing.Global.PagePadding
|
||||||
},
|
},
|
||||||
icon: {
|
icon: {
|
||||||
paddingRight: StyleConstants.Spacing.S
|
marginRight: StyleConstants.Spacing.S
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import client from '@api/client'
|
import client from '@api/client'
|
||||||
import haptics from '@components/haptics'
|
import haptics from '@components/haptics'
|
||||||
|
import Icon from '@components/Icon'
|
||||||
import { TimelineData } from '@components/Timelines/Timeline'
|
import { TimelineData } from '@components/Timelines/Timeline'
|
||||||
import { toast } from '@components/toast'
|
import { toast } from '@components/toast'
|
||||||
import { Feather } from '@expo/vector-icons'
|
|
||||||
import { useNavigation } from '@react-navigation/native'
|
import { useNavigation } from '@react-navigation/native'
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
@ -171,8 +171,8 @@ const TimelineActions: React.FC<Props> = ({ queryKey, status, reblog }) => {
|
|||||||
const childrenReply = useMemo(
|
const childrenReply = useMemo(
|
||||||
() => (
|
() => (
|
||||||
<>
|
<>
|
||||||
<Feather
|
<Icon
|
||||||
name='message-circle'
|
name='MessageCircle'
|
||||||
color={iconColor}
|
color={iconColor}
|
||||||
size={StyleConstants.Font.Size.M + 2}
|
size={StyleConstants.Font.Size.M + 2}
|
||||||
/>
|
/>
|
||||||
@ -193,8 +193,8 @@ const TimelineActions: React.FC<Props> = ({ queryKey, status, reblog }) => {
|
|||||||
)
|
)
|
||||||
const childrenReblog = useMemo(
|
const childrenReblog = useMemo(
|
||||||
() => (
|
() => (
|
||||||
<Feather
|
<Icon
|
||||||
name='repeat'
|
name='Repeat'
|
||||||
color={
|
color={
|
||||||
status.visibility === 'private' || status.visibility === 'direct'
|
status.visibility === 'private' || status.visibility === 'direct'
|
||||||
? theme.disabled
|
? theme.disabled
|
||||||
@ -207,8 +207,8 @@ const TimelineActions: React.FC<Props> = ({ queryKey, status, reblog }) => {
|
|||||||
)
|
)
|
||||||
const childrenFavourite = useMemo(
|
const childrenFavourite = useMemo(
|
||||||
() => (
|
() => (
|
||||||
<Feather
|
<Icon
|
||||||
name='heart'
|
name='Heart'
|
||||||
color={iconColorAction(status.favourited)}
|
color={iconColorAction(status.favourited)}
|
||||||
size={StyleConstants.Font.Size.M + 2}
|
size={StyleConstants.Font.Size.M + 2}
|
||||||
/>
|
/>
|
||||||
@ -217,8 +217,8 @@ const TimelineActions: React.FC<Props> = ({ queryKey, status, reblog }) => {
|
|||||||
)
|
)
|
||||||
const childrenBookmark = useMemo(
|
const childrenBookmark = useMemo(
|
||||||
() => (
|
() => (
|
||||||
<Feather
|
<Icon
|
||||||
name='bookmark'
|
name='Bookmark'
|
||||||
color={iconColorAction(status.bookmarked)}
|
color={iconColorAction(status.bookmarked)}
|
||||||
size={StyleConstants.Font.Size.M + 2}
|
size={StyleConstants.Font.Size.M + 2}
|
||||||
/>
|
/>
|
||||||
@ -227,8 +227,8 @@ const TimelineActions: React.FC<Props> = ({ queryKey, status, reblog }) => {
|
|||||||
)
|
)
|
||||||
const childrenShare = useMemo(
|
const childrenShare = useMemo(
|
||||||
() => (
|
() => (
|
||||||
<Feather
|
<Icon
|
||||||
name='share-2'
|
name='Share2'
|
||||||
color={iconColor}
|
color={iconColor}
|
||||||
size={StyleConstants.Font.Size.M + 2}
|
size={StyleConstants.Font.Size.M + 2}
|
||||||
/>
|
/>
|
||||||
|
@ -117,7 +117,7 @@ const TimelineAttachment: React.FC<Props> = ({ status }) => {
|
|||||||
) : (
|
) : (
|
||||||
<Button
|
<Button
|
||||||
type='icon'
|
type='icon'
|
||||||
content='eye-off'
|
content='EyeOff'
|
||||||
round
|
round
|
||||||
overlay
|
overlay
|
||||||
onPress={onPressShow}
|
onPress={onPressShow}
|
||||||
|
@ -67,7 +67,7 @@ const AttachmentAudio: React.FC<Props> = ({ sensitiveShown, audio }) => {
|
|||||||
)}
|
)}
|
||||||
<Button
|
<Button
|
||||||
type='icon'
|
type='icon'
|
||||||
content={audioPlaying ? 'pause-circle' : 'play-circle'}
|
content={audioPlaying ? 'PauseCircle' : 'PlayCircle'}
|
||||||
size='L'
|
size='L'
|
||||||
round
|
round
|
||||||
overlay
|
overlay
|
||||||
|
@ -64,7 +64,7 @@ const AttachmentVideo: React.FC<Props> = ({ sensitiveShown, video }) => {
|
|||||||
) : (
|
) : (
|
||||||
<Button
|
<Button
|
||||||
type='icon'
|
type='icon'
|
||||||
content='play-circle'
|
content='PlayCircle'
|
||||||
size='L'
|
size='L'
|
||||||
round
|
round
|
||||||
overlay
|
overlay
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Feather } from '@expo/vector-icons'
|
import Icon from '@components/Icon'
|
||||||
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 from 'react'
|
import React from 'react'
|
||||||
@ -22,8 +22,9 @@ const TimelineEnd: React.FC<Props> = ({ hasNextPage }) => {
|
|||||||
<Trans
|
<Trans
|
||||||
i18nKey='timeline:shared.end.message' // optional -> fallbacks to defaults if not provided
|
i18nKey='timeline:shared.end.message' // optional -> fallbacks to defaults if not provided
|
||||||
components={[
|
components={[
|
||||||
<Feather
|
<Icon
|
||||||
name='coffee'
|
inline
|
||||||
|
name='Coffee'
|
||||||
size={StyleConstants.Font.Size.S}
|
size={StyleConstants.Font.Size.S}
|
||||||
color={theme.secondary}
|
color={theme.secondary}
|
||||||
/>
|
/>
|
||||||
@ -43,8 +44,7 @@ const styles = StyleSheet.create({
|
|||||||
padding: StyleConstants.Spacing.M
|
padding: StyleConstants.Spacing.M
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
...StyleConstants.FontStyle.S,
|
...StyleConstants.FontStyle.S
|
||||||
marginLeft: StyleConstants.Spacing.S
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import client from '@api/client'
|
import client from '@api/client'
|
||||||
import haptics from '@components/haptics'
|
import haptics from '@components/haptics'
|
||||||
|
import Icon from '@components/Icon'
|
||||||
import { toast } from '@components/toast'
|
import { toast } from '@components/toast'
|
||||||
import { Feather } from '@expo/vector-icons'
|
|
||||||
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, useMemo } from 'react'
|
import React, { useCallback, useMemo } from 'react'
|
||||||
@ -66,8 +66,8 @@ const HeaderConversation: React.FC<Props> = ({ queryKey, conversation }) => {
|
|||||||
|
|
||||||
const actionChildren = useMemo(
|
const actionChildren = useMemo(
|
||||||
() => (
|
() => (
|
||||||
<Feather
|
<Icon
|
||||||
name='trash'
|
name='Trash'
|
||||||
color={theme.secondary}
|
color={theme.secondary}
|
||||||
size={StyleConstants.Font.Size.M + 2}
|
size={StyleConstants.Font.Size.M + 2}
|
||||||
/>
|
/>
|
||||||
@ -86,7 +86,7 @@ const HeaderConversation: React.FC<Props> = ({ queryKey, conversation }) => {
|
|||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
{conversation.unread && (
|
{conversation.unread && (
|
||||||
<Feather name='circle' color={theme.blue} style={styles.unread} />
|
<Icon name='Circle' color={theme.blue} style={styles.unread} />
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import BottomSheet from '@components/BottomSheet'
|
import BottomSheet from '@components/BottomSheet'
|
||||||
import { Feather } from '@expo/vector-icons'
|
import Icon from '@components/Icon'
|
||||||
import { getLocalUrl } from '@utils/slices/instancesSlice'
|
import { getLocalUrl } from '@utils/slices/instancesSlice'
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
@ -9,10 +9,10 @@ import HeaderDefaultActionsStatus from '@components/Timelines/Timeline/Shared/He
|
|||||||
import React, { useCallback, useMemo, useState } from 'react'
|
import React, { useCallback, useMemo, useState } from 'react'
|
||||||
import { Pressable, StyleSheet, View } from 'react-native'
|
import { Pressable, StyleSheet, View } from 'react-native'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
import HeaderSharedApplication from './HeaderShared/Application'
|
|
||||||
import HeaderSharedVisibility from './HeaderShared/Visibility'
|
|
||||||
import HeaderSharedCreated from './HeaderShared/Created'
|
|
||||||
import HeaderSharedAccount from './HeaderShared/Account'
|
import HeaderSharedAccount from './HeaderShared/Account'
|
||||||
|
import HeaderSharedApplication from './HeaderShared/Application'
|
||||||
|
import HeaderSharedCreated from './HeaderShared/Created'
|
||||||
|
import HeaderSharedVisibility from './HeaderShared/Visibility'
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
queryKey?: QueryKey.Timeline
|
queryKey?: QueryKey.Timeline
|
||||||
@ -37,8 +37,8 @@ const TimelineHeaderDefault: React.FC<Props> = ({
|
|||||||
|
|
||||||
const pressableAction = useMemo(
|
const pressableAction = useMemo(
|
||||||
() => (
|
() => (
|
||||||
<Feather
|
<Icon
|
||||||
name='more-horizontal'
|
name='MoreHorizontal'
|
||||||
color={theme.secondary}
|
color={theme.secondary}
|
||||||
size={StyleConstants.Font.Size.M + 2}
|
size={StyleConstants.Font.Size.M + 2}
|
||||||
/>
|
/>
|
||||||
@ -102,8 +102,7 @@ const TimelineHeaderDefault: React.FC<Props> = ({
|
|||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
base: {
|
base: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
flexDirection: 'row',
|
flexDirection: 'row'
|
||||||
alignItems: 'baseline'
|
|
||||||
},
|
},
|
||||||
accountAndMeta: {
|
accountAndMeta: {
|
||||||
flex: 4
|
flex: 4
|
||||||
|
@ -84,7 +84,7 @@ const HeaderDefaultActionsAccount: React.FC<Props> = ({
|
|||||||
setBottomSheetVisible(false)
|
setBottomSheetVisible(false)
|
||||||
mutate({ type: 'mute' })
|
mutate({ type: 'mute' })
|
||||||
}}
|
}}
|
||||||
iconFront='eye-off'
|
iconFront='EyeOff'
|
||||||
title={t('timeline:shared.header.default.actions.account.mute.button', {
|
title={t('timeline:shared.header.default.actions.account.mute.button', {
|
||||||
acct: account.acct
|
acct: account.acct
|
||||||
})}
|
})}
|
||||||
@ -94,7 +94,7 @@ const HeaderDefaultActionsAccount: React.FC<Props> = ({
|
|||||||
setBottomSheetVisible(false)
|
setBottomSheetVisible(false)
|
||||||
mutate({ type: 'block' })
|
mutate({ type: 'block' })
|
||||||
}}
|
}}
|
||||||
iconFront='x-circle'
|
iconFront='XCircle'
|
||||||
title={t(
|
title={t(
|
||||||
'timeline:shared.header.default.actions.account.block.button',
|
'timeline:shared.header.default.actions.account.block.button',
|
||||||
{
|
{
|
||||||
@ -107,7 +107,7 @@ const HeaderDefaultActionsAccount: React.FC<Props> = ({
|
|||||||
setBottomSheetVisible(false)
|
setBottomSheetVisible(false)
|
||||||
mutate({ type: 'reports' })
|
mutate({ type: 'reports' })
|
||||||
}}
|
}}
|
||||||
iconFront='flag'
|
iconFront='Flag'
|
||||||
title={t(
|
title={t(
|
||||||
'timeline:shared.header.default.actions.account.report.button',
|
'timeline:shared.header.default.actions.account.report.button',
|
||||||
{
|
{
|
||||||
|
@ -54,7 +54,7 @@ const HeaderDefaultActionsDomain: React.FC<Props> = ({
|
|||||||
setBottomSheetVisible(false)
|
setBottomSheetVisible(false)
|
||||||
mutate()
|
mutate()
|
||||||
}}
|
}}
|
||||||
iconFront='cloud-off'
|
iconFront='CloudOff'
|
||||||
title={t(`timeline:shared.header.default.actions.domain.block.button`, {
|
title={t(`timeline:shared.header.default.actions.domain.block.button`, {
|
||||||
domain
|
domain
|
||||||
})}
|
})}
|
||||||
|
@ -128,7 +128,7 @@ const HeaderDefaultActionsStatus: React.FC<Props> = ({
|
|||||||
setBottomSheetVisible(false)
|
setBottomSheetVisible(false)
|
||||||
mutate({ type: 'delete' })
|
mutate({ type: 'delete' })
|
||||||
}}
|
}}
|
||||||
iconFront='trash'
|
iconFront='Trash'
|
||||||
title={t('timeline:shared.header.default.actions.status.delete.button')}
|
title={t('timeline:shared.header.default.actions.status.delete.button')}
|
||||||
/>
|
/>
|
||||||
<MenuRow
|
<MenuRow
|
||||||
@ -174,7 +174,7 @@ const HeaderDefaultActionsStatus: React.FC<Props> = ({
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
iconFront='trash'
|
iconFront='Trash'
|
||||||
title={t('timeline:shared.header.default.actions.status.edit.button')}
|
title={t('timeline:shared.header.default.actions.status.edit.button')}
|
||||||
/>
|
/>
|
||||||
<MenuRow
|
<MenuRow
|
||||||
@ -182,7 +182,7 @@ const HeaderDefaultActionsStatus: React.FC<Props> = ({
|
|||||||
setBottomSheetVisible(false)
|
setBottomSheetVisible(false)
|
||||||
mutate({ type: 'mute', state: status.muted })
|
mutate({ type: 'mute', state: status.muted })
|
||||||
}}
|
}}
|
||||||
iconFront='volume-x'
|
iconFront='VolumeX'
|
||||||
title={
|
title={
|
||||||
status.muted
|
status.muted
|
||||||
? t(
|
? t(
|
||||||
@ -200,7 +200,7 @@ const HeaderDefaultActionsStatus: React.FC<Props> = ({
|
|||||||
setBottomSheetVisible(false)
|
setBottomSheetVisible(false)
|
||||||
mutate({ type: 'pin', state: status.pinned })
|
mutate({ type: 'pin', state: status.pinned })
|
||||||
}}
|
}}
|
||||||
iconFront='anchor'
|
iconFront='Anchor'
|
||||||
title={
|
title={
|
||||||
status.pinned
|
status.pinned
|
||||||
? t(
|
? t(
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import client from '@api/client'
|
import client from '@api/client'
|
||||||
import { Feather } from '@expo/vector-icons'
|
|
||||||
import haptics from '@components/haptics'
|
import haptics from '@components/haptics'
|
||||||
|
import Icon from '@components/Icon'
|
||||||
import { toast } from '@components/toast'
|
import { toast } from '@components/toast'
|
||||||
import { relationshipFetch } from '@utils/fetches/relationshipFetch'
|
import { relationshipFetch } from '@utils/fetches/relationshipFetch'
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
@ -9,10 +9,10 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'
|
|||||||
import { Pressable, StyleSheet, View } from 'react-native'
|
import { Pressable, StyleSheet, View } from 'react-native'
|
||||||
import { Chase } from 'react-native-animated-spinkit'
|
import { Chase } from 'react-native-animated-spinkit'
|
||||||
import { useQuery } from 'react-query'
|
import { useQuery } from 'react-query'
|
||||||
import HeaderSharedApplication from './HeaderShared/Application'
|
|
||||||
import HeaderSharedVisibility from './HeaderShared/Visibility'
|
|
||||||
import HeaderSharedCreated from './HeaderShared/Created'
|
|
||||||
import HeaderSharedAccount from './HeaderShared/Account'
|
import HeaderSharedAccount from './HeaderShared/Account'
|
||||||
|
import HeaderSharedApplication from './HeaderShared/Application'
|
||||||
|
import HeaderSharedCreated from './HeaderShared/Created'
|
||||||
|
import HeaderSharedVisibility from './HeaderShared/Visibility'
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
notification: Mastodon.Notification
|
notification: Mastodon.Notification
|
||||||
@ -73,19 +73,19 @@ const TimelineHeaderNotification: React.FC<Props> = ({ notification }) => {
|
|||||||
case 'success':
|
case 'success':
|
||||||
return (
|
return (
|
||||||
<Pressable onPress={relationshipOnPress}>
|
<Pressable onPress={relationshipOnPress}>
|
||||||
<Feather
|
<Icon
|
||||||
name={
|
name={
|
||||||
updateData
|
updateData
|
||||||
? updateData.following
|
? updateData.following
|
||||||
? 'user-check'
|
? 'UserCheck'
|
||||||
: updateData.requested
|
: updateData.requested
|
||||||
? 'loader'
|
? 'Loader'
|
||||||
: 'user-plus'
|
: 'UserPlus'
|
||||||
: data!.following
|
: data!.following
|
||||||
? 'user-check'
|
? 'UserCheck'
|
||||||
: data!.requested
|
: data!.requested
|
||||||
? 'loader'
|
? 'Loader'
|
||||||
: 'user-plus'
|
: 'UserPlus'
|
||||||
}
|
}
|
||||||
color={
|
color={
|
||||||
updateData
|
updateData
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Feather } from '@expo/vector-icons'
|
import Icon from '@components/Icon'
|
||||||
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 from 'react'
|
import React from 'react'
|
||||||
@ -12,8 +12,8 @@ const HeaderSharedVisibility: React.FC<Props> = ({ visibility }) => {
|
|||||||
const { theme } = useTheme()
|
const { theme } = useTheme()
|
||||||
|
|
||||||
return visibility && visibility === 'private' ? (
|
return visibility && visibility === 'private' ? (
|
||||||
<Feather
|
<Icon
|
||||||
name='lock'
|
name='Lock'
|
||||||
size={StyleConstants.Font.Size.S}
|
size={StyleConstants.Font.Size.S}
|
||||||
color={theme.secondary}
|
color={theme.secondary}
|
||||||
style={styles.visibility}
|
style={styles.visibility}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import client from '@api/client'
|
import client from '@api/client'
|
||||||
import Button from '@components/Button'
|
import Button from '@components/Button'
|
||||||
import haptics from '@components/haptics'
|
import haptics from '@components/haptics'
|
||||||
|
import Icon from '@components/Icon'
|
||||||
import relativeTime from '@components/relativeTime'
|
import relativeTime from '@components/relativeTime'
|
||||||
import { TimelineData } from '@components/Timelines/Timeline'
|
import { TimelineData } from '@components/Timelines/Timeline'
|
||||||
import { Feather } from '@expo/vector-icons'
|
|
||||||
import { ParseEmojis } from '@root/components/Parse'
|
import { ParseEmojis } from '@root/components/Parse'
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
@ -151,8 +151,8 @@ const TimelinePoll: React.FC<Props> = ({
|
|||||||
const isSelected = useCallback(
|
const isSelected = useCallback(
|
||||||
(index: number): any =>
|
(index: number): any =>
|
||||||
allOptions[index]
|
allOptions[index]
|
||||||
? `check-${poll.multiple ? 'square' : 'circle'}`
|
? `Check${poll.multiple ? 'Square' : 'Circle'}`
|
||||||
: `${poll.multiple ? 'square' : 'circle'}`,
|
: `${poll.multiple ? 'Square' : 'Circle'}`,
|
||||||
[allOptions]
|
[allOptions]
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -160,11 +160,11 @@ const TimelinePoll: React.FC<Props> = ({
|
|||||||
return poll.options.map((option, index) => (
|
return poll.options.map((option, index) => (
|
||||||
<View key={index} style={styles.optionContainer}>
|
<View key={index} style={styles.optionContainer}>
|
||||||
<View style={styles.optionContent}>
|
<View style={styles.optionContent}>
|
||||||
<Feather
|
<Icon
|
||||||
style={styles.optionSelection}
|
style={styles.optionSelection}
|
||||||
name={
|
name={
|
||||||
`${poll.own_votes?.includes(index) ? 'check-' : ''}${
|
`${poll.own_votes?.includes(index) ? 'Check' : ''}${
|
||||||
poll.multiple ? 'square' : 'circle'
|
poll.multiple ? 'Square' : 'Circle'
|
||||||
}` as any
|
}` as any
|
||||||
}
|
}
|
||||||
size={StyleConstants.Font.Size.M}
|
size={StyleConstants.Font.Size.M}
|
||||||
@ -224,7 +224,7 @@ const TimelinePoll: React.FC<Props> = ({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<View style={[styles.optionContent]}>
|
<View style={[styles.optionContent]}>
|
||||||
<Feather
|
<Icon
|
||||||
style={styles.optionSelection}
|
style={styles.optionSelection}
|
||||||
name={isSelected(index)}
|
name={isSelected(index)}
|
||||||
size={StyleConstants.Font.Size.L}
|
size={StyleConstants.Font.Size.L}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
|
import Icon from '@components/Icon'
|
||||||
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { StyleSheet, Text, View } from 'react-native'
|
import { StyleSheet, Text, View } from 'react-native'
|
||||||
import { SafeAreaView } from 'react-native-safe-area-context'
|
import { SafeAreaView } from 'react-native-safe-area-context'
|
||||||
import Toast from 'react-native-toast-message'
|
import Toast from 'react-native-toast-message'
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
|
||||||
import { Feather } from '@expo/vector-icons'
|
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
|
||||||
|
|
||||||
export interface Params {
|
export interface Params {
|
||||||
type: 'success' | 'error' | 'warning'
|
type: 'success' | 'error' | 'warning'
|
||||||
@ -49,9 +49,9 @@ const toast = ({
|
|||||||
const ToastBase = ({ config }: { config: Config }) => {
|
const ToastBase = ({ config }: { config: Config }) => {
|
||||||
const { theme } = useTheme()
|
const { theme } = useTheme()
|
||||||
const iconSet = {
|
const iconSet = {
|
||||||
success: 'check-circle',
|
success: 'CheckCircle',
|
||||||
error: 'x-circle',
|
error: 'XCircle',
|
||||||
warning: 'alert-circle'
|
warning: 'AlertCircle'
|
||||||
}
|
}
|
||||||
enum colorMapping {
|
enum colorMapping {
|
||||||
success = 'blue',
|
success = 'blue',
|
||||||
@ -67,11 +67,10 @@ const ToastBase = ({ config }: { config: Config }) => {
|
|||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<Feather
|
<Icon
|
||||||
// @ts-ignore
|
|
||||||
name={iconSet[config.type]}
|
name={iconSet[config.type]}
|
||||||
|
size={StyleConstants.Font.Size.M}
|
||||||
color={theme[colorMapping[config.type]]}
|
color={theme[colorMapping[config.type]]}
|
||||||
size={StyleConstants.Font.Size.M + 2}
|
|
||||||
/>
|
/>
|
||||||
<View style={styles.texts}>
|
<View style={styles.texts}>
|
||||||
<Text style={[styles.text1, { color: theme.primary }]}>
|
<Text style={[styles.text1, { color: theme.primary }]}>
|
||||||
@ -104,7 +103,7 @@ const styles = StyleSheet.create({
|
|||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
padding: StyleConstants.Spacing.L
|
padding: StyleConstants.Spacing.M
|
||||||
},
|
},
|
||||||
texts: {
|
texts: {
|
||||||
marginLeft: StyleConstants.Spacing.S
|
marginLeft: StyleConstants.Spacing.S
|
||||||
@ -114,7 +113,7 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
text2: {
|
text2: {
|
||||||
...StyleConstants.FontStyle.S,
|
...StyleConstants.FontStyle.S,
|
||||||
marginTop: StyleConstants.Spacing.S
|
marginTop: StyleConstants.Spacing.XS
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -57,16 +57,16 @@ export default {
|
|||||||
account: {
|
account: {
|
||||||
heading: '关于用户',
|
heading: '关于用户',
|
||||||
mute: {
|
mute: {
|
||||||
function: '隐藏 {{acct}} 的嘟文',
|
function: '隐藏 @{{acct}} 的嘟文',
|
||||||
button: '隐藏 {{acct}} 的嘟文'
|
button: '隐藏 @{{acct}} 的嘟文'
|
||||||
},
|
},
|
||||||
block: {
|
block: {
|
||||||
function: '屏蔽 {{acct}}',
|
function: '屏蔽 @{{acct}}',
|
||||||
button: '屏蔽 {{acct}}'
|
button: '屏蔽 @{{acct}}'
|
||||||
},
|
},
|
||||||
report: {
|
report: {
|
||||||
function: '举报 {{acct}}',
|
function: '举报 @{{acct}}',
|
||||||
button: '举报 {{acct}}'
|
button: '举报 @{{acct}}'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
domain: {
|
domain: {
|
||||||
|
@ -15,7 +15,7 @@ const ScreenMeLists: React.FC = () => {
|
|||||||
return data?.map((d: Mastodon.List, i: number) => (
|
return data?.map((d: Mastodon.List, i: number) => (
|
||||||
<MenuRow
|
<MenuRow
|
||||||
key={i}
|
key={i}
|
||||||
iconFront='list'
|
iconFront='List'
|
||||||
title={d.title}
|
title={d.title}
|
||||||
onPress={() =>
|
onPress={() =>
|
||||||
navigation.navigate('Screen-Me-Lists-List', {
|
navigation.navigate('Screen-Me-Lists-List', {
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
import React, { useRef, useState } from 'react'
|
import { useScrollToTop } from '@react-navigation/native'
|
||||||
import { Animated, ScrollView } from 'react-native'
|
import Collections from '@screens/Me/Root/Collections'
|
||||||
import { useSelector } from 'react-redux'
|
|
||||||
|
|
||||||
import { getLocalUrl } from '@utils/slices/instancesSlice'
|
|
||||||
|
|
||||||
import Login from '@screens/Me/Root/Login'
|
import Login from '@screens/Me/Root/Login'
|
||||||
import MyInfo from '@screens/Me/Root/MyInfo'
|
import MyInfo from '@screens/Me/Root/MyInfo'
|
||||||
import Collections from '@screens/Me/Root/Collections'
|
|
||||||
import Settings from '@screens/Me/Root/Settings'
|
import Settings from '@screens/Me/Root/Settings'
|
||||||
import Logout from '@screens/Me/Root/Logout'
|
import Logout from '@screens/Me/Root/Logout'
|
||||||
import { useScrollToTop } from '@react-navigation/native'
|
import AccountNav from '@screens/Shared/Account/Nav'
|
||||||
import { AccountState } from '../Shared/Account'
|
import accountReducer from '@screens/Shared/Account/utils/reducer'
|
||||||
import AccountNav from '../Shared/Account/Nav'
|
import accountInitialState from '@screens/Shared/Account/utils/initialState'
|
||||||
|
import AccountContext from '@screens/Shared/Account/utils/createContext'
|
||||||
|
import { getLocalUrl } from '@utils/slices/instancesSlice'
|
||||||
|
import React, { useReducer, useRef, useState } from 'react'
|
||||||
|
import { Animated, ScrollView } from 'react-native'
|
||||||
|
import { useSelector } from 'react-redux'
|
||||||
|
|
||||||
const ScreenMeRoot: React.FC = () => {
|
const ScreenMeRoot: React.FC = () => {
|
||||||
const localRegistered = useSelector(getLocalUrl)
|
const localRegistered = useSelector(getLocalUrl)
|
||||||
@ -19,24 +19,25 @@ const ScreenMeRoot: React.FC = () => {
|
|||||||
const scrollRef = useRef<ScrollView>(null)
|
const scrollRef = useRef<ScrollView>(null)
|
||||||
useScrollToTop(scrollRef)
|
useScrollToTop(scrollRef)
|
||||||
|
|
||||||
const scrollY = useRef(new Animated.Value(0)).current
|
const scrollY = useRef(new Animated.Value(0))
|
||||||
const [data, setData] = useState<Mastodon.Account>()
|
const [data, setData] = useState<Mastodon.Account>()
|
||||||
|
|
||||||
|
const [accountState, accountDispatch] = useReducer(
|
||||||
|
accountReducer,
|
||||||
|
accountInitialState
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<AccountContext.Provider value={{ accountState, accountDispatch }}>
|
||||||
{localRegistered && data ? (
|
{localRegistered && data ? (
|
||||||
<AccountNav
|
<AccountNav scrollY={scrollY} account={data} />
|
||||||
accountState={{ headerRatio: 0.4 } as AccountState}
|
|
||||||
scrollY={scrollY}
|
|
||||||
account={data}
|
|
||||||
/>
|
|
||||||
) : null}
|
) : null}
|
||||||
<ScrollView
|
<ScrollView
|
||||||
ref={scrollRef}
|
ref={scrollRef}
|
||||||
keyboardShouldPersistTaps='handled'
|
keyboardShouldPersistTaps='handled'
|
||||||
bounces={false}
|
bounces={false}
|
||||||
onScroll={Animated.event(
|
onScroll={Animated.event(
|
||||||
[{ nativeEvent: { contentOffset: { y: scrollY } } }],
|
[{ nativeEvent: { contentOffset: { y: scrollY.current } } }],
|
||||||
{ useNativeDriver: false }
|
{ useNativeDriver: false }
|
||||||
)}
|
)}
|
||||||
scrollEventThrottle={8}
|
scrollEventThrottle={8}
|
||||||
@ -46,7 +47,7 @@ const ScreenMeRoot: React.FC = () => {
|
|||||||
<Settings />
|
<Settings />
|
||||||
{localRegistered && <Logout />}
|
{localRegistered && <Logout />}
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</>
|
</AccountContext.Provider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,32 +27,32 @@ const Collections: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<MenuContainer>
|
<MenuContainer>
|
||||||
<MenuRow
|
<MenuRow
|
||||||
iconFront='mail'
|
iconFront='Mail'
|
||||||
iconBack='chevron-right'
|
iconBack='ChevronRight'
|
||||||
title={t('content.collections.conversations')}
|
title={t('content.collections.conversations')}
|
||||||
onPress={() => navigation.navigate('Screen-Me-Conversations')}
|
onPress={() => navigation.navigate('Screen-Me-Conversations')}
|
||||||
/>
|
/>
|
||||||
<MenuRow
|
<MenuRow
|
||||||
iconFront='bookmark'
|
iconFront='Bookmark'
|
||||||
iconBack='chevron-right'
|
iconBack='ChevronRight'
|
||||||
title={t('content.collections.bookmarks')}
|
title={t('content.collections.bookmarks')}
|
||||||
onPress={() => navigation.navigate('Screen-Me-Bookmarks')}
|
onPress={() => navigation.navigate('Screen-Me-Bookmarks')}
|
||||||
/>
|
/>
|
||||||
<MenuRow
|
<MenuRow
|
||||||
iconFront='star'
|
iconFront='Star'
|
||||||
iconBack='chevron-right'
|
iconBack='ChevronRight'
|
||||||
title={t('content.collections.favourites')}
|
title={t('content.collections.favourites')}
|
||||||
onPress={() => navigation.navigate('Screen-Me-Favourites')}
|
onPress={() => navigation.navigate('Screen-Me-Favourites')}
|
||||||
/>
|
/>
|
||||||
<MenuRow
|
<MenuRow
|
||||||
iconFront='list'
|
iconFront='List'
|
||||||
iconBack='chevron-right'
|
iconBack='ChevronRight'
|
||||||
title={t('content.collections.lists')}
|
title={t('content.collections.lists')}
|
||||||
onPress={() => navigation.navigate('Screen-Me-Lists')}
|
onPress={() => navigation.navigate('Screen-Me-Lists')}
|
||||||
/>
|
/>
|
||||||
<MenuRow
|
<MenuRow
|
||||||
iconFront='clipboard'
|
iconFront='Clipboard'
|
||||||
iconBack='chevron-right'
|
iconBack='ChevronRight'
|
||||||
title={t('content.collections.announcements')}
|
title={t('content.collections.announcements')}
|
||||||
content={announcementContent}
|
content={announcementContent}
|
||||||
loading={isFetching}
|
loading={isFetching}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import analytics from '@components/analytics'
|
import analytics from '@components/analytics'
|
||||||
import Button from '@components/Button'
|
import Button from '@components/Button'
|
||||||
import haptics from '@components/haptics'
|
import haptics from '@components/haptics'
|
||||||
|
import Icon from '@components/Icon'
|
||||||
import { ParseHTML } from '@components/Parse'
|
import { ParseHTML } from '@components/Parse'
|
||||||
import { Feather } from '@expo/vector-icons'
|
|
||||||
import { useNavigation } from '@react-navigation/native'
|
import { useNavigation } from '@react-navigation/native'
|
||||||
import { applicationFetch } from '@utils/fetches/applicationFetch'
|
import { applicationFetch } from '@utils/fetches/applicationFetch'
|
||||||
import { instanceFetch } from '@utils/fetches/instanceFetch'
|
import { instanceFetch } from '@utils/fetches/instanceFetch'
|
||||||
@ -282,8 +282,8 @@ const Login: React.FC = () => {
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<Text style={[styles.disclaimer, { color: theme.secondary }]}>
|
<Text style={[styles.disclaimer, { color: theme.secondary }]}>
|
||||||
<Feather
|
<Icon
|
||||||
name='lock'
|
name='Lock'
|
||||||
size={StyleConstants.Font.Size.M}
|
size={StyleConstants.Font.Size.M}
|
||||||
color={theme.secondary}
|
color={theme.secondary}
|
||||||
/>{' '}
|
/>{' '}
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
import React, { useEffect } from 'react'
|
|
||||||
import { useQuery } from 'react-query'
|
|
||||||
|
|
||||||
import { accountFetch } from '@utils/fetches/accountFetch'
|
|
||||||
import AccountHeader from '@screens/Shared/Account/Header'
|
import AccountHeader from '@screens/Shared/Account/Header'
|
||||||
import AccountInformation from '@screens/Shared/Account/Information'
|
import AccountInformation from '@screens/Shared/Account/Information'
|
||||||
import { useSelector } from 'react-redux'
|
import { accountFetch } from '@utils/fetches/accountFetch'
|
||||||
import { getLocalAccountId } from '@utils/slices/instancesSlice'
|
import { getLocalAccountId } from '@utils/slices/instancesSlice'
|
||||||
import { AccountState } from '@root/screens/Shared/Account'
|
import React, { useEffect } from 'react'
|
||||||
|
import { useQuery } from 'react-query'
|
||||||
|
import { useSelector } from 'react-redux'
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
setData: React.Dispatch<React.SetStateAction<Mastodon.Account | undefined>>
|
setData: React.Dispatch<React.SetStateAction<Mastodon.Account | undefined>>
|
||||||
@ -23,11 +21,7 @@ const MyInfo: React.FC<Props> = ({ setData }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AccountHeader
|
<AccountHeader account={data} limitHeight />
|
||||||
accountState={{ headerRatio: 0.4 } as AccountState}
|
|
||||||
account={data}
|
|
||||||
limitHeight
|
|
||||||
/>
|
|
||||||
<AccountInformation account={data} disableActions />
|
<AccountInformation account={data} disableActions />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
@ -11,8 +11,8 @@ const Settings: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<MenuContainer>
|
<MenuContainer>
|
||||||
<MenuRow
|
<MenuRow
|
||||||
iconFront='settings'
|
iconFront='Settings'
|
||||||
iconBack='chevron-right'
|
iconBack='ChevronRight'
|
||||||
title={t('content.settings')}
|
title={t('content.settings')}
|
||||||
onPress={() => navigation.navigate('Screen-Me-Settings')}
|
onPress={() => navigation.navigate('Screen-Me-Settings')}
|
||||||
/>
|
/>
|
||||||
|
@ -39,7 +39,7 @@ const ScreenMeSettings: React.FC = () => {
|
|||||||
<MenuRow
|
<MenuRow
|
||||||
title={t('content.language.heading')}
|
title={t('content.language.heading')}
|
||||||
content={t(`content.language.options.${settingsLanguage}`)}
|
content={t(`content.language.options.${settingsLanguage}`)}
|
||||||
iconBack='chevron-right'
|
iconBack='ChevronRight'
|
||||||
onPress={() =>
|
onPress={() =>
|
||||||
ActionSheetIOS.showActionSheetWithOptions(
|
ActionSheetIOS.showActionSheetWithOptions(
|
||||||
{
|
{
|
||||||
@ -70,7 +70,7 @@ const ScreenMeSettings: React.FC = () => {
|
|||||||
<MenuRow
|
<MenuRow
|
||||||
title={t('content.theme.heading')}
|
title={t('content.theme.heading')}
|
||||||
content={t(`content.theme.options.${settingsTheme}`)}
|
content={t(`content.theme.options.${settingsTheme}`)}
|
||||||
iconBack='chevron-right'
|
iconBack='ChevronRight'
|
||||||
onPress={() =>
|
onPress={() =>
|
||||||
ActionSheetIOS.showActionSheetWithOptions(
|
ActionSheetIOS.showActionSheetWithOptions(
|
||||||
{
|
{
|
||||||
@ -106,7 +106,7 @@ const ScreenMeSettings: React.FC = () => {
|
|||||||
<MenuRow
|
<MenuRow
|
||||||
title={t('content.browser.heading')}
|
title={t('content.browser.heading')}
|
||||||
content={t(`content.browser.options.${settingsBrowser}`)}
|
content={t(`content.browser.options.${settingsBrowser}`)}
|
||||||
iconBack='chevron-right'
|
iconBack='ChevronRight'
|
||||||
onPress={() =>
|
onPress={() =>
|
||||||
ActionSheetIOS.showActionSheetWithOptions(
|
ActionSheetIOS.showActionSheetWithOptions(
|
||||||
{
|
{
|
||||||
@ -137,7 +137,7 @@ const ScreenMeSettings: React.FC = () => {
|
|||||||
<MenuRow
|
<MenuRow
|
||||||
title={t('content.cache.heading')}
|
title={t('content.cache.heading')}
|
||||||
content={cacheSize ? prettyBytes(cacheSize) : '暂无缓存'}
|
content={cacheSize ? prettyBytes(cacheSize) : '暂无缓存'}
|
||||||
iconBack='chevron-right'
|
iconBack='ChevronRight'
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
await CacheManager.clearCache()
|
await CacheManager.clearCache()
|
||||||
haptics('Success')
|
haptics('Success')
|
||||||
@ -154,7 +154,7 @@ const ScreenMeSettings: React.FC = () => {
|
|||||||
/>
|
/>
|
||||||
<MenuRow
|
<MenuRow
|
||||||
title={t('content.copyrights.heading')}
|
title={t('content.copyrights.heading')}
|
||||||
iconBack='chevron-right'
|
iconBack='ChevronRight'
|
||||||
/>
|
/>
|
||||||
<Text style={[styles.version, { color: theme.secondary }]}>
|
<Text style={[styles.version, { color: theme.secondary }]}>
|
||||||
{t('content.version', { version: '1.0.0' })}
|
{t('content.version', { version: '1.0.0' })}
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
|
import BottomSheet from '@components/BottomSheet'
|
||||||
|
import { HeaderRight } from '@components/Header'
|
||||||
|
import HeaderDefaultActionsAccount from '@components/Timelines/Timeline/Shared/HeaderDefault/ActionsAccount'
|
||||||
|
import { accountFetch } from '@utils/fetches/accountFetch'
|
||||||
|
import { getLocalAccountId } from '@utils/slices/instancesSlice'
|
||||||
import React, { useEffect, useReducer, useRef, useState } from 'react'
|
import React, { useEffect, useReducer, useRef, useState } from 'react'
|
||||||
import { Animated, ScrollView } from 'react-native'
|
import { Animated, ScrollView } from 'react-native'
|
||||||
|
|
||||||
import { useQuery } from 'react-query'
|
import { useQuery } from 'react-query'
|
||||||
import { accountFetch } from '@utils/fetches/accountFetch'
|
import { useSelector } from 'react-redux'
|
||||||
import AccountToots from '@screens/Shared/Account/Toots'
|
import AccountHeader from './Account/Header'
|
||||||
import AccountHeader from '@screens/Shared/Account/Header'
|
import AccountInformation from './Account/Information'
|
||||||
import AccountInformation from '@screens/Shared/Account/Information'
|
|
||||||
import AccountNav from './Account/Nav'
|
import AccountNav from './Account/Nav'
|
||||||
import AccountSegmentedControl from './Account/SegmentedControl'
|
import AccountSegmentedControl from './Account/SegmentedControl'
|
||||||
import { HeaderRight } from '@root/components/Header'
|
import AccountToots from './Account/Toots'
|
||||||
import BottomSheet from '@root/components/BottomSheet'
|
import AccountContext from './Account/utils/createContext'
|
||||||
import { useSelector } from 'react-redux'
|
import accountInitialState from './Account/utils/initialState'
|
||||||
import { getLocalAccountId } from '@root/utils/slices/instancesSlice'
|
import accountReducer from './Account/utils/reducer'
|
||||||
import HeaderDefaultActionsAccount from '@root/components/Timelines/Timeline/Shared/HeaderDefault/ActionsAccount'
|
|
||||||
|
|
||||||
// Moved account example: https://m.cmx.im/web/accounts/27812
|
// Moved account example: https://m.cmx.im/web/accounts/27812
|
||||||
|
|
||||||
@ -25,48 +27,6 @@ export interface Props {
|
|||||||
navigation: any
|
navigation: any
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AccountState = {
|
|
||||||
headerRatio: number
|
|
||||||
informationLayout?: {
|
|
||||||
y: number
|
|
||||||
height: number
|
|
||||||
}
|
|
||||||
segmentedIndex: number
|
|
||||||
}
|
|
||||||
export type AccountAction =
|
|
||||||
| {
|
|
||||||
type: 'headerRatio'
|
|
||||||
payload: AccountState['headerRatio']
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'informationLayout'
|
|
||||||
payload: AccountState['informationLayout']
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'segmentedIndex'
|
|
||||||
payload: AccountState['segmentedIndex']
|
|
||||||
}
|
|
||||||
const AccountInitialState: AccountState = {
|
|
||||||
headerRatio: 0.4,
|
|
||||||
informationLayout: { height: 0, y: 100 },
|
|
||||||
segmentedIndex: 0
|
|
||||||
}
|
|
||||||
const accountReducer = (
|
|
||||||
state: AccountState,
|
|
||||||
action: AccountAction
|
|
||||||
): AccountState => {
|
|
||||||
switch (action.type) {
|
|
||||||
case 'headerRatio':
|
|
||||||
return { ...state, headerRatio: action.payload }
|
|
||||||
case 'informationLayout':
|
|
||||||
return { ...state, informationLayout: action.payload }
|
|
||||||
case 'segmentedIndex':
|
|
||||||
return { ...state, segmentedIndex: action.payload }
|
|
||||||
default:
|
|
||||||
throw new Error('Unexpected action')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const ScreenSharedAccount: React.FC<Props> = ({
|
const ScreenSharedAccount: React.FC<Props> = ({
|
||||||
route: {
|
route: {
|
||||||
params: { account }
|
params: { account }
|
||||||
@ -76,10 +36,10 @@ const ScreenSharedAccount: React.FC<Props> = ({
|
|||||||
const localAccountId = useSelector(getLocalAccountId)
|
const localAccountId = useSelector(getLocalAccountId)
|
||||||
const { data } = useQuery(['Account', { id: account.id }], accountFetch)
|
const { data } = useQuery(['Account', { id: account.id }], accountFetch)
|
||||||
|
|
||||||
const scrollY = useRef(new Animated.Value(0)).current
|
const scrollY = useRef(new Animated.Value(0))
|
||||||
const [accountState, accountDispatch] = useReducer(
|
const [accountState, accountDispatch] = useReducer(
|
||||||
accountReducer,
|
accountReducer,
|
||||||
AccountInitialState
|
accountInitialState
|
||||||
)
|
)
|
||||||
|
|
||||||
const [modalVisible, setBottomSheetVisible] = useState(false)
|
const [modalVisible, setBottomSheetVisible] = useState(false)
|
||||||
@ -88,7 +48,7 @@ const ScreenSharedAccount: React.FC<Props> = ({
|
|||||||
navigation.setOptions({
|
navigation.setOptions({
|
||||||
headerRight: () => (
|
headerRight: () => (
|
||||||
<HeaderRight
|
<HeaderRight
|
||||||
content='more-horizontal'
|
content='MoreHorizontal'
|
||||||
onPress={() => setBottomSheetVisible(true)}
|
onPress={() => setBottomSheetVisible(true)}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@ -97,39 +57,23 @@ const ScreenSharedAccount: React.FC<Props> = ({
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<AccountContext.Provider value={{ accountState, accountDispatch }}>
|
||||||
<AccountNav
|
<AccountNav scrollY={scrollY} account={data} />
|
||||||
accountState={accountState}
|
|
||||||
scrollY={scrollY}
|
|
||||||
account={data}
|
|
||||||
/>
|
|
||||||
{accountState.informationLayout?.height &&
|
{accountState.informationLayout?.height &&
|
||||||
accountState.informationLayout.y ? (
|
accountState.informationLayout.y ? (
|
||||||
<AccountSegmentedControl
|
<AccountSegmentedControl scrollY={scrollY} />
|
||||||
accountState={accountState}
|
|
||||||
accountDispatch={accountDispatch}
|
|
||||||
scrollY={scrollY}
|
|
||||||
/>
|
|
||||||
) : null}
|
) : null}
|
||||||
<ScrollView
|
<ScrollView
|
||||||
scrollEventThrottle={16}
|
scrollEventThrottle={16}
|
||||||
showsVerticalScrollIndicator={false}
|
showsVerticalScrollIndicator={false}
|
||||||
onScroll={Animated.event(
|
onScroll={Animated.event(
|
||||||
[{ nativeEvent: { contentOffset: { y: scrollY } } }],
|
[{ nativeEvent: { contentOffset: { y: scrollY.current } } }],
|
||||||
{ useNativeDriver: false }
|
{ useNativeDriver: false }
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<AccountHeader
|
<AccountHeader account={data} />
|
||||||
accountState={accountState}
|
<AccountInformation account={data} />
|
||||||
accountDispatch={accountDispatch}
|
<AccountToots id={account.id} />
|
||||||
account={data}
|
|
||||||
/>
|
|
||||||
<AccountInformation accountDispatch={accountDispatch} account={data} />
|
|
||||||
<AccountToots
|
|
||||||
accountState={accountState}
|
|
||||||
accountDispatch={accountDispatch}
|
|
||||||
id={account.id}
|
|
||||||
/>
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
<BottomSheet
|
<BottomSheet
|
||||||
@ -144,7 +88,7 @@ const ScreenSharedAccount: React.FC<Props> = ({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</BottomSheet>
|
</BottomSheet>
|
||||||
</>
|
</AccountContext.Provider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,21 +1,15 @@
|
|||||||
import { useTheme } from '@root/utils/styles/ThemeManager'
|
import { useTheme } from '@root/utils/styles/ThemeManager'
|
||||||
import React, { Dispatch, useEffect, useState } from 'react'
|
import React, { useContext, useEffect, useState } from 'react'
|
||||||
import { Dimensions, Image, StyleSheet, View } from 'react-native'
|
import { Dimensions, Image, StyleSheet, View } from 'react-native'
|
||||||
import { AccountAction, AccountState } from '../Account'
|
import AccountContext from './utils/createContext'
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
accountState: AccountState
|
|
||||||
accountDispatch?: Dispatch<AccountAction>
|
|
||||||
account?: Mastodon.Account
|
account?: Mastodon.Account
|
||||||
limitHeight?: boolean
|
limitHeight?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const AccountHeader: React.FC<Props> = ({
|
const AccountHeader: React.FC<Props> = ({ account, limitHeight = false }) => {
|
||||||
accountState,
|
const { accountState, accountDispatch } = useContext(AccountContext)
|
||||||
accountDispatch,
|
|
||||||
account,
|
|
||||||
limitHeight = false
|
|
||||||
}) => {
|
|
||||||
const { theme } = useTheme()
|
const { theme } = useTheme()
|
||||||
const [ratio, setRatio] = useState(accountState.headerRatio)
|
const [ratio, setRatio] = useState(accountState.headerRatio)
|
||||||
|
|
||||||
@ -70,4 +64,7 @@ const styles = StyleSheet.create({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export default AccountHeader
|
export default React.memo(
|
||||||
|
AccountHeader,
|
||||||
|
(_, next) => next.account === undefined
|
||||||
|
)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { StyleConstants } from '@utils/styles/constants'
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
import React, { createRef, Dispatch, useCallback, useEffect } from 'react'
|
import React, { createRef, useCallback, useContext, useEffect } from 'react'
|
||||||
import { Animated, StyleSheet, View } from 'react-native'
|
import { Animated, StyleSheet, View } from 'react-native'
|
||||||
import AccountInformationAvatar from './Information/Avatar'
|
import AccountInformationAvatar from './Information/Avatar'
|
||||||
import AccountInformationName from './Information/Name'
|
import AccountInformationName from './Information/Name'
|
||||||
@ -9,19 +9,18 @@ import AccountInformationStats from './Information/Stats'
|
|||||||
import AccountInformationActions from './Information/Actions'
|
import AccountInformationActions from './Information/Actions'
|
||||||
import AccountInformationFields from './Information/Fields'
|
import AccountInformationFields from './Information/Fields'
|
||||||
import AccountInformationNotes from './Information/Notes'
|
import AccountInformationNotes from './Information/Notes'
|
||||||
import { AccountAction } from '../Account'
|
import AccountContext from './utils/createContext'
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
accountDispatch?: Dispatch<AccountAction>
|
|
||||||
account: Mastodon.Account | undefined
|
account: Mastodon.Account | undefined
|
||||||
disableActions?: boolean
|
disableActions?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const AccountInformation: React.FC<Props> = ({
|
const AccountInformation: React.FC<Props> = ({
|
||||||
accountDispatch,
|
|
||||||
account,
|
account,
|
||||||
disableActions = false
|
disableActions = false
|
||||||
}) => {
|
}) => {
|
||||||
|
const { accountDispatch } = useContext(AccountContext)
|
||||||
const shimmerAvatarRef = createRef<any>()
|
const shimmerAvatarRef = createRef<any>()
|
||||||
const shimmerNameRef = createRef<any>()
|
const shimmerNameRef = createRef<any>()
|
||||||
const shimmerAccountRef = createRef<any>()
|
const shimmerAccountRef = createRef<any>()
|
||||||
@ -98,4 +97,7 @@ const styles = StyleSheet.create({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export default AccountInformation
|
export default React.memo(
|
||||||
|
AccountInformation,
|
||||||
|
(_, next) => next.account === undefined
|
||||||
|
)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Feather } from '@expo/vector-icons'
|
import Icon from '@components/Icon'
|
||||||
import { StyleConstants } from '@root/utils/styles/constants'
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
import { useTheme } from '@root/utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import { LinearGradient } from 'expo-linear-gradient'
|
import { LinearGradient } from 'expo-linear-gradient'
|
||||||
import React, { forwardRef } from 'react'
|
import React, { forwardRef } from 'react'
|
||||||
import { StyleSheet, Text, View } from 'react-native'
|
import { StyleSheet, Text, View } from 'react-native'
|
||||||
@ -38,13 +38,19 @@ const AccountInformationAccount = forwardRef<ShimmerPlaceholder, Props>(
|
|||||||
@{account?.acct}
|
@{account?.acct}
|
||||||
</Text>
|
</Text>
|
||||||
{account?.locked ? (
|
{account?.locked ? (
|
||||||
<Feather name='lock' style={styles.type} color={theme.secondary} />
|
<Icon
|
||||||
) : null}
|
name='Lock'
|
||||||
{account?.bot ? (
|
|
||||||
<Feather
|
|
||||||
name='hard-drive'
|
|
||||||
style={styles.type}
|
style={styles.type}
|
||||||
color={theme.secondary}
|
color={theme.secondary}
|
||||||
|
size={StyleConstants.Font.Size.M}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
{account?.bot ? (
|
||||||
|
<Icon
|
||||||
|
name='HardDrive'
|
||||||
|
style={styles.type}
|
||||||
|
color={theme.secondary}
|
||||||
|
size={StyleConstants.Font.Size.M}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</View>
|
</View>
|
||||||
|
@ -131,7 +131,7 @@ const AccountInformationActions: React.FC<Props> = ({ account }) => {
|
|||||||
{query.data && !query.data.blocked_by ? (
|
{query.data && !query.data.blocked_by ? (
|
||||||
<Button
|
<Button
|
||||||
type='icon'
|
type='icon'
|
||||||
content='mail'
|
content='Mail'
|
||||||
round
|
round
|
||||||
onPress={() =>
|
onPress={() =>
|
||||||
navigation.navigate('Screen-Shared-Compose', {
|
navigation.navigate('Screen-Shared-Compose', {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Feather } from '@expo/vector-icons'
|
import Icon from '@components/Icon'
|
||||||
import { StyleConstants } from '@root/utils/styles/constants'
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
import { useTheme } from '@root/utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import { LinearGradient } from 'expo-linear-gradient'
|
import { LinearGradient } from 'expo-linear-gradient'
|
||||||
import React, { forwardRef } from 'react'
|
import React, { forwardRef } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
@ -29,8 +29,8 @@ const AccountInformationCreated = forwardRef<ShimmerPlaceholder, Props>(
|
|||||||
shimmerColors={theme.shimmer}
|
shimmerColors={theme.shimmer}
|
||||||
>
|
>
|
||||||
<View style={styles.created}>
|
<View style={styles.created}>
|
||||||
<Feather
|
<Icon
|
||||||
name='calendar'
|
name='Calendar'
|
||||||
size={StyleConstants.Font.Size.S}
|
size={StyleConstants.Font.Size.S}
|
||||||
color={theme.secondary}
|
color={theme.secondary}
|
||||||
style={styles.icon}
|
style={styles.icon}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
import Icon from '@components/Icon'
|
||||||
import { ParseHTML } from '@components/Parse'
|
import { ParseHTML } from '@components/Parse'
|
||||||
import { Feather } from '@expo/vector-icons'
|
|
||||||
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 from 'react'
|
import React from 'react'
|
||||||
@ -27,8 +27,8 @@ const AccountInformationFields: React.FC<Props> = ({ account }) => {
|
|||||||
showFullLink
|
showFullLink
|
||||||
/>
|
/>
|
||||||
{field.verified_at ? (
|
{field.verified_at ? (
|
||||||
<Feather
|
<Icon
|
||||||
name='check-circle'
|
name='CheckCircle'
|
||||||
size={StyleConstants.Font.Size.M}
|
size={StyleConstants.Font.Size.M}
|
||||||
color={theme.primary}
|
color={theme.primary}
|
||||||
style={styles.fieldCheck}
|
style={styles.fieldCheck}
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
import { ParseEmojis } from '@components/Parse'
|
import { ParseEmojis } from '@components/Parse'
|
||||||
import { AccountState } from '@screens/Shared/Account'
|
|
||||||
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 from 'react'
|
import React, { MutableRefObject, useContext } from 'react'
|
||||||
import { Animated, Dimensions, StyleSheet, Text, View } from 'react-native'
|
import { Animated, Dimensions, StyleSheet, Text, View } from 'react-native'
|
||||||
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
||||||
|
import AccountContext from './utils/createContext'
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
accountState: AccountState
|
scrollY: MutableRefObject<Animated.Value>
|
||||||
scrollY: Animated.Value
|
|
||||||
account: Mastodon.Account | undefined
|
account: Mastodon.Account | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
const AccountNav: React.FC<Props> = ({ accountState, scrollY, account }) => {
|
const AccountNav: React.FC<Props> = ({ scrollY, account }) => {
|
||||||
|
const { accountState } = useContext(AccountContext)
|
||||||
const { theme } = useTheme()
|
const { theme } = useTheme()
|
||||||
const headerHeight = useSafeAreaInsets().top + 44
|
const headerHeight = useSafeAreaInsets().top + 44
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ const AccountNav: React.FC<Props> = ({ accountState, scrollY, account }) => {
|
|||||||
styles.base,
|
styles.base,
|
||||||
{
|
{
|
||||||
backgroundColor: theme.background,
|
backgroundColor: theme.background,
|
||||||
opacity: scrollY.interpolate({
|
opacity: scrollY.current.interpolate({
|
||||||
inputRange: [0, 200],
|
inputRange: [0, 200],
|
||||||
outputRange: [0, 1],
|
outputRange: [0, 1],
|
||||||
extrapolate: 'clamp'
|
extrapolate: 'clamp'
|
||||||
@ -51,7 +51,7 @@ const AccountNav: React.FC<Props> = ({ accountState, scrollY, account }) => {
|
|||||||
style={[
|
style={[
|
||||||
styles.display_name,
|
styles.display_name,
|
||||||
{
|
{
|
||||||
marginTop: scrollY.interpolate({
|
marginTop: scrollY.current.interpolate({
|
||||||
inputRange: [nameY, nameY + 20],
|
inputRange: [nameY, nameY + 20],
|
||||||
outputRange: [50, 0],
|
outputRange: [50, 0],
|
||||||
extrapolate: 'clamp'
|
extrapolate: 'clamp'
|
||||||
@ -89,4 +89,4 @@ const styles = StyleSheet.create({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export default AccountNav
|
export default React.memo(AccountNav, (_, next) => next.account === undefined)
|
||||||
|
@ -1,28 +1,23 @@
|
|||||||
import SegmentedControl from '@react-native-community/segmented-control'
|
import SegmentedControl from '@react-native-community/segmented-control'
|
||||||
import { StyleConstants } from '@root/utils/styles/constants'
|
import { StyleConstants } from '@root/utils/styles/constants'
|
||||||
import { useTheme } from '@root/utils/styles/ThemeManager'
|
import { useTheme } from '@root/utils/styles/ThemeManager'
|
||||||
import React, { Dispatch } from 'react'
|
import React, { MutableRefObject, useContext } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { Animated, StyleSheet } from 'react-native'
|
import { Animated, StyleSheet } from 'react-native'
|
||||||
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
||||||
import { AccountAction, AccountState } from '../Account'
|
import AccountContext from './utils/createContext'
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
accountState: AccountState
|
scrollY: MutableRefObject<Animated.Value>
|
||||||
accountDispatch: Dispatch<AccountAction>
|
|
||||||
scrollY: Animated.Value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const AccountSegmentedControl: React.FC<Props> = ({
|
const AccountSegmentedControl: React.FC<Props> = ({ scrollY }) => {
|
||||||
accountState,
|
const { accountState, accountDispatch } = useContext(AccountContext)
|
||||||
accountDispatch,
|
|
||||||
scrollY
|
|
||||||
}) => {
|
|
||||||
const { t } = useTranslation('sharedAccount')
|
const { t } = useTranslation('sharedAccount')
|
||||||
const { mode, theme } = useTheme()
|
const { mode, theme } = useTheme()
|
||||||
|
|
||||||
const headerHeight = useSafeAreaInsets().top + 44
|
const headerHeight = useSafeAreaInsets().top + 44
|
||||||
const translateY = scrollY.interpolate({
|
const translateY = scrollY.current.interpolate({
|
||||||
inputRange: [
|
inputRange: [
|
||||||
0,
|
0,
|
||||||
(accountState.informationLayout?.y || 0) +
|
(accountState.informationLayout?.y || 0) +
|
||||||
@ -82,4 +77,4 @@ const styles = StyleSheet.create({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export default AccountSegmentedControl
|
export default React.memo(AccountSegmentedControl, () => true)
|
||||||
|
@ -1,24 +1,18 @@
|
|||||||
import React, { Dispatch, useCallback } from 'react'
|
|
||||||
import { Dimensions, StyleSheet } from 'react-native'
|
|
||||||
import { TabView } from 'react-native-tab-view'
|
|
||||||
|
|
||||||
import Timeline from '@components/Timelines/Timeline'
|
import Timeline from '@components/Timelines/Timeline'
|
||||||
import { AccountAction, AccountState } from '../Account'
|
|
||||||
import { StyleConstants } from '@root/utils/styles/constants'
|
|
||||||
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
|
||||||
import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs'
|
import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs'
|
||||||
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
|
import React, { useContext } from 'react'
|
||||||
|
import { Dimensions, StyleSheet } from 'react-native'
|
||||||
|
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
||||||
|
import { TabView } from 'react-native-tab-view'
|
||||||
|
import AccountContext from './utils/createContext'
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
accountState: AccountState
|
|
||||||
accountDispatch: Dispatch<AccountAction>
|
|
||||||
id: Mastodon.Account['id']
|
id: Mastodon.Account['id']
|
||||||
}
|
}
|
||||||
|
|
||||||
const AccountToots: React.FC<Props> = ({
|
const AccountToots: React.FC<Props> = ({ id }) => {
|
||||||
accountState,
|
const { accountState, accountDispatch } = useContext(AccountContext)
|
||||||
accountDispatch,
|
|
||||||
id
|
|
||||||
}) => {
|
|
||||||
const headerHeight = useSafeAreaInsets().top + 44
|
const headerHeight = useSafeAreaInsets().top + 44
|
||||||
const footerHeight = useSafeAreaInsets().bottom + useBottomTabBarHeight()
|
const footerHeight = useSafeAreaInsets().bottom + useBottomTabBarHeight()
|
||||||
|
|
||||||
@ -28,18 +22,15 @@ const AccountToots: React.FC<Props> = ({
|
|||||||
{ key: 'Account_Media' }
|
{ key: 'Account_Media' }
|
||||||
]
|
]
|
||||||
|
|
||||||
const renderScene = useCallback(
|
const renderScene = ({
|
||||||
({
|
route
|
||||||
route
|
}: {
|
||||||
}: {
|
route: {
|
||||||
route: {
|
key: App.Pages
|
||||||
key: App.Pages
|
}
|
||||||
}
|
}) => {
|
||||||
}) => {
|
return <Timeline page={route.key} account={id} disableRefresh />
|
||||||
return <Timeline page={route.key} account={id} disableRefresh />
|
}
|
||||||
},
|
|
||||||
[]
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TabView
|
<TabView
|
||||||
|
10
src/screens/Shared/Account/utils/createContext.ts
Normal file
10
src/screens/Shared/Account/utils/createContext.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { createContext, Dispatch } from 'react'
|
||||||
|
import { AccountAction, AccountState } from './types'
|
||||||
|
|
||||||
|
type ContextType = {
|
||||||
|
accountState: AccountState
|
||||||
|
accountDispatch: Dispatch<AccountAction>
|
||||||
|
}
|
||||||
|
const AccountContext = createContext<ContextType>({} as ContextType)
|
||||||
|
|
||||||
|
export default AccountContext
|
9
src/screens/Shared/Account/utils/initialState.ts
Normal file
9
src/screens/Shared/Account/utils/initialState.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { AccountState } from "./types"
|
||||||
|
|
||||||
|
const accountInitialState: AccountState = {
|
||||||
|
headerRatio: 0.4,
|
||||||
|
informationLayout: { height: 0, y: 100 },
|
||||||
|
segmentedIndex: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
export default accountInitialState
|
19
src/screens/Shared/Account/utils/reducer.ts
Normal file
19
src/screens/Shared/Account/utils/reducer.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { AccountAction, AccountState } from "./types"
|
||||||
|
|
||||||
|
const accountReducer = (
|
||||||
|
state: AccountState,
|
||||||
|
action: AccountAction
|
||||||
|
): AccountState => {
|
||||||
|
switch (action.type) {
|
||||||
|
case 'headerRatio':
|
||||||
|
return { ...state, headerRatio: action.payload }
|
||||||
|
case 'informationLayout':
|
||||||
|
return { ...state, informationLayout: action.payload }
|
||||||
|
case 'segmentedIndex':
|
||||||
|
return { ...state, segmentedIndex: action.payload }
|
||||||
|
default:
|
||||||
|
throw new Error('Unexpected action')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default accountReducer
|
22
src/screens/Shared/Account/utils/types.d.ts
vendored
Normal file
22
src/screens/Shared/Account/utils/types.d.ts
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
export type AccountState = {
|
||||||
|
headerRatio: number
|
||||||
|
informationLayout?: {
|
||||||
|
y: number
|
||||||
|
height: number
|
||||||
|
}
|
||||||
|
segmentedIndex: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AccountAction =
|
||||||
|
| {
|
||||||
|
type: 'headerRatio'
|
||||||
|
payload: AccountState['headerRatio']
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: 'informationLayout'
|
||||||
|
payload: AccountState['informationLayout']
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: 'segmentedIndex'
|
||||||
|
payload: AccountState['segmentedIndex']
|
||||||
|
}
|
@ -157,8 +157,8 @@ const ScreenSharedAnnouncements: React.FC = ({
|
|||||||
style={[styles.reaction, { borderColor: theme.primary }]}
|
style={[styles.reaction, { borderColor: theme.primary }]}
|
||||||
onPress={() => invisibleTextInputRef.current?.focus()}
|
onPress={() => invisibleTextInputRef.current?.focus()}
|
||||||
>
|
>
|
||||||
<Feather
|
<Icon
|
||||||
name='plus'
|
name='Plus'
|
||||||
size={StyleConstants.Font.Size.M}
|
size={StyleConstants.Font.Size.M}
|
||||||
color={theme.primary}
|
color={theme.primary}
|
||||||
/>
|
/>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { Feather } from '@expo/vector-icons'
|
import Icon from '@components/Icon'
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
import layoutAnimation from '@utils/styles/layoutAnimation'
|
import layoutAnimation from '@utils/styles/layoutAnimation'
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import React, { useCallback, useContext, useMemo } from 'react'
|
import React, { useCallback, useContext, useMemo } from 'react'
|
||||||
import { ActionSheetIOS, StyleSheet, View } from 'react-native'
|
import { ActionSheetIOS, Pressable, StyleSheet, View } from 'react-native'
|
||||||
import addAttachment from './/addAttachment'
|
import addAttachment from './/addAttachment'
|
||||||
import ComposeContext from './utils/createContext'
|
import ComposeContext from './utils/createContext'
|
||||||
|
|
||||||
@ -53,13 +53,13 @@ const ComposeActions: React.FC = () => {
|
|||||||
const visibilityIcon = useMemo(() => {
|
const visibilityIcon = useMemo(() => {
|
||||||
switch (composeState.visibility) {
|
switch (composeState.visibility) {
|
||||||
case 'public':
|
case 'public':
|
||||||
return 'globe'
|
return 'Globe'
|
||||||
case 'unlisted':
|
case 'unlisted':
|
||||||
return 'unlock'
|
return 'Unlock'
|
||||||
case 'private':
|
case 'private':
|
||||||
return 'lock'
|
return 'Lock'
|
||||||
case 'direct':
|
case 'direct':
|
||||||
return 'mail'
|
return 'Mail'
|
||||||
}
|
}
|
||||||
}, [composeState.visibility])
|
}, [composeState.visibility])
|
||||||
const visibilityOnPress = useCallback(() => {
|
const visibilityOnPress = useCallback(() => {
|
||||||
@ -134,35 +134,41 @@ const ComposeActions: React.FC = () => {
|
|||||||
{ backgroundColor: theme.background, borderTopColor: theme.border }
|
{ backgroundColor: theme.background, borderTopColor: theme.border }
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Feather
|
<Pressable
|
||||||
name='aperture'
|
|
||||||
size={24}
|
|
||||||
color={attachmentColor}
|
|
||||||
onPress={attachmentOnPress}
|
onPress={attachmentOnPress}
|
||||||
|
children={<Icon name='Aperture' size={24} color={attachmentColor} />}
|
||||||
/>
|
/>
|
||||||
<Feather
|
<Pressable
|
||||||
name='bar-chart-2'
|
|
||||||
size={24}
|
|
||||||
color={pollColor}
|
|
||||||
onPress={pollOnPress}
|
onPress={pollOnPress}
|
||||||
|
children={<Icon name='BarChart2' size={24} color={pollColor} />}
|
||||||
/>
|
/>
|
||||||
<Feather
|
<Pressable
|
||||||
name={visibilityIcon}
|
|
||||||
size={24}
|
|
||||||
color={composeState.visibilityLock ? theme.disabled : theme.secondary}
|
|
||||||
onPress={visibilityOnPress}
|
onPress={visibilityOnPress}
|
||||||
|
children={
|
||||||
|
<Icon
|
||||||
|
name={visibilityIcon}
|
||||||
|
size={24}
|
||||||
|
color={
|
||||||
|
composeState.visibilityLock ? theme.disabled : theme.secondary
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<Feather
|
<Pressable
|
||||||
name='alert-triangle'
|
|
||||||
size={24}
|
|
||||||
color={composeState.spoiler.active ? theme.primary : theme.secondary}
|
|
||||||
onPress={spoilerOnPress}
|
onPress={spoilerOnPress}
|
||||||
|
children={
|
||||||
|
<Icon
|
||||||
|
name='AlertTriangle'
|
||||||
|
size={24}
|
||||||
|
color={
|
||||||
|
composeState.spoiler.active ? theme.primary : theme.secondary
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<Feather
|
<Pressable
|
||||||
name='smile'
|
|
||||||
size={24}
|
|
||||||
color={emojiColor}
|
|
||||||
onPress={emojiOnPress}
|
onPress={emojiOnPress}
|
||||||
|
children={<Icon name='Smile' size={24} color={emojiColor} />}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Feather } from '@expo/vector-icons'
|
|
||||||
import Button from '@components/Button'
|
import Button from '@components/Button'
|
||||||
import haptics from '@components/haptics'
|
import haptics from '@components/haptics'
|
||||||
|
import Icon from '@components/Icon'
|
||||||
import { useNavigation } from '@react-navigation/native'
|
import { useNavigation } from '@react-navigation/native'
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
import layoutAnimation from '@utils/styles/layoutAnimation'
|
import layoutAnimation from '@utils/styles/layoutAnimation'
|
||||||
@ -149,7 +149,7 @@ const ComposeAttachments: React.FC = () => {
|
|||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
type='icon'
|
type='icon'
|
||||||
content='x'
|
content='X'
|
||||||
spacing='M'
|
spacing='M'
|
||||||
round
|
round
|
||||||
overlay
|
overlay
|
||||||
@ -165,7 +165,7 @@ const ComposeAttachments: React.FC = () => {
|
|||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
type='icon'
|
type='icon'
|
||||||
content='edit'
|
content='Edit'
|
||||||
spacing='M'
|
spacing='M'
|
||||||
round
|
round
|
||||||
overlay
|
overlay
|
||||||
@ -198,7 +198,7 @@ const ComposeAttachments: React.FC = () => {
|
|||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
type='icon'
|
type='icon'
|
||||||
content='upload-cloud'
|
content='UploadCloud'
|
||||||
spacing='M'
|
spacing='M'
|
||||||
round
|
round
|
||||||
overlay
|
overlay
|
||||||
@ -224,8 +224,8 @@ const ComposeAttachments: React.FC = () => {
|
|||||||
return (
|
return (
|
||||||
<View style={styles.base}>
|
<View style={styles.base}>
|
||||||
<Pressable style={styles.sensitive} onPress={sensitiveOnPress}>
|
<Pressable style={styles.sensitive} onPress={sensitiveOnPress}>
|
||||||
<Feather
|
<Icon
|
||||||
name={composeState.attachments.sensitive ? 'check-circle' : 'circle'}
|
name={composeState.attachments.sensitive ? 'CheckCircle' : 'Circle'}
|
||||||
size={StyleConstants.Font.Size.L}
|
size={StyleConstants.Font.Size.L}
|
||||||
color={theme.primary}
|
color={theme.primary}
|
||||||
/>
|
/>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import Button from '@components/Button'
|
import Button from '@components/Button'
|
||||||
|
import Icon from '@components/Icon'
|
||||||
import { MenuRow } from '@components/Menu'
|
import { MenuRow } from '@components/Menu'
|
||||||
import { Feather } from '@expo/vector-icons'
|
|
||||||
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, { useContext, useEffect, useState } from 'react'
|
import React, { useContext, useEffect, useState } from 'react'
|
||||||
@ -47,8 +47,8 @@ const ComposePoll: React.FC = () => {
|
|||||||
})
|
})
|
||||||
return (
|
return (
|
||||||
<View key={i} style={styles.option}>
|
<View key={i} style={styles.option}>
|
||||||
<Feather
|
<Icon
|
||||||
name={multiple ? 'square' : 'circle'}
|
name={multiple ? 'Square' : 'Circle'}
|
||||||
size={StyleConstants.Font.Size.L}
|
size={StyleConstants.Font.Size.L}
|
||||||
color={theme.secondary}
|
color={theme.secondary}
|
||||||
/>
|
/>
|
||||||
@ -88,7 +88,7 @@ const ComposePoll: React.FC = () => {
|
|||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
type='icon'
|
type='icon'
|
||||||
content='minus'
|
content='Minus'
|
||||||
round
|
round
|
||||||
disabled={!(total > 2)}
|
disabled={!(total > 2)}
|
||||||
/>
|
/>
|
||||||
@ -102,7 +102,7 @@ const ComposePoll: React.FC = () => {
|
|||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
type='icon'
|
type='icon'
|
||||||
content='plus'
|
content='Plus'
|
||||||
round
|
round
|
||||||
disabled={!(total < 4)}
|
disabled={!(total < 4)}
|
||||||
/>
|
/>
|
||||||
@ -124,7 +124,7 @@ const ComposePoll: React.FC = () => {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
iconBack='chevron-right'
|
iconBack='ChevronRight'
|
||||||
/>
|
/>
|
||||||
<MenuRow
|
<MenuRow
|
||||||
title='有效期'
|
title='有效期'
|
||||||
@ -143,7 +143,7 @@ const ComposePoll: React.FC = () => {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
iconBack='chevron-right'
|
iconBack='ChevronRight'
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
@ -94,7 +94,7 @@ const ScreenSharedImagesViewer: React.FC<Props> = ({
|
|||||||
contentStyle: { backgroundColor: 'black' },
|
contentStyle: { backgroundColor: 'black' },
|
||||||
headerStyle: { backgroundColor: 'black' },
|
headerStyle: { backgroundColor: 'black' },
|
||||||
headerLeft: () => (
|
headerLeft: () => (
|
||||||
<HeaderLeft content='x' onPress={() => navigation.goBack()} />
|
<HeaderLeft content='X' onPress={() => navigation.goBack()} />
|
||||||
),
|
),
|
||||||
headerCenter: () => (
|
headerCenter: () => (
|
||||||
<Text style={styles.headerCenter}>
|
<Text style={styles.headerCenter}>
|
||||||
@ -103,7 +103,7 @@ const ScreenSharedImagesViewer: React.FC<Props> = ({
|
|||||||
),
|
),
|
||||||
headerRight: () => (
|
headerRight: () => (
|
||||||
<HeaderRight
|
<HeaderRight
|
||||||
content='share'
|
content='Share'
|
||||||
onPress={() =>
|
onPress={() =>
|
||||||
ActionSheetIOS.showShareActionSheetWithOptions(
|
ActionSheetIOS.showShareActionSheetWithOptions(
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { HeaderRight } from '@components/Header'
|
import { HeaderRight } from '@components/Header'
|
||||||
|
import Icon from '@components/Icon'
|
||||||
import { ParseEmojis, ParseHTML } from '@components/Parse'
|
import { ParseEmojis, ParseHTML } from '@components/Parse'
|
||||||
import { Feather } from '@expo/vector-icons'
|
|
||||||
import { useNavigation } from '@react-navigation/native'
|
import { useNavigation } from '@react-navigation/native'
|
||||||
import { searchFetch } from '@utils/fetches/searchFetch'
|
import { searchFetch } from '@utils/fetches/searchFetch'
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
@ -262,8 +262,8 @@ const ScreenSharedSearch: React.FC = () => {
|
|||||||
<View
|
<View
|
||||||
style={[styles.searchField, { borderBottomColor: theme.secondary }]}
|
style={[styles.searchField, { borderBottomColor: theme.secondary }]}
|
||||||
>
|
>
|
||||||
<Feather
|
<Icon
|
||||||
name='search'
|
name='Search'
|
||||||
color={theme.primary}
|
color={theme.primary}
|
||||||
size={StyleConstants.Font.Size.M}
|
size={StyleConstants.Font.Size.M}
|
||||||
style={styles.searchIcon}
|
style={styles.searchIcon}
|
||||||
|
@ -15,7 +15,7 @@ const ScreenSharedToot: React.FC<Props> = ({
|
|||||||
params: { toot }
|
params: { toot }
|
||||||
}
|
}
|
||||||
}) => {
|
}) => {
|
||||||
return <Timeline page='Toot' toot={toot} disableRefresh disableInfinity />
|
return <Timeline page='Toot' toot={toot.id} disableRefresh disableInfinity />
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ScreenSharedToot
|
export default ScreenSharedToot
|
||||||
|
@ -194,10 +194,16 @@ export const timelineFetch = async ({
|
|||||||
res = await client({
|
res = await client({
|
||||||
method: 'get',
|
method: 'get',
|
||||||
instance: 'local',
|
instance: 'local',
|
||||||
url: `statuses/${toot!.id}/context`
|
url: `statuses/${toot}`
|
||||||
|
})
|
||||||
|
const theToot = res.body
|
||||||
|
res = await client({
|
||||||
|
method: 'get',
|
||||||
|
instance: 'local',
|
||||||
|
url: `statuses/${toot}/context`
|
||||||
})
|
})
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
toots: [...res.body.ancestors, toot, ...res.body.descendants],
|
toots: [...res.body.ancestors, theToot, ...res.body.descendants],
|
||||||
pointer: res.body.ancestors.length
|
pointer: res.body.ancestors.length
|
||||||
})
|
})
|
||||||
default:
|
default:
|
||||||
|
@ -12,11 +12,11 @@
|
|||||||
"baseUrl": "./",
|
"baseUrl": "./",
|
||||||
"paths": {
|
"paths": {
|
||||||
// "@assets/*": ["./assets/*"],
|
// "@assets/*": ["./assets/*"],
|
||||||
"@root/*": ["./src/*"],
|
|
||||||
"@api/*": ["./src/api/*"],
|
"@api/*": ["./src/api/*"],
|
||||||
"@components/*": ["./src/components/*"],
|
"@components/*": ["./src/components/*"],
|
||||||
"@screens/*": ["./src/screens/*"],
|
"@screens/*": ["./src/screens/*"],
|
||||||
"@utils/*": ["./src/utils/*"]
|
"@utils/*": ["./src/utils/*"],
|
||||||
|
"@root/*": ["./src/*"],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
|
@ -8119,6 +8119,11 @@ react-native-expo-image-cache@^4.1.0:
|
|||||||
crypto-js "^3.1.9-1"
|
crypto-js "^3.1.9-1"
|
||||||
lodash "^4.17.4"
|
lodash "^4.17.4"
|
||||||
|
|
||||||
|
react-native-feather@^1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-native-feather/-/react-native-feather-1.0.2.tgz#9b02a32f313088084da5ebb0130659fa582edf43"
|
||||||
|
integrity sha512-SxMCMyGQeDtZtl2mhssoFTsfFKh/eH6S11+720BPGYYXz1iaYwQ4G/xqFxWOvQOQK2qtOTvkFOBlabbKwBMuhQ==
|
||||||
|
|
||||||
react-native-gesture-handler@~1.8.0:
|
react-native-gesture-handler@~1.8.0:
|
||||||
version "1.8.0"
|
version "1.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-1.8.0.tgz#18f61f51da50320f938957b0ee79bc58f47449dc"
|
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-1.8.0.tgz#18f61f51da50320f938957b0ee79bc58f47449dc"
|
||||||
|
Reference in New Issue
Block a user