mirror of
https://github.com/tooot-app/app
synced 2025-06-05 22:19:13 +02:00
Preparing for CI test
This commit is contained in:
@@ -114,14 +114,18 @@ const Index: React.FC<Props> = ({ localCorrupt }) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<StatusBar barStyle={barStyle[mode]} backgroundColor={theme.background} />
|
||||
<StatusBar barStyle={barStyle[mode]} />
|
||||
<NavigationContainer
|
||||
ref={navigationRef}
|
||||
theme={themes[mode]}
|
||||
onReady={navigationContainerOnReady}
|
||||
onStateChange={navigationContainerOnStateChange}
|
||||
>
|
||||
<Stack.Navigator mode='modal' initialRouteName='Screen-Tabs'>
|
||||
<Stack.Navigator
|
||||
mode='modal'
|
||||
initialRouteName='Screen-Tabs'
|
||||
screenOptions={{ cardStyle: { backgroundColor: theme.background } }}
|
||||
>
|
||||
<Stack.Screen
|
||||
name='Screen-Tabs'
|
||||
component={ScreenTabs}
|
||||
|
@@ -1,14 +1,8 @@
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import React, { useCallback, useState } from 'react'
|
||||
import {
|
||||
ImageStyle,
|
||||
Pressable,
|
||||
StyleProp,
|
||||
StyleSheet,
|
||||
ViewStyle
|
||||
} from 'react-native'
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
import { Pressable, StyleProp, StyleSheet, ViewStyle } from 'react-native'
|
||||
import { Blurhash } from 'react-native-blurhash'
|
||||
import FastImage from 'react-native-fast-image'
|
||||
import FastImage, { ImageStyle } from 'react-native-fast-image'
|
||||
import { SharedElement } from 'react-navigation-shared-element'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
|
||||
@@ -23,70 +17,120 @@ export interface Props {
|
||||
imageStyle?: StyleProp<ImageStyle>
|
||||
}
|
||||
|
||||
const GracefullyImage: React.FC<Props> = ({
|
||||
sharedElement,
|
||||
hidden = false,
|
||||
uri,
|
||||
blurhash,
|
||||
dimension,
|
||||
onPress,
|
||||
style,
|
||||
imageStyle
|
||||
}) => {
|
||||
const { mode, theme } = useTheme()
|
||||
const [imageLoaded, setImageLoaded] = useState(false)
|
||||
|
||||
const children = useCallback(() => {
|
||||
return (
|
||||
<>
|
||||
{sharedElement ? (
|
||||
<SharedElement id={`image.${sharedElement}`} style={[styles.image]}>
|
||||
<FastImage
|
||||
source={{ uri: uri.preview || uri.original || uri.remote }}
|
||||
style={[styles.image, imageStyle]}
|
||||
onLoad={() => setImageLoaded(true)}
|
||||
/>
|
||||
</SharedElement>
|
||||
) : (
|
||||
<FastImage
|
||||
source={{ uri: uri.preview || uri.original || uri.remote }}
|
||||
style={[styles.image, imageStyle]}
|
||||
onLoad={() => setImageLoaded(true)}
|
||||
/>
|
||||
)}
|
||||
{blurhash && (hidden || !imageLoaded) ? (
|
||||
<Blurhash
|
||||
decodeAsync
|
||||
blurhash={blurhash}
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
position: 'absolute',
|
||||
top: StyleConstants.Spacing.XS / 2,
|
||||
left: StyleConstants.Spacing.XS / 2
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
const GracefullyImage = React.memo(
|
||||
({
|
||||
sharedElement,
|
||||
hidden = false,
|
||||
uri,
|
||||
blurhash,
|
||||
dimension,
|
||||
onPress,
|
||||
style,
|
||||
imageStyle
|
||||
}: Props) => {
|
||||
const { mode, theme } = useTheme()
|
||||
const [previewLoaded, setPreviewLoaded] = useState(
|
||||
uri.preview ? false : true
|
||||
)
|
||||
}, [hidden, imageLoaded, mode, uri])
|
||||
const [originalLoaded, setOriginalLoaded] = useState(false)
|
||||
const [originalFailed, setOriginalFailed] = useState(false)
|
||||
const [remoteLoaded, setRemoteLoaded] = useState(uri.remote ? false : true)
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
children={children}
|
||||
style={[
|
||||
style,
|
||||
{ backgroundColor: theme.shimmerDefault },
|
||||
dimension && { ...dimension }
|
||||
]}
|
||||
{...(onPress
|
||||
? hidden
|
||||
? { disabled: true }
|
||||
: { onPress }
|
||||
: { disabled: true })}
|
||||
/>
|
||||
)
|
||||
}
|
||||
const sourceUri = useMemo(() => {
|
||||
if (previewLoaded) {
|
||||
if (originalFailed) {
|
||||
return uri.remote
|
||||
} else {
|
||||
return uri.original
|
||||
}
|
||||
} else {
|
||||
return uri.preview
|
||||
}
|
||||
}, [previewLoaded, originalLoaded, originalFailed, remoteLoaded])
|
||||
const onLoad = useCallback(() => {
|
||||
if (previewLoaded) {
|
||||
if (originalFailed) {
|
||||
return setRemoteLoaded(true)
|
||||
} else {
|
||||
return setOriginalLoaded(true)
|
||||
}
|
||||
} else {
|
||||
return setPreviewLoaded(true)
|
||||
}
|
||||
}, [previewLoaded, originalLoaded, originalFailed, remoteLoaded])
|
||||
const onError = useCallback(() => {
|
||||
if (previewLoaded) {
|
||||
if (originalFailed) {
|
||||
return
|
||||
} else {
|
||||
return setOriginalFailed(true)
|
||||
}
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}, [previewLoaded, originalLoaded, originalFailed, remoteLoaded])
|
||||
|
||||
const children = useCallback(() => {
|
||||
return (
|
||||
<>
|
||||
{sharedElement ? (
|
||||
<SharedElement id={`image.${sharedElement}`} style={[styles.image]}>
|
||||
<FastImage
|
||||
source={{ uri: sourceUri }}
|
||||
style={[styles.image, imageStyle]}
|
||||
onLoad={onLoad}
|
||||
onError={onError}
|
||||
/>
|
||||
</SharedElement>
|
||||
) : (
|
||||
<FastImage
|
||||
source={{ uri: sourceUri }}
|
||||
style={[styles.image, imageStyle]}
|
||||
onLoad={onLoad}
|
||||
onError={onError}
|
||||
/>
|
||||
)}
|
||||
{blurhash &&
|
||||
(hidden || !(previewLoaded || originalLoaded || remoteLoaded)) ? (
|
||||
<Blurhash
|
||||
decodeAsync
|
||||
blurhash={blurhash}
|
||||
style={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
position: 'absolute',
|
||||
top: StyleConstants.Spacing.XS / 2,
|
||||
left: StyleConstants.Spacing.XS / 2
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
)
|
||||
}, [hidden, previewLoaded, originalLoaded, remoteLoaded, mode, uri])
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
children={children}
|
||||
style={[
|
||||
style,
|
||||
{ backgroundColor: theme.shimmerDefault },
|
||||
dimension && { ...dimension }
|
||||
]}
|
||||
{...(onPress
|
||||
? hidden
|
||||
? { disabled: true }
|
||||
: { onPress }
|
||||
: { disabled: true })}
|
||||
/>
|
||||
)
|
||||
},
|
||||
(prev, next) => {
|
||||
let skipUpdate = true
|
||||
skipUpdate = prev.hidden === next.hidden
|
||||
skipUpdate = prev.uri.original === next.uri.original
|
||||
return false
|
||||
}
|
||||
)
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
image: {
|
||||
|
@@ -202,6 +202,7 @@ const TimelineActions: React.FC<Props> = ({
|
||||
: iconColorAction(status.reblogged)
|
||||
}
|
||||
size={StyleConstants.Font.Size.L}
|
||||
strokeWidth={status.reblogged ? 3 : undefined}
|
||||
/>
|
||||
{status.reblogs_count > 0 && (
|
||||
<Text
|
||||
@@ -225,6 +226,7 @@ const TimelineActions: React.FC<Props> = ({
|
||||
name='Heart'
|
||||
color={iconColorAction(status.favourited)}
|
||||
size={StyleConstants.Font.Size.L}
|
||||
strokeWidth={status.favourited ? 3 : undefined}
|
||||
/>
|
||||
{status.favourites_count > 0 && (
|
||||
<Text
|
||||
@@ -248,6 +250,7 @@ const TimelineActions: React.FC<Props> = ({
|
||||
name='Bookmark'
|
||||
color={iconColorAction(status.bookmarked)}
|
||||
size={StyleConstants.Font.Size.L}
|
||||
strokeWidth={status.bookmarked ? 3 : undefined}
|
||||
/>
|
||||
),
|
||||
[status.bookmarked]
|
||||
|
@@ -114,7 +114,7 @@ const TimelineAttachment: React.FC<Props> = ({ status }) => {
|
||||
|
||||
return (
|
||||
<View>
|
||||
<View style={styles.container}>{attachments}</View>
|
||||
<View style={styles.container} children={attachments} />
|
||||
|
||||
{status.sensitive &&
|
||||
(sensitiveShown ? (
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import analytics from '@components/analytics'
|
||||
import Button from '@components/Button'
|
||||
import GracefullyImage from '@components/GracefullyImage'
|
||||
import { Slider } from '@sharcoux/slider'
|
||||
@@ -8,7 +9,6 @@ import React, { useCallback, useState } from 'react'
|
||||
import { StyleSheet, View } from 'react-native'
|
||||
import { Blurhash } from 'react-native-blurhash'
|
||||
import attachmentAspectRatio from './aspectRatio'
|
||||
import analytics from '@components/analytics'
|
||||
|
||||
export interface Props {
|
||||
total: number
|
||||
|
@@ -27,6 +27,7 @@ const TimelineCard: React.FC<Props> = ({ card }) => {
|
||||
uri={{ original: card.image }}
|
||||
blurhash={card.blurhash}
|
||||
style={styles.left}
|
||||
imageStyle={styles.image}
|
||||
/>
|
||||
)}
|
||||
<View style={styles.right}>
|
||||
@@ -64,15 +65,13 @@ const styles = StyleSheet.create({
|
||||
height: StyleConstants.Font.LineHeight.M * 5,
|
||||
marginTop: StyleConstants.Spacing.M,
|
||||
borderWidth: StyleSheet.hairlineWidth,
|
||||
borderRadius: 6
|
||||
borderRadius: 6,
|
||||
overflow: 'hidden'
|
||||
},
|
||||
left: {
|
||||
width: StyleConstants.Font.LineHeight.M * 5,
|
||||
height: StyleConstants.Font.LineHeight.M * 5
|
||||
flexBasis: StyleConstants.Font.LineHeight.M * 5
|
||||
},
|
||||
image: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
borderTopLeftRadius: 6,
|
||||
borderBottomLeftRadius: 6
|
||||
},
|
||||
|
@@ -1,8 +1,11 @@
|
||||
import analytics from '@components/analytics'
|
||||
import Button from '@components/Button'
|
||||
import { StackScreenProps } from '@react-navigation/stack'
|
||||
import { getLocalAccount, getLocalUrl } from '@utils/slices/instancesSlice'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import React, { useCallback, useEffect, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Dimensions, StyleSheet, View } from 'react-native'
|
||||
import {
|
||||
PanGestureHandler,
|
||||
@@ -32,6 +35,8 @@ export type ScreenAccountProp = StackScreenProps<
|
||||
|
||||
const ScreenActions = React.memo(
|
||||
({ route: { params }, navigation }: ScreenAccountProp) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const localAccount = useSelector(getLocalAccount)
|
||||
let sameAccount = false
|
||||
switch (params.type) {
|
||||
@@ -174,6 +179,15 @@ const ScreenActions = React.memo(
|
||||
]}
|
||||
/>
|
||||
{actions}
|
||||
<Button
|
||||
type='text'
|
||||
content={t('common:buttons.cancel')}
|
||||
onPress={() => {
|
||||
analytics('bottomsheet_cancel')
|
||||
// dismiss()
|
||||
}}
|
||||
style={styles.button}
|
||||
/>
|
||||
</Animated.View>
|
||||
</PanGestureHandler>
|
||||
</Animated.View>
|
||||
|
@@ -229,7 +229,7 @@ const ScreenCompose: React.FC<ScreenComposeProp> = ({
|
||||
|
||||
return (
|
||||
<KeyboardAvoidingView
|
||||
style={[styles.base, {backgroundColor: 'red'}]}
|
||||
style={styles.base}
|
||||
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
||||
>
|
||||
<SafeAreaView
|
||||
|
@@ -2,7 +2,8 @@ import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import React, { MutableRefObject, useContext } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Dimensions, Image, StyleSheet, Text, View } from 'react-native'
|
||||
import { Dimensions, StyleSheet, Text, View } from 'react-native'
|
||||
import FastImage from 'react-native-fast-image'
|
||||
import { PanGestureHandler } from 'react-native-gesture-handler'
|
||||
import Animated, {
|
||||
Extrapolate,
|
||||
@@ -110,7 +111,7 @@ const ComposeEditAttachmentImage: React.FC<Props> = ({ index, focus }) => {
|
||||
return (
|
||||
<>
|
||||
<View style={{ overflow: 'hidden', flex: 1, alignItems: 'center' }}>
|
||||
<Image
|
||||
<FastImage
|
||||
style={{
|
||||
width: imageDimensionis.width,
|
||||
height: imageDimensionis.height
|
||||
|
@@ -53,14 +53,6 @@ const ComposeRoot: React.FC = () => {
|
||||
})
|
||||
}
|
||||
}, [emojisData])
|
||||
useEffect(() => {
|
||||
if (emojisData && emojisData.length) {
|
||||
// Prefetch first batch of emojis for faster loading experience
|
||||
emojisData.slice(0, 40).forEach(emoji => {
|
||||
Image.prefetch(emoji.url)
|
||||
})
|
||||
}
|
||||
}, [emojisData])
|
||||
|
||||
const listEmpty = useMemo(() => {
|
||||
if (isFetching) {
|
||||
|
@@ -15,15 +15,9 @@ import React, {
|
||||
useRef
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
FlatList,
|
||||
Image,
|
||||
Pressable,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View
|
||||
} from 'react-native'
|
||||
import { FlatList, Pressable, StyleSheet, Text, View } from 'react-native'
|
||||
import { Chase } from 'react-native-animated-spinkit'
|
||||
import FastImage from 'react-native-fast-image'
|
||||
import ComposeContext from '../../utils/createContext'
|
||||
import { ExtendedAttachment } from '../../utils/types'
|
||||
import addAttachment from './addAttachment'
|
||||
@@ -120,7 +114,7 @@ const ComposeAttachments: React.FC = () => {
|
||||
key={index}
|
||||
style={[styles.container, { width: calculateWidth(item) }]}
|
||||
>
|
||||
<Image
|
||||
<FastImage
|
||||
style={styles.image}
|
||||
source={{
|
||||
uri: item.local?.local_thumbnail || item.remote?.preview_url
|
||||
|
@@ -1,18 +1,12 @@
|
||||
import analytics from '@components/analytics'
|
||||
import haptics from '@components/haptics'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import React, { useCallback, useContext, useMemo } from 'react'
|
||||
import {
|
||||
Image,
|
||||
Pressable,
|
||||
SectionList,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View
|
||||
} from 'react-native'
|
||||
import { Pressable, SectionList, StyleSheet, Text, View } from 'react-native'
|
||||
import FastImage from 'react-native-fast-image'
|
||||
import ComposeContext from '../../utils/createContext'
|
||||
import updateText from '../../updateText'
|
||||
import analytics from '@components/analytics'
|
||||
|
||||
const SingleEmoji = ({ emoji }: { emoji: Mastodon.Emoji }) => {
|
||||
const { composeState, composeDispatch } = useContext(ComposeContext)
|
||||
@@ -31,7 +25,7 @@ const SingleEmoji = ({ emoji }: { emoji: Mastodon.Emoji }) => {
|
||||
haptics('Success')
|
||||
}, [])
|
||||
const children = useMemo(
|
||||
() => <Image source={{ uri: emoji.url }} style={styles.emoji} />,
|
||||
() => <FastImage source={{ uri: emoji.url }} style={styles.emoji} />,
|
||||
[]
|
||||
)
|
||||
return (
|
||||
|
@@ -10,11 +10,10 @@ import { useTimelineQuery } from '@utils/queryHooks/timeline'
|
||||
import {
|
||||
getLocalAccount,
|
||||
getLocalActiveIndex,
|
||||
getLocalNotification,
|
||||
localUpdateNotification
|
||||
getLocalNotification
|
||||
} from '@utils/slices/instancesSlice'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import React, { useCallback, useEffect, useMemo } from 'react'
|
||||
import React, { useCallback, useMemo } from 'react'
|
||||
import { Platform } from 'react-native'
|
||||
import FastImage from 'react-native-fast-image'
|
||||
import { useDispatch, useSelector } from 'react-redux'
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import Constants from 'expo-constants'
|
||||
import * as Updates from 'expo-updates'
|
||||
import React from 'react'
|
||||
import { ScrollView } from 'react-native-gesture-handler'
|
||||
import SettingsAnalytics from './Settings/Analytics'
|
||||
@@ -15,7 +15,7 @@ const ScreenMeSettings: React.FC = () => {
|
||||
|
||||
{__DEV__ ||
|
||||
['development'].some(channel =>
|
||||
Constants.manifest.releaseChannel?.includes(channel)
|
||||
Updates.releaseChannel.includes(channel)
|
||||
) ? (
|
||||
<SettingsDev />
|
||||
) : null}
|
||||
|
@@ -6,6 +6,7 @@ import {
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import Constants from 'expo-constants'
|
||||
import * as Updates from 'expo-updates'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { StyleSheet, Text } from 'react-native'
|
||||
@@ -31,7 +32,7 @@ const SettingsAnalytics: React.FC = () => {
|
||||
<Text style={[styles.version, { color: theme.secondary }]}>
|
||||
{t('content.version', {
|
||||
version: Constants.manifest.version,
|
||||
releaseChannel: Constants.manifest.releaseChannel || 'dev'
|
||||
releaseChannel: Updates.releaseChannel
|
||||
})}
|
||||
</Text>
|
||||
</MenuContainer>
|
||||
|
@@ -6,7 +6,7 @@ import { useSearchQuery } from '@utils/queryHooks/search'
|
||||
import { getLocalActiveIndex } from '@utils/slices/instancesSlice'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import Constants from 'expo-constants'
|
||||
import * as Updates from 'expo-updates'
|
||||
import * as Linking from 'expo-linking'
|
||||
import * as StoreReview from 'expo-store-review'
|
||||
import * as WebBrowser from 'expo-web-browser'
|
||||
@@ -44,7 +44,7 @@ const SettingsTooot: React.FC = () => {
|
||||
/>
|
||||
{__DEV__ ||
|
||||
['production', 'development'].some(channel =>
|
||||
Constants.manifest.releaseChannel?.includes(channel)
|
||||
Updates.releaseChannel?.includes(channel)
|
||||
) ? (
|
||||
<MenuRow
|
||||
title={t('content.review.heading')}
|
||||
|
@@ -7,7 +7,6 @@ import {
|
||||
getLocalActiveIndex,
|
||||
getLocalInstances,
|
||||
InstanceLocal,
|
||||
InstancesState,
|
||||
localUpdateActiveIndex
|
||||
} from '@utils/slices/instancesSlice'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
@@ -26,16 +25,11 @@ import { useQueryClient } from 'react-query'
|
||||
import { useDispatch, useSelector } from 'react-redux'
|
||||
|
||||
interface Props {
|
||||
index: NonNullable<InstancesState['local']['activeIndex']>
|
||||
instance: InstanceLocal
|
||||
disabled?: boolean
|
||||
}
|
||||
|
||||
const AccountButton: React.FC<Props> = ({
|
||||
index,
|
||||
instance,
|
||||
disabled = false
|
||||
}) => {
|
||||
const AccountButton: React.FC<Props> = ({ instance, disabled = false }) => {
|
||||
const queryClient = useQueryClient()
|
||||
const navigation = useNavigation()
|
||||
const dispatch = useDispatch()
|
||||
@@ -51,7 +45,7 @@ const AccountButton: React.FC<Props> = ({
|
||||
onPress={() => {
|
||||
haptics('Light')
|
||||
analytics('switch_existing_press')
|
||||
dispatch(localUpdateActiveIndex(index))
|
||||
dispatch(localUpdateActiveIndex(instance))
|
||||
queryClient.clear()
|
||||
navigation.goBack()
|
||||
}}
|
||||
@@ -86,14 +80,20 @@ const ScreenMeSwitchRoot: React.FC = () => {
|
||||
`${b.uri}${b.account.acct}`
|
||||
)
|
||||
)
|
||||
.map((instance, index) => (
|
||||
<AccountButton
|
||||
key={index}
|
||||
index={index}
|
||||
instance={instance}
|
||||
disabled={localActiveIndex === index}
|
||||
/>
|
||||
))
|
||||
.map((instance, index) => {
|
||||
const localAccount = localInstances[localActiveIndex!]
|
||||
return (
|
||||
<AccountButton
|
||||
key={index}
|
||||
instance={instance}
|
||||
disabled={
|
||||
instance.url === localAccount.url &&
|
||||
instance.token === localAccount.token &&
|
||||
instance.account.id === localAccount.account.id
|
||||
}
|
||||
/>
|
||||
)
|
||||
})
|
||||
: null}
|
||||
</View>
|
||||
</View>
|
||||
|
@@ -1,11 +1,7 @@
|
||||
import { useTheme } from '@utils/styles/ThemeManager'
|
||||
import React, { useContext, useEffect } from 'react'
|
||||
import { Dimensions, Image } from 'react-native'
|
||||
import Animated, {
|
||||
useAnimatedStyle,
|
||||
useSharedValue,
|
||||
withTiming
|
||||
} from 'react-native-reanimated'
|
||||
import React, { useContext } from 'react'
|
||||
import { Dimensions } from 'react-native'
|
||||
import FastImage from 'react-native-fast-image'
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
||||
import AccountContext from './utils/createContext'
|
||||
|
||||
@@ -15,39 +11,18 @@ export interface Props {
|
||||
}
|
||||
|
||||
const AccountHeader: React.FC<Props> = ({ account, limitHeight = false }) => {
|
||||
const { accountState, accountDispatch } = useContext(AccountContext)
|
||||
const { accountState } = useContext(AccountContext)
|
||||
const { theme } = useTheme()
|
||||
const topInset = useSafeAreaInsets().top
|
||||
|
||||
const height = useSharedValue(
|
||||
Dimensions.get('screen').width * accountState.headerRatio + topInset
|
||||
)
|
||||
const styleHeight = useAnimatedStyle(() => {
|
||||
return {
|
||||
height: withTiming(height.value)
|
||||
}
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
account?.header &&
|
||||
!account.header.includes('/headers/original/missing.png')
|
||||
) {
|
||||
Image.getSize(account.header, (width, height) => {
|
||||
// if (!limitHeight) {
|
||||
// accountDispatch({
|
||||
// type: 'headerRatio',
|
||||
// payload: height / width
|
||||
// })
|
||||
// }
|
||||
})
|
||||
}
|
||||
}, [account])
|
||||
|
||||
return (
|
||||
<Animated.Image
|
||||
<FastImage
|
||||
source={{ uri: account?.header }}
|
||||
style={[styleHeight, { backgroundColor: theme.disabled }]}
|
||||
style={{
|
||||
height:
|
||||
Dimensions.get('screen').width * accountState.headerRatio + topInset,
|
||||
backgroundColor: theme.disabled
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
@@ -88,7 +88,9 @@ const styles = StyleSheet.create({
|
||||
}
|
||||
})
|
||||
|
||||
export default React.memo(
|
||||
AccountInformation,
|
||||
(_, next) => next.account === undefined
|
||||
)
|
||||
export default React.memo(AccountInformation, (prev, next) => {
|
||||
let skipUpdate = true
|
||||
skipUpdate = prev.account?.id === next.account?.id
|
||||
skipUpdate = prev.account?.acct === next.account?.acct
|
||||
return skipUpdate
|
||||
})
|
||||
|
@@ -3,7 +3,7 @@ import GracefullyImage from '@components/GracefullyImage'
|
||||
import { useNavigation } from '@react-navigation/native'
|
||||
import { StackNavigationProp } from '@react-navigation/stack'
|
||||
import { StyleConstants } from '@utils/styles/constants'
|
||||
import React, { useMemo } from 'react'
|
||||
import React from 'react'
|
||||
import { Pressable, StyleSheet } from 'react-native'
|
||||
|
||||
export interface Props {
|
||||
@@ -15,35 +15,33 @@ const AccountInformationAvatar: React.FC<Props> = ({ account, myInfo }) => {
|
||||
const navigation = useNavigation<
|
||||
StackNavigationProp<Nav.TabLocalStackParamList>
|
||||
>()
|
||||
const dimension = useMemo(
|
||||
() => ({
|
||||
width: StyleConstants.Avatar.L,
|
||||
height: StyleConstants.Avatar.L
|
||||
}),
|
||||
[]
|
||||
)
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
disabled={!myInfo}
|
||||
onPress={() => {
|
||||
analytics('account_avatar_press')
|
||||
myInfo &&
|
||||
account &&
|
||||
navigation.push('Tab-Shared-Account', { account })
|
||||
myInfo && account && navigation.push('Tab-Shared-Account', { account })
|
||||
}}
|
||||
style={styles.base}
|
||||
>
|
||||
<GracefullyImage
|
||||
style={styles.base}
|
||||
key={account?.avatar}
|
||||
style={styles.image}
|
||||
uri={{ original: account?.avatar || '' }}
|
||||
dimension={dimension}
|
||||
/>
|
||||
</Pressable>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
base: { borderRadius: 8, overflow: 'hidden' }
|
||||
base: {
|
||||
borderRadius: 8,
|
||||
overflow: 'hidden',
|
||||
width: StyleConstants.Avatar.L,
|
||||
height: StyleConstants.Avatar.L
|
||||
},
|
||||
image: { flex: 1 }
|
||||
})
|
||||
|
||||
export default AccountInformationAvatar
|
||||
|
@@ -1,18 +1,17 @@
|
||||
import Constants from 'expo-constants'
|
||||
import * as Updates from 'expo-updates'
|
||||
import * as Sentry from 'sentry-expo'
|
||||
import log from './log'
|
||||
|
||||
const sentry = () => {
|
||||
log('log', 'Sentry', 'initializing')
|
||||
Sentry.init({
|
||||
environment: Constants.manifest.extra.sentryEnv,
|
||||
dsn: Constants.manifest.extra.sentryDSN,
|
||||
environment: Constants.manifest.extra.toootEnvironment,
|
||||
enableInExpoDevelopment: false,
|
||||
debug:
|
||||
__DEV__ ||
|
||||
['development'].some(channel =>
|
||||
Constants.manifest.releaseChannel?.includes(channel)
|
||||
)
|
||||
['development'].some(channel => Updates.releaseChannel.includes(channel))
|
||||
})
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
|
||||
import { RootState } from '@root/store'
|
||||
import Constants from 'expo-constants'
|
||||
import * as Updates from 'expo-updates'
|
||||
import * as StoreReview from 'expo-store-review'
|
||||
|
||||
export const supportedLngs = ['zh-Hans', 'en']
|
||||
@@ -38,7 +38,7 @@ const contextsSlice = createSlice({
|
||||
initialState: contextsInitialState as ContextsState,
|
||||
reducers: {
|
||||
updateStoreReview: (state, action: PayloadAction<1>) => {
|
||||
if (Constants.manifest.releaseChannel?.includes('production')) {
|
||||
if (Updates.releaseChannel.includes('production')) {
|
||||
state.storeReview.current = state.storeReview.current + action.payload
|
||||
if (state.storeReview.current === state.storeReview.context) {
|
||||
StoreReview.isAvailableAsync().then(() => StoreReview.requestReview())
|
||||
|
@@ -175,15 +175,13 @@ const instancesSlice = createSlice({
|
||||
name: 'instances',
|
||||
initialState: instancesInitialState,
|
||||
reducers: {
|
||||
localUpdateActiveIndex: (
|
||||
state,
|
||||
action: PayloadAction<NonNullable<InstancesState['local']['activeIndex']>>
|
||||
) => {
|
||||
if (action.payload < state.local.instances.length) {
|
||||
state.local.activeIndex = action.payload
|
||||
} else {
|
||||
throw new Error('Set index cannot be found')
|
||||
}
|
||||
localUpdateActiveIndex: (state, action: PayloadAction<InstanceLocal>) => {
|
||||
state.local.activeIndex = state.local.instances.findIndex(
|
||||
instance =>
|
||||
instance.url === action.payload.url &&
|
||||
instance.token === action.payload.token &&
|
||||
instance.account.id === action.payload.account.id
|
||||
)
|
||||
},
|
||||
localUpdateAccount: (
|
||||
state,
|
||||
|
Reference in New Issue
Block a user