This commit is contained in:
xmflsct 2022-12-12 20:43:45 +01:00
parent dee4e2810a
commit 6936e8009a
52 changed files with 268 additions and 233 deletions

View File

@ -1,3 +0,0 @@
{
"javascript.inlayHints.functionLikeReturnTypes.enabled": false
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

BIN
demo/screenshots/Tab-Me.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 609 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 402 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 KiB

View File

@ -1,6 +1,7 @@
const demoStatuses = [ const demoStatus: Mastodon.Status[] = [
{ {
id: '1', id: '1',
uri: 'https://example.com',
created_at: new Date().toISOString(), created_at: new Date().toISOString(),
sensitive: false, sensitive: false,
visibility: 'public', visibility: 'public',
@ -13,7 +14,6 @@ const demoStatuses = [
bookmarked: false, bookmarked: false,
content: content:
'<p>Would you like to try out this simple, beautiful and open-source mobile app for Mastodon? 😊</p>', '<p>Would you like to try out this simple, beautiful and open-source mobile app for Mastodon? 😊</p>',
reblog: null,
application: { application: {
name: 'tooot', name: 'tooot',
website: 'https://tooot.app' website: 'https://tooot.app'
@ -23,19 +23,31 @@ const demoStatuses = [
username: 'tooot📱', username: 'tooot📱',
acct: 'tooot@xmflsct.com', acct: 'tooot@xmflsct.com',
display_name: 'tooot📱', display_name: 'tooot📱',
avatar_static: avatar: 'https://avatars.githubusercontent.com/u/77554750?s=200&v=4',
'https://avatars.githubusercontent.com/u/77554750?s=200&v=4' avatar_static: 'https://avatars.githubusercontent.com/u/77554750?s=200&v=4',
url: '',
header: '',
header_static: '',
locked: false,
discoverable: false,
created_at: new Date().toISOString(),
last_status_at: new Date().toISOString(),
statuses_count: 1,
followers_count: 1,
following_count: 1,
fields: [],
bot: false
}, },
media_attachments: [], media_attachments: [],
poll: { poll: {
id: '1', id: '1',
expires_at: new Date().setDate(new Date().getDate() + 5), expires_at: new Date().setDate(new Date().getDate() + 5).toString(),
expired: false, expired: false,
multiple: false, multiple: false,
votes_count: 10, votes_count: 10,
voters_count: null, voters_count: 2,
voted: false, voted: false,
own_votes: null, own_votes: undefined,
options: [ options: [
{ {
title: 'I would love to!', title: 'I would love to!',
@ -48,11 +60,15 @@ const demoStatuses = [
], ],
emojis: [] emojis: []
}, },
mentions: [] mentions: [],
tags: [],
emojis: [],
pinned: false
}, },
{ {
id: '2', id: '2',
created_at: new Date().setMinutes(new Date().getMinutes() - 2), uri: 'https://example.com',
created_at: new Date().setMinutes(new Date().getMinutes() - 2).toString(),
sensitive: false, sensitive: false,
spoiler_text: '', spoiler_text: '',
visibility: 'public', visibility: 'public',
@ -65,18 +81,26 @@ const demoStatuses = [
bookmarked: false, bookmarked: false,
content: content:
'<p>Mastodon is a free and open-source self-hosted social networking service. It allows anyone to host their own server node in the network, and its various separately operated user bases are federated across many different servers. These nodes are referred to as "instances" by Mastodon users.</p>', '<p>Mastodon is a free and open-source self-hosted social networking service. It allows anyone to host their own server node in the network, and its various separately operated user bases are federated across many different servers. These nodes are referred to as "instances" by Mastodon users.</p>',
reblog: null, application: { name: 'Web' },
application: {
name: 'Web',
website: null
},
account: { account: {
id: '1000', id: '1000',
username: 'Mastodon', username: 'Mastodon',
acct: 'mastodon', acct: 'mastodon',
display_name: 'Mastodon', display_name: 'Mastodon',
avatar_static: avatar: 'https://mastodon.social/apple-touch-icon.png',
'https://mastodon.social/apple-touch-icon.png' avatar_static: 'https://mastodon.social/apple-touch-icon.png',
url: '',
header: '',
header_static: '',
locked: false,
discoverable: false,
created_at: new Date().toISOString(),
last_status_at: new Date().toISOString(),
statuses_count: 1,
followers_count: 1,
following_count: 1,
fields: [],
bot: false
}, },
media_attachments: [], media_attachments: [],
card: { card: {
@ -85,18 +109,31 @@ const demoStatuses = [
description: description:
'Mastodon is an open source decentralized social network - by the people for the people. Join the federation and take back control of your social media!', 'Mastodon is an open source decentralized social network - by the people for the people. Join the federation and take back control of your social media!',
type: 'link', type: 'link',
image: image: 'https://mastodon.social/apple-touch-icon.png',
'https://mastodon.social/apple-touch-icon.png' author_name: '',
author_url: '',
provider_name: '',
provider_url: '',
html: '<p></p>',
width: 100,
height: 100,
embed_url: 'https://example.com',
blurhash: ''
}, },
mentions: [] mentions: [],
tags: [],
emojis: [],
pinned: false
}, },
{ {
id: '3', id: '3',
created_at: '2021-01-24T09:50:00.901Z', uri: '',
created_at: new Date().setHours(new Date().getHours() - 1).toString(),
sensitive: false,
spoiler_text: '', spoiler_text: '',
visibility: 'public', visibility: 'public',
replies_count: 2, replies_count: 2,
reblogs_count: null, reblogs_count: 1,
favourites_count: 3, favourites_count: 3,
favourited: false, favourited: false,
reblogged: false, reblogged: false,
@ -104,24 +141,38 @@ const demoStatuses = [
bookmarked: true, bookmarked: true,
content: content:
'<p>These servers are connected as a federated social network, allowing users from different servers to interact with each other seamlessly. Once a Mastodon server knows another Mastodon server, it "federates" with the other Mastodon server. Mastodon is a part of the wider Fediverse, allowing its users to also interact with users on different open platforms that support the same protocol, such as PeerTube and Friendica.</p>', '<p>These servers are connected as a federated social network, allowing users from different servers to interact with each other seamlessly. Once a Mastodon server knows another Mastodon server, it "federates" with the other Mastodon server. Mastodon is a part of the wider Fediverse, allowing its users to also interact with users on different open platforms that support the same protocol, such as PeerTube and Friendica.</p>',
reblog: null, application: { name: 'Web' },
application: {
name: 'Web',
website: null
},
account: { account: {
id: '1001', id: '1001',
username: 'Fediverse', username: 'Fediverse',
acct: 'fediverse', acct: 'fediverse',
display_name: 'Fediverse', display_name: 'Fediverse',
avatar:
'https://e7.pngegg.com/pngimages/667/514/png-clipart-mastodon-fediverse-social-media-free-software-logo-social-media-blue-text.png',
avatar_static: avatar_static:
'https://e7.pngegg.com/pngimages/667/514/png-clipart-mastodon-fediverse-social-media-free-software-logo-social-media-blue-text.png' 'https://e7.pngegg.com/pngimages/667/514/png-clipart-mastodon-fediverse-social-media-free-software-logo-social-media-blue-text.png',
url: '',
header: '',
header_static: '',
locked: false,
discoverable: false,
created_at: new Date().toISOString(),
last_status_at: new Date().toISOString(),
statuses_count: 1,
followers_count: 1,
following_count: 1,
fields: [],
bot: false
}, },
media_attachments: [], media_attachments: [],
mentions: [] mentions: [],
tags: [],
emojis: [],
pinned: false
}, },
{ {
id: '4', id: '4',
uri: 'https://example.com',
created_at: '2021-01-24T08:50:00.901Z', created_at: '2021-01-24T08:50:00.901Z',
sensitive: false, sensitive: false,
visibility: 'public', visibility: 'public',
@ -134,7 +185,6 @@ const demoStatuses = [
bookmarked: false, bookmarked: false,
content: content:
'<p>tooot is an open source, simple mobile client for Mastodon. Focusing on your connections while being able to explore the Fediverse.</p>', '<p>tooot is an open source, simple mobile client for Mastodon. Focusing on your connections while being able to explore the Fediverse.</p>',
reblog: null,
application: { application: {
name: 'tooot', name: 'tooot',
website: 'https://tooot.app' website: 'https://tooot.app'
@ -144,14 +194,30 @@ const demoStatuses = [
username: 'tooot📱', username: 'tooot📱',
acct: 'tooot@xmflsct.com', acct: 'tooot@xmflsct.com',
display_name: 'tooot📱', display_name: 'tooot📱',
avatar_static: avatar: 'https://avatars.githubusercontent.com/u/77554750?s=200&v=4',
'https://avatars.githubusercontent.com/u/77554750?s=200&v=4' avatar_static: 'https://avatars.githubusercontent.com/u/77554750?s=200&v=4',
url: '',
header: '',
header_static: '',
locked: false,
discoverable: false,
created_at: new Date().toISOString(),
last_status_at: new Date().toISOString(),
statuses_count: 1,
followers_count: 1,
following_count: 1,
fields: [],
bot: false
}, },
media_attachments: [], media_attachments: [],
mentions: [] mentions: [],
tags: [],
emojis: [],
pinned: false
}, },
{ {
id: '5', id: '5',
uri: 'https://example.com',
created_at: '2021-01-24T07:50:00.901Z', created_at: '2021-01-24T07:50:00.901Z',
sensitive: false, sensitive: false,
visibility: 'public', visibility: 'public',
@ -164,7 +230,6 @@ const demoStatuses = [
bookmarked: false, bookmarked: false,
content: content:
'<p>- tooot supports multiple accounts<br />- tooot supports browsing external instance<br />- tooot aims to support multiple languages</p>', '<p>- tooot supports multiple accounts<br />- tooot supports browsing external instance<br />- tooot aims to support multiple languages</p>',
reblog: null,
application: { application: {
name: 'tooot', name: 'tooot',
website: 'https://tooot.app' website: 'https://tooot.app'
@ -174,12 +239,27 @@ const demoStatuses = [
username: 'tooot📱', username: 'tooot📱',
acct: 'tooot@xmflsct.com', acct: 'tooot@xmflsct.com',
display_name: 'tooot📱', display_name: 'tooot📱',
avatar_static: avatar: 'https://avatars.githubusercontent.com/u/77554750?s=200&v=4',
'https://avatars.githubusercontent.com/u/77554750?s=200&v=4' avatar_static: 'https://avatars.githubusercontent.com/u/77554750?s=200&v=4',
url: '',
header: '',
header_static: '',
locked: false,
discoverable: false,
created_at: new Date().toISOString(),
last_status_at: new Date().toISOString(),
statuses_count: 1,
followers_count: 1,
following_count: 1,
fields: [],
bot: false
}, },
media_attachments: [], media_attachments: [],
mentions: [] mentions: [],
tags: [],
emojis: [],
pinned: false
} }
] ]
export default demoStatuses export default demoStatus

View File

@ -86,9 +86,10 @@ const MenuRow: React.FC<Props> = ({
> >
<View <View
style={{ style={{
flex: 3, flexGrow: 3,
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center' alignItems: 'center',
marginRight: StyleConstants.Spacing.M
}} }}
> >
{iconFront && ( {iconFront && (

View File

@ -1,7 +1,7 @@
{ {
"server": { "server": {
"textInput": { "textInput": {
"placeholder": "Instance' domain" "placeholder": "Instance's domain"
}, },
"button": "Login", "button": "Login",
"information": { "information": {

View File

@ -1,13 +1,11 @@
{ {
"heading": { "heading": {
"left": { "left": {
"button": "Cancel",
"alert": { "alert": {
"title": "Cancel editing?", "title": "Cancel editing?",
"buttons": { "buttons": {
"save": "Save draft", "save": "Save draft",
"delete": "Delete draft", "delete": "Delete draft"
"cancel": "Cancel"
} }
} }
}, },

View File

@ -4,7 +4,6 @@
"name": "Following" "name": "Following"
}, },
"public": { "public": {
"name": "",
"segments": { "segments": {
"federated": "Federated", "federated": "Federated",
"local": "Local", "local": "Local",
@ -13,9 +12,6 @@
}, },
"notifications": { "notifications": {
"name": "Notifications" "name": "Notifications"
},
"me": {
"name": "About me"
} }
}, },
"common": { "common": {
@ -348,7 +344,7 @@
"notInLists": "Other lists" "notInLists": "Other lists"
}, },
"attachments": { "attachments": {
"name": "<0 /><1>\"s media</1>" "name": "<0 /><1>'s media</1>"
}, },
"hashtag": { "hashtag": {
"follow": "Follow", "follow": "Follow",

View File

@ -206,7 +206,7 @@ const ScreenCompose: React.FC<RootStackScreenProps<'Screen-Compose'>> = ({
() => ( () => (
<HeaderLeft <HeaderLeft
type='text' type='text'
content={t('heading.left.button')} content={t('common:buttons.cancel')}
onPress={() => { onPress={() => {
if (!composeState.dirty) { if (!composeState.dirty) {
navigation.goBack() navigation.goBack()
@ -229,7 +229,7 @@ const ScreenCompose: React.FC<RootStackScreenProps<'Screen-Compose'>> = ({
} }
}, },
{ {
text: t('heading.left.alert.buttons.cancel'), text: t('common:buttons.cancel'),
style: 'cancel' style: 'cancel'
} }
]) ])
@ -342,9 +342,7 @@ const ScreenCompose: React.FC<RootStackScreenProps<'Screen-Compose'>> = ({
) )
const headerContent = useMemo(() => { const headerContent = useMemo(() => {
return `${totalTextCount} / ${maxTootChars}${ return `${totalTextCount} / ${maxTootChars}`
__DEV__ ? ` Dirty: ${composeState.dirty.toString()}` : ''
}`
}, [totalTextCount, maxTootChars, composeState.dirty]) }, [totalTextCount, maxTootChars, composeState.dirty])
const inputProps: EmojisState['inputProps'] = [ const inputProps: EmojisState['inputProps'] = [

View File

@ -32,7 +32,7 @@ export const menuListDelete = ({
key: 'list-delete', key: 'list-delete',
onSelect: () => onSelect: () =>
Alert.alert( Alert.alert(
i18next.t('screenTabs:me.listDelete.confirm.title', { list: params.title.slice(0, 6) }), i18next.t('screenTabs:me.listDelete.confirm.title', { list: params.title.slice(0, 20) }),
i18next.t('screenTabs:me.listDelete.confirm.message'), i18next.t('screenTabs:me.listDelete.confirm.message'),
[ [
{ {

View File

@ -28,10 +28,7 @@ const AccountInformation = React.memo(
<View style={styles.base}> <View style={styles.base}>
<Placeholder <Placeholder
Animation={props => ( Animation={props => (
<Fade <Fade {...props} style={{ backgroundColor: colors.shimmerHighlight }} />
{...props}
style={{ backgroundColor: colors.shimmerHighlight }}
/>
)} )}
> >
<View style={styles.avatarAndActions}> <View style={styles.avatarAndActions}>
@ -41,7 +38,7 @@ const AccountInformation = React.memo(
<AccountInformationName account={account} /> <AccountInformationName account={account} />
<AccountInformationAccount account={account} localInstance={myInfo} /> <AccountInformationAccount account={account} />
<AccountInformationFields account={account} myInfo={myInfo} /> <AccountInformationFields account={account} myInfo={myInfo} />

View File

@ -1,10 +1,7 @@
import Icon from '@components/Icon' import Icon from '@components/Icon'
import CustomText from '@components/Text' import CustomText from '@components/Text'
import { useRelationshipQuery } from '@utils/queryHooks/relationship' import { useRelationshipQuery } from '@utils/queryHooks/relationship'
import { import { getInstanceAccount, getInstanceUri } from '@utils/slices/instancesSlice'
getInstanceAccount,
getInstanceUri
} 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'
import React from 'react' import React from 'react'
@ -15,19 +12,12 @@ import { PlaceholderLine } from 'rn-placeholder'
export interface Props { export interface Props {
account: Mastodon.Account | undefined account: Mastodon.Account | undefined
localInstance: boolean
} }
const AccountInformationAccount: React.FC<Props> = ({ const AccountInformationAccount: React.FC<Props> = ({ account }) => {
account,
localInstance
}) => {
const { t } = useTranslation('screenTabs') const { t } = useTranslation('screenTabs')
const { colors } = useTheme() const { colors } = useTheme()
const instanceAccount = useSelector( const instanceAccount = useSelector(getInstanceAccount, (prev, next) => prev?.acct === next?.acct)
getInstanceAccount,
(prev, next) => prev?.acct === next?.acct
)
const instanceUri = useSelector(getInstanceUri) const instanceUri = useSelector(getInstanceUri)
const { data: relationship } = useRelationshipQuery({ const { data: relationship } = useRelationshipQuery({
@ -35,6 +25,10 @@ const AccountInformationAccount: React.FC<Props> = ({
options: { enabled: account !== undefined } options: { enabled: account !== undefined }
}) })
const localInstance = instanceAccount.acct.includes('@')
? instanceAccount.acct.includes(`@${instanceUri}`)
: true
if (account || (localInstance && instanceAccount)) { if (account || (localInstance && instanceAccount)) {
return ( return (
<View <View
@ -54,7 +48,7 @@ const AccountInformationAccount: React.FC<Props> = ({
) : null} ) : null}
<CustomText <CustomText
style={{ style={{
textDecorationLine: (account?.moved || account?.suspended) ? 'line-through' : undefined textDecorationLine: account?.moved || account?.suspended ? 'line-through' : undefined
}} }}
selectable selectable
> >
@ -94,7 +88,4 @@ const AccountInformationAccount: React.FC<Props> = ({
} }
} }
export default React.memo( export default AccountInformationAccount
AccountInformationAccount,
(_, next) => next.account === undefined
)

View File

@ -5,7 +5,7 @@ import { StackNavigationProp } from '@react-navigation/stack'
import { TabLocalStackParamList } from '@utils/navigation/navigators' import { TabLocalStackParamList } from '@utils/navigation/navigators'
import { StyleConstants } from '@utils/styles/constants' import { StyleConstants } from '@utils/styles/constants'
import React from 'react' import React from 'react'
import { Pressable, StyleSheet, View } from 'react-native' import { Pressable, View } from 'react-native'
export interface Props { export interface Props {
account: Mastodon.Account | undefined account: Mastodon.Account | undefined
@ -13,24 +13,24 @@ export interface Props {
edit?: boolean edit?: boolean
} }
const AccountInformationAvatar: React.FC<Props> = ({ const AccountInformationAvatar: React.FC<Props> = ({ account, myInfo, edit }) => {
account, const navigation = useNavigation<StackNavigationProp<TabLocalStackParamList>>()
myInfo,
edit
}) => {
const navigation =
useNavigation<StackNavigationProp<TabLocalStackParamList>>()
return ( return (
<Pressable <Pressable
disabled={!myInfo} disabled={!myInfo}
onPress={() => { onPress={() => {
myInfo && account && navigation.push('Tab-Shared-Account', { account }) myInfo && account && navigation.push('Tab-Shared-Account', { account })
}} }}
style={styles.base} style={{
borderRadius: 8,
overflow: 'hidden',
width: StyleConstants.Avatar.L,
height: StyleConstants.Avatar.L
}}
> >
<GracefullyImage <GracefullyImage
key={account?.avatar} key={account?.avatar}
style={styles.image} style={{ flex: 1 }}
uri={{ original: account?.avatar, static: account?.avatar_static }} uri={{ original: account?.avatar, static: account?.avatar_static }}
/> />
{edit ? ( {edit ? (
@ -51,14 +51,4 @@ const AccountInformationAvatar: React.FC<Props> = ({
) )
} }
const styles = StyleSheet.create({
base: {
borderRadius: 8,
overflow: 'hidden',
width: StyleConstants.Avatar.L,
height: StyleConstants.Avatar.L
},
image: { flex: 1 }
})
export default AccountInformationAvatar export default AccountInformationAvatar

View File

@ -12,59 +12,53 @@ export interface Props {
hidden?: boolean hidden?: boolean
} }
const AccountInformationCreated = React.memo( const AccountInformationCreated: React.FC<Props> = ({ account, hidden = false }) => {
({ account, hidden = false }: Props) => { if (hidden) {
if (hidden) { return null
return null }
}
const { i18n } = useTranslation() const { i18n } = useTranslation()
const { colors } = useTheme() const { colors } = useTheme()
const { t } = useTranslation('screenTabs') const { t } = useTranslation('screenTabs')
if (account) { if (account) {
return ( return (
<View <View
style={{ style={{
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
borderRadius: 0, borderRadius: 0,
marginBottom: StyleConstants.Spacing.M marginBottom: StyleConstants.Spacing.M
}} }}
> >
<Icon <Icon
name='Calendar' name='Calendar'
size={StyleConstants.Font.Size.S} size={StyleConstants.Font.Size.S}
color={colors.secondary} color={colors.secondary}
style={{ marginRight: StyleConstants.Spacing.XS }} style={{ marginRight: StyleConstants.Spacing.XS }}
/>
<CustomText fontStyle='S' style={{ color: colors.secondary }}>
{t('shared.account.created_at', {
date: new Date(account.created_at || '').toLocaleDateString(
i18n.language,
{
year: 'numeric',
month: 'long',
day: 'numeric'
}
)
})}
</CustomText>
</View>
)
} else {
return (
<PlaceholderLine
width={StyleConstants.Font.Size.S * 4}
height={StyleConstants.Font.LineHeight.S}
color={colors.shimmerDefault}
noMargin
style={{ borderRadius: 0, marginBottom: StyleConstants.Spacing.M }}
/> />
) <CustomText fontStyle='S' style={{ color: colors.secondary }}>
} {t('shared.account.created_at', {
}, date: new Date(account.created_at || '').toLocaleDateString(i18n.language, {
(_, next) => next.account === undefined year: 'numeric',
) month: 'long',
day: 'numeric'
})
})}
</CustomText>
</View>
)
} else {
return (
<PlaceholderLine
width={StyleConstants.Font.Size.S * 4}
height={StyleConstants.Font.LineHeight.S}
color={colors.shimmerDefault}
noMargin
style={{ borderRadius: 0, marginBottom: StyleConstants.Spacing.M }}
/>
)
}
}
export default AccountInformationCreated export default AccountInformationCreated

View File

@ -10,53 +10,50 @@ export interface Props {
myInfo?: boolean myInfo?: boolean
} }
const AccountInformationFields = React.memo( const AccountInformationFields: React.FC<Props> = ({ account, myInfo }) => {
({ account, myInfo }: Props) => { if (account?.suspended || myInfo || !account?.fields || account.fields.length === 0) {
if (account?.suspended || myInfo || !account?.fields || account.fields.length === 0) { return null
return null }
}
const { colors } = useTheme() const { colors } = useTheme()
return ( return (
<View style={[styles.fields, { borderTopColor: colors.border }]}> <View style={[styles.fields, { borderTopColor: colors.border }]}>
{account.fields.map((field, index) => ( {account.fields.map((field, index) => (
<View key={index} style={[styles.field, { borderBottomColor: colors.border }]}> <View key={index} style={[styles.field, { borderBottomColor: colors.border }]}>
<View style={[styles.fieldLeft, { borderRightColor: colors.border }]}> <View style={[styles.fieldLeft, { borderRightColor: colors.border }]}>
<ParseHTML <ParseHTML
content={field.name} content={field.name}
size={'S'} size={'S'}
emojis={account.emojis} emojis={account.emojis}
showFullLink showFullLink
numberOfLines={5} numberOfLines={5}
selectable selectable
/>
{field.verified_at ? (
<Icon
name='CheckCircle'
size={StyleConstants.Font.Size.M}
color={colors.primaryDefault}
style={styles.fieldCheck}
/> />
{field.verified_at ? ( ) : null}
<Icon
name='CheckCircle'
size={StyleConstants.Font.Size.M}
color={colors.primaryDefault}
style={styles.fieldCheck}
/>
) : null}
</View>
<View style={styles.fieldRight}>
<ParseHTML
content={field.value}
size={'S'}
emojis={account.emojis}
showFullLink
numberOfLines={5}
selectable
/>
</View>
</View> </View>
))} <View style={styles.fieldRight}>
</View> <ParseHTML
) content={field.value}
}, size={'S'}
(_, next) => next.account === undefined emojis={account.emojis}
) showFullLink
numberOfLines={5}
selectable
/>
</View>
</View>
))}
</View>
)
}
const styles = StyleSheet.create({ const styles = StyleSheet.create({
fields: { fields: {

View File

@ -66,4 +66,4 @@ const AccountInformationName: React.FC<Props> = ({ account }) => {
) )
} }
export default React.memo(AccountInformationName, (_, next) => next.account === undefined) export default AccountInformationName

View File

@ -1,45 +1,35 @@
import { ParseHTML } from '@components/Parse' import { ParseHTML } from '@components/Parse'
import { StyleConstants } from '@utils/styles/constants' import { StyleConstants } from '@utils/styles/constants'
import React, { useState } from 'react' import React from 'react'
import { StyleSheet, View } from 'react-native' import { View } from 'react-native'
export interface Props { export interface Props {
account: Mastodon.Account | undefined account: Mastodon.Account | undefined
myInfo?: boolean myInfo?: boolean
} }
const AccountInformationNote = React.memo( const AccountInformationNote: React.FC<Props> = ({ account, myInfo }) => {
({ account, myInfo }: Props) => { if (
const [note, setNote] = useState(account?.source?.note) account?.suspended ||
if ( myInfo ||
account?.suspended || !account?.note ||
myInfo || account.note.length === 0 ||
!account?.note || account.note === '<p></p>'
account.note.length === 0 || ) {
account.note === '<p></p>' return null
) {
return null
}
return (
<View style={styles.note}>
<ParseHTML
content={account.note!}
size={'M'}
emojis={account.emojis}
selectable
numberOfLines={999}
/>
</View>
)
},
(_, next) => next.account === undefined
)
const styles = StyleSheet.create({
note: {
marginBottom: StyleConstants.Spacing.L
} }
})
return (
<View style={{ marginBottom: StyleConstants.Spacing.L }}>
<ParseHTML
content={account.note!}
size={'M'}
emojis={account.emojis}
selectable
numberOfLines={999}
/>
</View>
)
}
export default AccountInformationNote export default AccountInformationNote

View File

@ -39,7 +39,7 @@ const TabSharedAccountInLists: React.FC<
}) })
}, []) }, [])
const listsQuery = useListsQuery({}) const listsQuery = useListsQuery()
const accountInListsQuery = useAccountInListsQuery({ id: account.id }) const accountInListsQuery = useAccountInListsQuery({ id: account.id })
const sections = [ const sections = [
@ -48,8 +48,10 @@ const TabSharedAccountInLists: React.FC<
id: 'out', id: 'out',
title: t('shared.accountInLists.notInLists'), title: t('shared.accountInLists.notInLists'),
data: data:
listsQuery.data?.filter( listsQuery.data?.filter(({ id }) =>
({ id }) => accountInListsQuery.data?.filter(d => d.id !== id).length accountInListsQuery.data?.length
? accountInListsQuery.data.filter(d => d.id !== id).length
: true
) || [] ) || []
} }
] ]

View File

@ -54,7 +54,11 @@ const TabSharedSearch: React.FC<TabSharedStackScreenProps<'Tab-Shared-Search'>>
fontSize: StyleConstants.Font.Size.M, fontSize: StyleConstants.Font.Size.M,
flex: 1, flex: 1,
color: colors.primaryDefault, color: colors.primaryDefault,
paddingLeft: StyleConstants.Spacing.XS marginLeft: StyleConstants.Spacing.XS,
paddingLeft: StyleConstants.Spacing.XS,
paddingVertical: StyleConstants.Spacing.XS,
borderBottomColor: colors.border,
borderBottomWidth: 1
}} }}
autoFocus autoFocus
onChangeText={debounce( onChangeText={debounce(