mirror of
https://github.com/tooot-app/app
synced 2025-04-25 07:28:41 +02:00
Updates
This commit is contained in:
parent
17f15a199c
commit
83048450e8
@ -9,9 +9,18 @@ import * as WebBrowser from 'expo-web-browser'
|
|||||||
import { debounce } from 'lodash'
|
import { debounce } from 'lodash'
|
||||||
import React, { useCallback, useMemo, useState } from 'react'
|
import React, { useCallback, useMemo, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { Alert, Image, StyleSheet, Text, TextInput, View } from 'react-native'
|
import {
|
||||||
|
Alert,
|
||||||
|
Image,
|
||||||
|
KeyboardAvoidingView,
|
||||||
|
Platform,
|
||||||
|
StyleSheet,
|
||||||
|
Text,
|
||||||
|
TextInput,
|
||||||
|
View
|
||||||
|
} from 'react-native'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
import { Placeholder, Fade } from 'rn-placeholder'
|
import { Placeholder } from 'rn-placeholder'
|
||||||
import analytics from './analytics'
|
import analytics from './analytics'
|
||||||
import InstanceAuth from './Instance/Auth'
|
import InstanceAuth from './Instance/Auth'
|
||||||
import InstanceInfo from './Instance/Info'
|
import InstanceInfo from './Instance/Info'
|
||||||
@ -115,7 +124,10 @@ const ComponentInstance: React.FC<Props> = ({
|
|||||||
}, [domain, instanceQuery.data, appsQuery.data])
|
}, [domain, instanceQuery.data, appsQuery.data])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<KeyboardAvoidingView
|
||||||
|
style={{ flex: 1 }}
|
||||||
|
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
||||||
|
>
|
||||||
{!disableHeaderImage ? (
|
{!disableHeaderImage ? (
|
||||||
<View style={styles.imageContainer}>
|
<View style={styles.imageContainer}>
|
||||||
<Image
|
<Image
|
||||||
@ -157,18 +169,8 @@ const ComponentInstance: React.FC<Props> = ({
|
|||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View>
|
<View>
|
||||||
<Placeholder
|
<Placeholder>
|
||||||
{...(instanceQuery.isFetching && {
|
|
||||||
Animation: props => (
|
|
||||||
<Fade
|
|
||||||
{...props}
|
|
||||||
style={{ backgroundColor: theme.shimmerHighlight }}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<InstanceInfo
|
<InstanceInfo
|
||||||
visible={instanceQuery.data?.title !== undefined}
|
|
||||||
header={t('server.information.name')}
|
header={t('server.information.name')}
|
||||||
content={instanceQuery.data?.title || undefined}
|
content={instanceQuery.data?.title || undefined}
|
||||||
potentialWidth={2}
|
potentialWidth={2}
|
||||||
@ -176,7 +178,6 @@ const ComponentInstance: React.FC<Props> = ({
|
|||||||
<View style={styles.instanceStats}>
|
<View style={styles.instanceStats}>
|
||||||
<InstanceInfo
|
<InstanceInfo
|
||||||
style={styles.stat1}
|
style={styles.stat1}
|
||||||
visible={instanceQuery.data?.stats?.user_count !== undefined}
|
|
||||||
header={t('server.information.accounts')}
|
header={t('server.information.accounts')}
|
||||||
content={
|
content={
|
||||||
instanceQuery.data?.stats?.user_count?.toString() || undefined
|
instanceQuery.data?.stats?.user_count?.toString() || undefined
|
||||||
@ -185,7 +186,6 @@ const ComponentInstance: React.FC<Props> = ({
|
|||||||
/>
|
/>
|
||||||
<InstanceInfo
|
<InstanceInfo
|
||||||
style={styles.stat2}
|
style={styles.stat2}
|
||||||
visible={instanceQuery.data?.stats?.status_count !== undefined}
|
|
||||||
header={t('server.information.statuses')}
|
header={t('server.information.statuses')}
|
||||||
content={
|
content={
|
||||||
instanceQuery.data?.stats?.status_count?.toString() ||
|
instanceQuery.data?.stats?.status_count?.toString() ||
|
||||||
@ -195,7 +195,6 @@ const ComponentInstance: React.FC<Props> = ({
|
|||||||
/>
|
/>
|
||||||
<InstanceInfo
|
<InstanceInfo
|
||||||
style={styles.stat3}
|
style={styles.stat3}
|
||||||
visible={instanceQuery.data?.stats?.domain_count !== undefined}
|
|
||||||
header={t('server.information.domains')}
|
header={t('server.information.domains')}
|
||||||
content={
|
content={
|
||||||
instanceQuery.data?.stats?.domain_count?.toString() ||
|
instanceQuery.data?.stats?.domain_count?.toString() ||
|
||||||
@ -231,7 +230,7 @@ const ComponentInstance: React.FC<Props> = ({
|
|||||||
</View>
|
</View>
|
||||||
|
|
||||||
{requestAuth}
|
{requestAuth}
|
||||||
</>
|
</KeyboardAvoidingView>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
import analytics from '@components/analytics'
|
|
||||||
import Icon from '@components/Icon'
|
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
|
||||||
import * as WebBrowser from 'expo-web-browser'
|
|
||||||
import React from 'react'
|
|
||||||
import { useTranslation } from 'react-i18next'
|
|
||||||
import { Pressable, StyleSheet, Text } from 'react-native'
|
|
||||||
|
|
||||||
export interface Props {
|
|
||||||
agreed: boolean
|
|
||||||
setAgreed: React.Dispatch<React.SetStateAction<boolean>>
|
|
||||||
}
|
|
||||||
|
|
||||||
const EULA = React.memo(
|
|
||||||
({ agreed, setAgreed }: Props) => {
|
|
||||||
const { t } = useTranslation('componentInstance')
|
|
||||||
const { theme } = useTheme()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Pressable style={styles.base} onPress={() => setAgreed(!agreed)}>
|
|
||||||
<Icon
|
|
||||||
style={styles.icon}
|
|
||||||
name={agreed ? 'CheckCircle' : 'Circle'}
|
|
||||||
size={StyleConstants.Font.Size.M}
|
|
||||||
color={theme.primary}
|
|
||||||
/>
|
|
||||||
<Text style={[styles.text, { color: theme.primary }]}>
|
|
||||||
{t('server.EULA.base')}
|
|
||||||
<Text
|
|
||||||
style={{ color: theme.blue }}
|
|
||||||
children={t('server.EULA.EULA')}
|
|
||||||
onPress={() => {
|
|
||||||
analytics('view_EULA')
|
|
||||||
WebBrowser.openBrowserAsync(
|
|
||||||
'https://tooot.app/end-user-license-agreement'
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Text>
|
|
||||||
</Pressable>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
(prev, next) => prev.agreed === next.agreed
|
|
||||||
)
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
base: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
marginTop: StyleConstants.Spacing.M,
|
|
||||||
paddingHorizontal: StyleConstants.Spacing.Global.PagePadding,
|
|
||||||
alignItems: 'center'
|
|
||||||
},
|
|
||||||
icon: {
|
|
||||||
marginRight: StyleConstants.Spacing.XS
|
|
||||||
},
|
|
||||||
text: {
|
|
||||||
...StyleConstants.FontStyle.S
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
export default EULA
|
|
@ -8,15 +8,13 @@ import { PlaceholderLine } from 'rn-placeholder'
|
|||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
style?: ViewStyle
|
style?: ViewStyle
|
||||||
visible: boolean
|
|
||||||
header: string
|
header: string
|
||||||
content?: string
|
content?: string
|
||||||
potentialWidth?: number
|
potentialWidth?: number
|
||||||
potentialLines?: number
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const InstanceInfo = React.memo(
|
const InstanceInfo = React.memo(
|
||||||
({ style, header, content, potentialWidth, potentialLines = 1 }: Props) => {
|
({ style, header, content, potentialWidth }: Props) => {
|
||||||
const { t } = useTranslation('componentInstance')
|
const { t } = useTranslation('componentInstance')
|
||||||
const { theme } = useTheme()
|
const { theme } = useTheme()
|
||||||
|
|
||||||
@ -31,24 +29,22 @@ const InstanceInfo = React.memo(
|
|||||||
expandHint={t('server.information.description.expandHint')}
|
expandHint={t('server.information.description.expandHint')}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
Array.from(Array(potentialLines)).map((_, i) => (
|
<PlaceholderLine
|
||||||
<PlaceholderLine
|
width={
|
||||||
key={i}
|
potentialWidth
|
||||||
width={
|
? potentialWidth * StyleConstants.Font.Size.M
|
||||||
potentialWidth
|
: undefined
|
||||||
? potentialWidth * StyleConstants.Font.Size.M
|
}
|
||||||
: undefined
|
height={StyleConstants.Font.LineHeight.M}
|
||||||
}
|
color={theme.shimmerDefault}
|
||||||
height={StyleConstants.Font.LineHeight.M}
|
noMargin
|
||||||
color={theme.shimmerDefault}
|
style={{ borderRadius: 0 }}
|
||||||
noMargin
|
/>
|
||||||
style={{ borderRadius: 0 }}
|
|
||||||
/>
|
|
||||||
))
|
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
|
(prev, next) => prev.content === next.content
|
||||||
)
|
)
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
@ -41,7 +41,7 @@ const TimelineDefault: React.FC<Props> = ({
|
|||||||
pinned
|
pinned
|
||||||
}) => {
|
}) => {
|
||||||
const { theme } = useTheme()
|
const { theme } = useTheme()
|
||||||
const instanceAccount = useSelector(getInstanceAccount, (prev, next) => true)
|
const instanceAccount = useSelector(getInstanceAccount, () => true)
|
||||||
const navigation = useNavigation<
|
const navigation = useNavigation<
|
||||||
StackNavigationProp<Nav.TabLocalStackParamList>
|
StackNavigationProp<Nav.TabLocalStackParamList>
|
||||||
>()
|
>()
|
||||||
|
@ -103,7 +103,7 @@ const TimelineRefresh: React.FC<Props> = ({
|
|||||||
queryClient.setQueryData<InfiniteData<TimelineData> | undefined>(
|
queryClient.setQueryData<InfiniteData<TimelineData> | undefined>(
|
||||||
queryKey,
|
queryKey,
|
||||||
data => {
|
data => {
|
||||||
if (data?.pages[0].body.length === 0) {
|
if (data?.pages[0] && data.pages[0].body.length === 0) {
|
||||||
return {
|
return {
|
||||||
pages: data.pages.slice(1),
|
pages: data.pages.slice(1),
|
||||||
pageParams: data.pageParams.slice(1)
|
pageParams: data.pageParams.slice(1)
|
||||||
|
@ -22,277 +22,274 @@ export interface Props {
|
|||||||
reblog: boolean
|
reblog: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const TimelineActions: React.FC<Props> = ({
|
const TimelineActions = React.memo(
|
||||||
queryKey,
|
({ queryKey, rootQueryKey, status, accts, reblog }: Props) => {
|
||||||
rootQueryKey,
|
const navigation = useNavigation()
|
||||||
status,
|
const { t } = useTranslation('componentTimeline')
|
||||||
accts,
|
const { mode, theme } = useTheme()
|
||||||
reblog
|
const iconColor = theme.secondary
|
||||||
}) => {
|
const iconColorAction = (state: boolean) =>
|
||||||
const navigation = useNavigation()
|
state ? theme.primary : theme.secondary
|
||||||
const { t } = useTranslation('componentTimeline')
|
|
||||||
const { mode, theme } = useTheme()
|
|
||||||
const iconColor = theme.secondary
|
|
||||||
const iconColorAction = (state: boolean) =>
|
|
||||||
state ? theme.primary : theme.secondary
|
|
||||||
|
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const mutation = useTimelineMutation({
|
const mutation = useTimelineMutation({
|
||||||
queryClient,
|
queryClient,
|
||||||
onMutate: true,
|
onMutate: true,
|
||||||
onSuccess: (_, params) => {
|
onSuccess: (_, params) => {
|
||||||
const theParams = params as MutationVarsTimelineUpdateStatusProperty
|
const theParams = params as MutationVarsTimelineUpdateStatusProperty
|
||||||
if (
|
if (
|
||||||
// Un-bookmark from bookmarks page
|
// Un-bookmark from bookmarks page
|
||||||
(queryKey[1].page === 'Bookmarks' &&
|
(queryKey[1].page === 'Bookmarks' &&
|
||||||
theParams.payload.property === 'bookmarked') ||
|
theParams.payload.property === 'bookmarked') ||
|
||||||
// Un-favourite from favourites page
|
// Un-favourite from favourites page
|
||||||
(queryKey[1].page === 'Favourites' &&
|
(queryKey[1].page === 'Favourites' &&
|
||||||
theParams.payload.property === 'favourited') ||
|
theParams.payload.property === 'favourited') ||
|
||||||
// Un-reblog from following page
|
// Un-reblog from following page
|
||||||
(queryKey[1].page === 'Following' &&
|
(queryKey[1].page === 'Following' &&
|
||||||
|
theParams.payload.property === 'reblogged' &&
|
||||||
|
theParams.payload.currentValue === true)
|
||||||
|
) {
|
||||||
|
queryClient.invalidateQueries(queryKey)
|
||||||
|
} else if (
|
||||||
theParams.payload.property === 'reblogged' &&
|
theParams.payload.property === 'reblogged' &&
|
||||||
theParams.payload.currentValue === true)
|
queryKey[1].page !== 'Following'
|
||||||
) {
|
) {
|
||||||
|
// When reblogged, update cache of following page
|
||||||
|
const tempQueryKey: QueryKeyTimeline = [
|
||||||
|
'Timeline',
|
||||||
|
{ page: 'Following' }
|
||||||
|
]
|
||||||
|
queryClient.invalidateQueries(tempQueryKey)
|
||||||
|
} else if (theParams.payload.property === 'favourited') {
|
||||||
|
// When favourited, update favourited page
|
||||||
|
const tempQueryKey: QueryKeyTimeline = [
|
||||||
|
'Timeline',
|
||||||
|
{ page: 'Favourites' }
|
||||||
|
]
|
||||||
|
queryClient.invalidateQueries(tempQueryKey)
|
||||||
|
} else if (theParams.payload.property === 'bookmarked') {
|
||||||
|
// When bookmarked, update bookmark page
|
||||||
|
const tempQueryKey: QueryKeyTimeline = [
|
||||||
|
'Timeline',
|
||||||
|
{ page: 'Bookmarks' }
|
||||||
|
]
|
||||||
|
queryClient.invalidateQueries(tempQueryKey)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onError: (err: any, params, oldData) => {
|
||||||
|
const correctParam = params as MutationVarsTimelineUpdateStatusProperty
|
||||||
|
displayMessage({
|
||||||
|
mode,
|
||||||
|
type: 'error',
|
||||||
|
message: t('common:toastMessage.error.message', {
|
||||||
|
function: t(
|
||||||
|
`shared.actions.${correctParam.payload.property}.function`
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
...(err.status &&
|
||||||
|
typeof err.status === 'number' &&
|
||||||
|
err.data &&
|
||||||
|
err.data.error &&
|
||||||
|
typeof err.data.error === 'string' && {
|
||||||
|
description: err.data.error
|
||||||
|
})
|
||||||
|
})
|
||||||
queryClient.invalidateQueries(queryKey)
|
queryClient.invalidateQueries(queryKey)
|
||||||
} else if (
|
|
||||||
theParams.payload.property === 'reblogged' &&
|
|
||||||
queryKey[1].page !== 'Following'
|
|
||||||
) {
|
|
||||||
// When reblogged, update cache of following page
|
|
||||||
const tempQueryKey: QueryKeyTimeline = [
|
|
||||||
'Timeline',
|
|
||||||
{ page: 'Following' }
|
|
||||||
]
|
|
||||||
queryClient.invalidateQueries(tempQueryKey)
|
|
||||||
} else if (theParams.payload.property === 'favourited') {
|
|
||||||
// When favourited, update favourited page
|
|
||||||
const tempQueryKey: QueryKeyTimeline = [
|
|
||||||
'Timeline',
|
|
||||||
{ page: 'Favourites' }
|
|
||||||
]
|
|
||||||
queryClient.invalidateQueries(tempQueryKey)
|
|
||||||
} else if (theParams.payload.property === 'bookmarked') {
|
|
||||||
// When bookmarked, update bookmark page
|
|
||||||
const tempQueryKey: QueryKeyTimeline = [
|
|
||||||
'Timeline',
|
|
||||||
{ page: 'Bookmarks' }
|
|
||||||
]
|
|
||||||
queryClient.invalidateQueries(tempQueryKey)
|
|
||||||
}
|
}
|
||||||
},
|
})
|
||||||
onError: (err: any, params, oldData) => {
|
|
||||||
const correctParam = params as MutationVarsTimelineUpdateStatusProperty
|
const onPressReply = useCallback(() => {
|
||||||
displayMessage({
|
analytics('timeline_shared_actions_reply_press', {
|
||||||
mode,
|
page: queryKey[1].page,
|
||||||
type: 'error',
|
count: status.replies_count
|
||||||
message: t('common:toastMessage.error.message', {
|
|
||||||
function: t(
|
|
||||||
`shared.actions.${correctParam.payload.property}.function`
|
|
||||||
)
|
|
||||||
}),
|
|
||||||
...(err.status &&
|
|
||||||
typeof err.status === 'number' &&
|
|
||||||
err.data &&
|
|
||||||
err.data.error &&
|
|
||||||
typeof err.data.error === 'string' && {
|
|
||||||
description: err.data.error
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
queryClient.invalidateQueries(queryKey)
|
navigation.navigate('Screen-Compose', {
|
||||||
}
|
type: 'reply',
|
||||||
})
|
incomingStatus: status,
|
||||||
|
accts,
|
||||||
|
queryKey
|
||||||
|
})
|
||||||
|
}, [status.replies_count])
|
||||||
|
const onPressReblog = useCallback(() => {
|
||||||
|
analytics('timeline_shared_actions_reblog_press', {
|
||||||
|
page: queryKey[1].page,
|
||||||
|
count: status.reblogs_count,
|
||||||
|
current: status.reblogged
|
||||||
|
})
|
||||||
|
mutation.mutate({
|
||||||
|
type: 'updateStatusProperty',
|
||||||
|
queryKey,
|
||||||
|
rootQueryKey,
|
||||||
|
id: status.id,
|
||||||
|
reblog,
|
||||||
|
payload: {
|
||||||
|
property: 'reblogged',
|
||||||
|
currentValue: status.reblogged,
|
||||||
|
propertyCount: 'reblogs_count',
|
||||||
|
countValue: status.reblogs_count
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, [status.reblogged, status.reblogs_count])
|
||||||
|
const onPressFavourite = useCallback(() => {
|
||||||
|
analytics('timeline_shared_actions_favourite_press', {
|
||||||
|
page: queryKey[1].page,
|
||||||
|
count: status.favourites_count,
|
||||||
|
current: status.favourited
|
||||||
|
})
|
||||||
|
mutation.mutate({
|
||||||
|
type: 'updateStatusProperty',
|
||||||
|
queryKey,
|
||||||
|
rootQueryKey,
|
||||||
|
id: status.id,
|
||||||
|
reblog,
|
||||||
|
payload: {
|
||||||
|
property: 'favourited',
|
||||||
|
currentValue: status.favourited,
|
||||||
|
propertyCount: 'favourites_count',
|
||||||
|
countValue: status.favourites_count
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, [status.favourited, status.favourites_count])
|
||||||
|
const onPressBookmark = useCallback(() => {
|
||||||
|
analytics('timeline_shared_actions_bookmark_press', {
|
||||||
|
page: queryKey[1].page,
|
||||||
|
current: status.bookmarked
|
||||||
|
})
|
||||||
|
mutation.mutate({
|
||||||
|
type: 'updateStatusProperty',
|
||||||
|
queryKey,
|
||||||
|
rootQueryKey,
|
||||||
|
id: status.id,
|
||||||
|
reblog,
|
||||||
|
payload: {
|
||||||
|
property: 'bookmarked',
|
||||||
|
currentValue: status.bookmarked,
|
||||||
|
propertyCount: undefined,
|
||||||
|
countValue: undefined
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, [status.bookmarked])
|
||||||
|
|
||||||
const onPressReply = useCallback(() => {
|
const childrenReply = useMemo(
|
||||||
analytics('timeline_shared_actions_reply_press', {
|
() => (
|
||||||
page: queryKey[1].page,
|
<>
|
||||||
count: status.replies_count
|
<Icon
|
||||||
})
|
name='MessageCircle'
|
||||||
navigation.navigate('Screen-Compose', {
|
color={iconColor}
|
||||||
type: 'reply',
|
size={StyleConstants.Font.Size.L}
|
||||||
incomingStatus: status,
|
/>
|
||||||
accts,
|
{status.replies_count > 0 && (
|
||||||
queryKey
|
<Text
|
||||||
})
|
style={{
|
||||||
}, [status.replies_count])
|
color: theme.secondary,
|
||||||
const onPressReblog = useCallback(() => {
|
fontSize: StyleConstants.Font.Size.M,
|
||||||
analytics('timeline_shared_actions_reblog_press', {
|
marginLeft: StyleConstants.Spacing.XS
|
||||||
page: queryKey[1].page,
|
}}
|
||||||
count: status.reblogs_count,
|
>
|
||||||
current: status.reblogged
|
{status.replies_count}
|
||||||
})
|
</Text>
|
||||||
mutation.mutate({
|
)}
|
||||||
type: 'updateStatusProperty',
|
</>
|
||||||
queryKey,
|
),
|
||||||
rootQueryKey,
|
[status.replies_count]
|
||||||
id: status.id,
|
)
|
||||||
reblog,
|
const childrenReblog = useMemo(
|
||||||
payload: {
|
() => (
|
||||||
property: 'reblogged',
|
<>
|
||||||
currentValue: status.reblogged,
|
<Icon
|
||||||
propertyCount: 'reblogs_count',
|
name='Repeat'
|
||||||
countValue: status.reblogs_count
|
color={
|
||||||
}
|
status.visibility === 'private' || status.visibility === 'direct'
|
||||||
})
|
? theme.disabled
|
||||||
}, [status.reblogged, status.reblogs_count])
|
: iconColorAction(status.reblogged)
|
||||||
const onPressFavourite = useCallback(() => {
|
}
|
||||||
analytics('timeline_shared_actions_favourite_press', {
|
size={StyleConstants.Font.Size.L}
|
||||||
page: queryKey[1].page,
|
/>
|
||||||
count: status.favourites_count,
|
{status.reblogs_count > 0 && (
|
||||||
current: status.favourited
|
<Text
|
||||||
})
|
style={{
|
||||||
mutation.mutate({
|
color: iconColorAction(status.reblogged),
|
||||||
type: 'updateStatusProperty',
|
fontSize: StyleConstants.Font.Size.M,
|
||||||
queryKey,
|
marginLeft: StyleConstants.Spacing.XS
|
||||||
rootQueryKey,
|
}}
|
||||||
id: status.id,
|
>
|
||||||
reblog,
|
{status.reblogs_count}
|
||||||
payload: {
|
</Text>
|
||||||
property: 'favourited',
|
)}
|
||||||
currentValue: status.favourited,
|
</>
|
||||||
propertyCount: 'favourites_count',
|
),
|
||||||
countValue: status.favourites_count
|
[status.reblogged, status.reblogs_count]
|
||||||
}
|
)
|
||||||
})
|
const childrenFavourite = useMemo(
|
||||||
}, [status.favourited, status.favourites_count])
|
() => (
|
||||||
const onPressBookmark = useCallback(() => {
|
<>
|
||||||
analytics('timeline_shared_actions_bookmark_press', {
|
<Icon
|
||||||
page: queryKey[1].page,
|
name='Heart'
|
||||||
current: status.bookmarked
|
color={iconColorAction(status.favourited)}
|
||||||
})
|
size={StyleConstants.Font.Size.L}
|
||||||
mutation.mutate({
|
/>
|
||||||
type: 'updateStatusProperty',
|
{status.favourites_count > 0 && (
|
||||||
queryKey,
|
<Text
|
||||||
rootQueryKey,
|
style={{
|
||||||
id: status.id,
|
color: iconColorAction(status.favourited),
|
||||||
reblog,
|
fontSize: StyleConstants.Font.Size.M,
|
||||||
payload: {
|
marginLeft: StyleConstants.Spacing.XS,
|
||||||
property: 'bookmarked',
|
marginTop: 0
|
||||||
currentValue: status.bookmarked,
|
}}
|
||||||
propertyCount: undefined,
|
>
|
||||||
countValue: undefined
|
{status.favourites_count}
|
||||||
}
|
</Text>
|
||||||
})
|
)}
|
||||||
}, [status.bookmarked])
|
</>
|
||||||
|
),
|
||||||
const childrenReply = useMemo(
|
[status.favourited, status.favourites_count]
|
||||||
() => (
|
)
|
||||||
<>
|
const childrenBookmark = useMemo(
|
||||||
|
() => (
|
||||||
<Icon
|
<Icon
|
||||||
name='MessageCircle'
|
name='Bookmark'
|
||||||
color={iconColor}
|
color={iconColorAction(status.bookmarked)}
|
||||||
size={StyleConstants.Font.Size.L}
|
size={StyleConstants.Font.Size.L}
|
||||||
/>
|
/>
|
||||||
{status.replies_count > 0 && (
|
),
|
||||||
<Text
|
[status.bookmarked]
|
||||||
style={{
|
)
|
||||||
color: theme.secondary,
|
|
||||||
fontSize: StyleConstants.Font.Size.M,
|
return (
|
||||||
marginLeft: StyleConstants.Spacing.XS
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{status.replies_count}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
[status.replies_count]
|
|
||||||
)
|
|
||||||
const childrenReblog = useMemo(
|
|
||||||
() => (
|
|
||||||
<>
|
<>
|
||||||
<Icon
|
<View style={styles.actions}>
|
||||||
name='Repeat'
|
<Pressable
|
||||||
color={
|
style={styles.action}
|
||||||
status.visibility === 'private' || status.visibility === 'direct'
|
onPress={onPressReply}
|
||||||
? theme.disabled
|
children={childrenReply}
|
||||||
: iconColorAction(status.reblogged)
|
/>
|
||||||
}
|
|
||||||
size={StyleConstants.Font.Size.L}
|
<Pressable
|
||||||
/>
|
style={styles.action}
|
||||||
{status.reblogs_count > 0 && (
|
onPress={onPressReblog}
|
||||||
<Text
|
children={childrenReblog}
|
||||||
style={{
|
disabled={
|
||||||
color: iconColorAction(status.reblogged),
|
status.visibility === 'private' || status.visibility === 'direct'
|
||||||
fontSize: StyleConstants.Font.Size.M,
|
}
|
||||||
marginLeft: StyleConstants.Spacing.XS
|
/>
|
||||||
}}
|
|
||||||
>
|
<Pressable
|
||||||
{status.reblogs_count}
|
style={styles.action}
|
||||||
</Text>
|
onPress={onPressFavourite}
|
||||||
)}
|
children={childrenFavourite}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Pressable
|
||||||
|
style={styles.action}
|
||||||
|
onPress={onPressBookmark}
|
||||||
|
children={childrenBookmark}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
</>
|
</>
|
||||||
),
|
)
|
||||||
[status.reblogged, status.reblogs_count]
|
},
|
||||||
)
|
() => true
|
||||||
const childrenFavourite = useMemo(
|
)
|
||||||
() => (
|
|
||||||
<>
|
|
||||||
<Icon
|
|
||||||
name='Heart'
|
|
||||||
color={iconColorAction(status.favourited)}
|
|
||||||
size={StyleConstants.Font.Size.L}
|
|
||||||
/>
|
|
||||||
{status.favourites_count > 0 && (
|
|
||||||
<Text
|
|
||||||
style={{
|
|
||||||
color: iconColorAction(status.favourited),
|
|
||||||
fontSize: StyleConstants.Font.Size.M,
|
|
||||||
marginLeft: StyleConstants.Spacing.XS,
|
|
||||||
marginTop: 0
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{status.favourites_count}
|
|
||||||
</Text>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
[status.favourited, status.favourites_count]
|
|
||||||
)
|
|
||||||
const childrenBookmark = useMemo(
|
|
||||||
() => (
|
|
||||||
<Icon
|
|
||||||
name='Bookmark'
|
|
||||||
color={iconColorAction(status.bookmarked)}
|
|
||||||
size={StyleConstants.Font.Size.L}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
[status.bookmarked]
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<View style={styles.actions}>
|
|
||||||
<Pressable
|
|
||||||
style={styles.action}
|
|
||||||
onPress={onPressReply}
|
|
||||||
children={childrenReply}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Pressable
|
|
||||||
style={styles.action}
|
|
||||||
onPress={onPressReblog}
|
|
||||||
children={childrenReblog}
|
|
||||||
disabled={
|
|
||||||
status.visibility === 'private' || status.visibility === 'direct'
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Pressable
|
|
||||||
style={styles.action}
|
|
||||||
onPress={onPressFavourite}
|
|
||||||
children={childrenFavourite}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Pressable
|
|
||||||
style={styles.action}
|
|
||||||
onPress={onPressBookmark}
|
|
||||||
children={childrenBookmark}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
actions: {
|
actions: {
|
||||||
|
@ -15,28 +15,32 @@ import { useQueryClient } from 'react-query'
|
|||||||
import HeaderSharedCreated from './HeaderShared/Created'
|
import HeaderSharedCreated from './HeaderShared/Created'
|
||||||
import HeaderSharedMuted from './HeaderShared/Muted'
|
import HeaderSharedMuted from './HeaderShared/Muted'
|
||||||
|
|
||||||
const Names: React.FC<{ accounts: Mastodon.Account[] }> = ({ accounts }) => {
|
const Names = React.memo(
|
||||||
const { t } = useTranslation('componentTimeline')
|
({ accounts }: { accounts: Mastodon.Account[] }) => {
|
||||||
const { theme } = useTheme()
|
const { t } = useTranslation('componentTimeline')
|
||||||
|
const { theme } = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Text numberOfLines={1}>
|
<Text
|
||||||
<Text style={[styles.namesLeading, { color: theme.secondary }]}>
|
numberOfLines={1}
|
||||||
{t('shared.header.conversation.withAccounts')}
|
style={[styles.namesLeading, { color: theme.secondary }]}
|
||||||
|
>
|
||||||
|
<Text>{t('shared.header.conversation.withAccounts')}</Text>
|
||||||
|
{accounts.map((account, index) => (
|
||||||
|
<Text key={account.id} numberOfLines={1}>
|
||||||
|
{index !== 0 ? t('common:separator') : undefined}
|
||||||
|
<ParseEmojis
|
||||||
|
content={account.display_name || account.username}
|
||||||
|
emojis={account.emojis}
|
||||||
|
fontBold
|
||||||
|
/>
|
||||||
|
</Text>
|
||||||
|
))}
|
||||||
</Text>
|
</Text>
|
||||||
{accounts.map((account, index) => (
|
)
|
||||||
<Text key={account.id} numberOfLines={1}>
|
},
|
||||||
{index !== 0 ? t('common:separator') : undefined}
|
() => true
|
||||||
<ParseEmojis
|
)
|
||||||
content={account.display_name || account.username}
|
|
||||||
emojis={account.emojis}
|
|
||||||
fontBold
|
|
||||||
/>
|
|
||||||
</Text>
|
|
||||||
))}
|
|
||||||
</Text>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
queryKey: QueryKeyTimeline
|
queryKey: QueryKeyTimeline
|
||||||
|
@ -9,29 +9,32 @@ export interface Props {
|
|||||||
withoutName?: boolean // For notification follow request etc.
|
withoutName?: boolean // For notification follow request etc.
|
||||||
}
|
}
|
||||||
|
|
||||||
const HeaderSharedAccount: React.FC<Props> = ({
|
const HeaderSharedAccount = React.memo(
|
||||||
account,
|
({ account, withoutName = false }: Props) => {
|
||||||
withoutName = false
|
const { theme } = useTheme()
|
||||||
}) => {
|
|
||||||
const { theme } = useTheme()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.base}>
|
<View style={styles.base}>
|
||||||
{withoutName ? null : (
|
{withoutName ? null : (
|
||||||
<Text style={styles.name} numberOfLines={1}>
|
<Text style={styles.name} numberOfLines={1}>
|
||||||
<ParseEmojis
|
<ParseEmojis
|
||||||
content={account.display_name || account.username}
|
content={account.display_name || account.username}
|
||||||
emojis={account.emojis}
|
emojis={account.emojis}
|
||||||
fontBold
|
fontBold
|
||||||
/>
|
/>
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
<Text
|
||||||
|
style={[styles.acct, { color: theme.secondary }]}
|
||||||
|
numberOfLines={1}
|
||||||
|
>
|
||||||
|
@{account.acct}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
</View>
|
||||||
<Text style={[styles.acct, { color: theme.secondary }]} numberOfLines={1}>
|
)
|
||||||
@{account.acct}
|
},
|
||||||
</Text>
|
() => true
|
||||||
</View>
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
base: {
|
base: {
|
||||||
|
@ -10,24 +10,29 @@ export interface Props {
|
|||||||
application?: Mastodon.Application
|
application?: Mastodon.Application
|
||||||
}
|
}
|
||||||
|
|
||||||
const HeaderSharedApplication: React.FC<Props> = ({ application }) => {
|
const HeaderSharedApplication = React.memo(
|
||||||
const { theme } = useTheme()
|
({ application }: Props) => {
|
||||||
const { t } = useTranslation('componentTimeline')
|
const { theme } = useTheme()
|
||||||
|
const { t } = useTranslation('componentTimeline')
|
||||||
|
|
||||||
return application && application.name !== 'Web' ? (
|
return application && application.name !== 'Web' ? (
|
||||||
<Text
|
<Text
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
analytics('timeline_shared_header_application_press', {
|
analytics('timeline_shared_header_application_press', {
|
||||||
application
|
application
|
||||||
})
|
})
|
||||||
application.website && (await openLink(application.website))
|
application.website && (await openLink(application.website))
|
||||||
}}
|
}}
|
||||||
style={[styles.application, { color: theme.secondary }]}
|
style={[styles.application, { color: theme.secondary }]}
|
||||||
>
|
>
|
||||||
{t('shared.header.shared.application', { application: application.name })}
|
{t('shared.header.shared.application', {
|
||||||
</Text>
|
application: application.name
|
||||||
) : null
|
})}
|
||||||
}
|
</Text>
|
||||||
|
) : null
|
||||||
|
},
|
||||||
|
() => true
|
||||||
|
)
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
application: {
|
application: {
|
||||||
|
@ -8,18 +8,21 @@ export interface Props {
|
|||||||
muted?: Mastodon.Status['muted']
|
muted?: Mastodon.Status['muted']
|
||||||
}
|
}
|
||||||
|
|
||||||
const HeaderSharedMuted: React.FC<Props> = ({ muted }) => {
|
const HeaderSharedMuted = React.memo(
|
||||||
const { theme } = useTheme()
|
({ muted }: Props) => {
|
||||||
|
const { theme } = useTheme()
|
||||||
|
|
||||||
return muted ? (
|
return muted ? (
|
||||||
<Icon
|
<Icon
|
||||||
name='VolumeX'
|
name='VolumeX'
|
||||||
size={StyleConstants.Font.Size.S}
|
size={StyleConstants.Font.Size.S}
|
||||||
color={theme.secondary}
|
color={theme.secondary}
|
||||||
style={styles.visibility}
|
style={styles.visibility}
|
||||||
/>
|
/>
|
||||||
) : null
|
) : null
|
||||||
}
|
},
|
||||||
|
() => true
|
||||||
|
)
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
visibility: {
|
visibility: {
|
||||||
|
@ -8,32 +8,35 @@ export interface Props {
|
|||||||
visibility: Mastodon.Status['visibility']
|
visibility: Mastodon.Status['visibility']
|
||||||
}
|
}
|
||||||
|
|
||||||
const HeaderSharedVisibility: React.FC<Props> = ({ visibility }) => {
|
const HeaderSharedVisibility = React.memo(
|
||||||
const { theme } = useTheme()
|
({ visibility }: Props) => {
|
||||||
|
const { theme } = useTheme()
|
||||||
|
|
||||||
switch (visibility) {
|
switch (visibility) {
|
||||||
case 'private':
|
case 'private':
|
||||||
return (
|
return (
|
||||||
<Icon
|
<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}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
case 'direct':
|
case 'direct':
|
||||||
return (
|
return (
|
||||||
<Icon
|
<Icon
|
||||||
name='Mail'
|
name='Mail'
|
||||||
size={StyleConstants.Font.Size.S}
|
size={StyleConstants.Font.Size.S}
|
||||||
color={theme.secondary}
|
color={theme.secondary}
|
||||||
style={styles.visibility}
|
style={styles.visibility}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
default:
|
default:
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
() => true
|
||||||
|
)
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
visibility: {
|
visibility: {
|
||||||
|
@ -353,7 +353,7 @@ const ScreenCompose: React.FC<ScreenComposeProp> = ({
|
|||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name='Screen-Compose-DraftsList'
|
name='Screen-Compose-DraftsList'
|
||||||
component={ComposeDraftsList}
|
component={ComposeDraftsList}
|
||||||
options={{ stackPresentation: 'modal' }}
|
options={{ stackPresentation: 'modal', headerShown: false }}
|
||||||
/>
|
/>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name='Screen-Compose-EditAttachment'
|
name='Screen-Compose-EditAttachment'
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import Timeline from '@components/Timeline'
|
import Timeline from '@components/Timeline'
|
||||||
|
import TimelineDefault from '@components/Timeline/Default'
|
||||||
import { StackScreenProps } from '@react-navigation/stack'
|
import { StackScreenProps } from '@react-navigation/stack'
|
||||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||||
import React from 'react'
|
import React, { useCallback } from 'react'
|
||||||
|
|
||||||
const ScreenMeListsList: React.FC<StackScreenProps<
|
const ScreenMeListsList: React.FC<StackScreenProps<
|
||||||
Nav.TabMeStackParamList,
|
Nav.TabMeStackParamList,
|
||||||
@ -12,8 +13,12 @@ const ScreenMeListsList: React.FC<StackScreenProps<
|
|||||||
}
|
}
|
||||||
}) => {
|
}) => {
|
||||||
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'List', list }]
|
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'List', list }]
|
||||||
|
const renderItem = useCallback(
|
||||||
|
({ item }) => <TimelineDefault item={item} queryKey={queryKey} />,
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
|
||||||
return <Timeline queryKey={queryKey} />
|
return <Timeline queryKey={queryKey} customProps={{ renderItem }} />
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ScreenMeListsList
|
export default ScreenMeListsList
|
||||||
|
@ -2,7 +2,7 @@ import { HeaderCenter, HeaderLeft } from '@components/Header'
|
|||||||
import { StackScreenProps } from '@react-navigation/stack'
|
import { StackScreenProps } from '@react-navigation/stack'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { Platform } from 'react-native'
|
import { KeyboardAvoidingView, Platform } from 'react-native'
|
||||||
import { createNativeStackNavigator } from 'react-native-screens/native-stack'
|
import { createNativeStackNavigator } from 'react-native-screens/native-stack'
|
||||||
import ScreenMeSwitchRoot from './Switch/Root'
|
import ScreenMeSwitchRoot from './Switch/Root'
|
||||||
|
|
||||||
@ -14,26 +14,33 @@ const ScreenMeSwitch: React.FC<StackScreenProps<
|
|||||||
>> = ({ navigation }) => {
|
>> = ({ navigation }) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
return (
|
return (
|
||||||
<Stack.Navigator
|
<KeyboardAvoidingView
|
||||||
screenOptions={{ headerHideShadow: true, headerTopInsetEnabled: false }}
|
style={{ flex: 1 }}
|
||||||
|
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
||||||
>
|
>
|
||||||
<Stack.Screen
|
<Stack.Navigator
|
||||||
name='Screen-Me-Switch-Root'
|
screenOptions={{ headerHideShadow: true, headerTopInsetEnabled: false }}
|
||||||
component={ScreenMeSwitchRoot}
|
>
|
||||||
options={{
|
<Stack.Screen
|
||||||
headerTitle: t('meSwitch:heading'),
|
name='Screen-Me-Switch-Root'
|
||||||
...(Platform.OS === 'android' && {
|
component={ScreenMeSwitchRoot}
|
||||||
headerCenter: () => <HeaderCenter content={t('meSwitch:heading')} />
|
options={{
|
||||||
}),
|
headerTitle: t('meSwitch:heading'),
|
||||||
headerLeft: () => (
|
...(Platform.OS === 'android' && {
|
||||||
<HeaderLeft
|
headerCenter: () => (
|
||||||
content='ChevronDown'
|
<HeaderCenter content={t('meSwitch:heading')} />
|
||||||
onPress={() => navigation.goBack()}
|
)
|
||||||
/>
|
}),
|
||||||
)
|
headerLeft: () => (
|
||||||
}}
|
<HeaderLeft
|
||||||
/>
|
content='ChevronDown'
|
||||||
</Stack.Navigator>
|
onPress={() => navigation.goBack()}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Stack.Navigator>
|
||||||
|
</KeyboardAvoidingView>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,56 +60,52 @@ const ScreenMeSwitchRoot: React.FC = () => {
|
|||||||
const instanceActive = useSelector(getInstanceActive)
|
const instanceActive = useSelector(getInstanceActive)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<KeyboardAvoidingView
|
<ScrollView style={styles.base} keyboardShouldPersistTaps='handled'>
|
||||||
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
<View style={[styles.firstSection, { borderBottomColor: theme.border }]}>
|
||||||
style={{ flex: 1 }}
|
<Text style={[styles.header, { color: theme.primary }]}>
|
||||||
>
|
{t('content.existing')}
|
||||||
<ScrollView keyboardShouldPersistTaps='handled'>
|
</Text>
|
||||||
<View
|
<View style={styles.accountButtons}>
|
||||||
style={[styles.firstSection, { borderBottomColor: theme.border }]}
|
{instances.length
|
||||||
>
|
? instances
|
||||||
<Text style={[styles.header, { color: theme.primary }]}>
|
.slice()
|
||||||
{t('content.existing')}
|
.sort((a, b) =>
|
||||||
</Text>
|
`${a.uri}${a.account.acct}`.localeCompare(
|
||||||
<View style={styles.accountButtons}>
|
`${b.uri}${b.account.acct}`
|
||||||
{instances.length
|
|
||||||
? instances
|
|
||||||
.slice()
|
|
||||||
.sort((a, b) =>
|
|
||||||
`${a.uri}${a.account.acct}`.localeCompare(
|
|
||||||
`${b.uri}${b.account.acct}`
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
.map((instance, index) => {
|
)
|
||||||
const localAccount = instances[instanceActive!]
|
.map((instance, index) => {
|
||||||
return (
|
const localAccount = instances[instanceActive!]
|
||||||
<AccountButton
|
return (
|
||||||
key={index}
|
<AccountButton
|
||||||
instance={instance}
|
key={index}
|
||||||
disabled={
|
instance={instance}
|
||||||
instance.url === localAccount.url &&
|
disabled={
|
||||||
instance.token === localAccount.token &&
|
instance.url === localAccount.url &&
|
||||||
instance.account.id === localAccount.account.id
|
instance.token === localAccount.token &&
|
||||||
}
|
instance.account.id === localAccount.account.id
|
||||||
/>
|
}
|
||||||
)
|
/>
|
||||||
})
|
)
|
||||||
: null}
|
})
|
||||||
</View>
|
: null}
|
||||||
</View>
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
<View style={styles.secondSection}>
|
<View style={styles.secondSection}>
|
||||||
<Text style={[styles.header, { color: theme.primary }]}>
|
<Text style={[styles.header, { color: theme.primary }]}>
|
||||||
{t('content.new')}
|
{t('content.new')}
|
||||||
</Text>
|
</Text>
|
||||||
<ComponentInstance disableHeaderImage goBack />
|
<ComponentInstance disableHeaderImage goBack />
|
||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</KeyboardAvoidingView>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
base: {
|
||||||
|
marginBottom: StyleConstants.Spacing.L
|
||||||
|
},
|
||||||
header: {
|
header: {
|
||||||
...StyleConstants.FontStyle.M,
|
...StyleConstants.FontStyle.M,
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user