Using new text component

Need to use global accessibility checks rather than per text component which is not efficient
This commit is contained in:
Zhiyuan Zheng 2022-05-07 00:52:32 +02:00
parent 8caf315894
commit 7c48c61c99
60 changed files with 1302 additions and 1494 deletions

View File

@ -123,7 +123,7 @@ private_lane :build_ios do
end
desc "Build and deploy Android app"
private_lane :build_android do
lane :build_android do
sh("echo #{ENV["ANDROID_KEYSTORE"]} | base64 -d | tee #{File.expand_path('..', Dir.pwd)}/android/tooot.jks >/dev/null", log: false)
case ENVIRONMENT

View File

@ -19,7 +19,7 @@
"android": "react-native run-android",
"iphone": "react-native run-ios",
"ipad": "react-native run-ios --simulator 'iPad mini (6th generation)'",
"app:build": "bundle exec fastlane build",
"app:build": "bundle exec fastlane build_android",
"release": "scripts/release.sh",
"clean": "react-native-clean-project",
"postinstall": "patch-package"

View File

@ -5,9 +5,10 @@ import { TabLocalStackParamList } from '@utils/navigation/navigators'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback } from 'react'
import { Pressable, StyleSheet, Text, View } from 'react-native'
import { Pressable, View } from 'react-native'
import analytics from './analytics'
import GracefullyImage from './GracefullyImage'
import CustomText from './Text'
export interface Props {
account: Mastodon.Account
@ -32,50 +33,45 @@ const ComponentAccount: React.FC<Props> = ({
return (
<Pressable
accessibilityRole='button'
style={[styles.itemDefault, styles.itemAccount]}
style={{
paddingHorizontal: StyleConstants.Spacing.Global.PagePadding,
paddingVertical: StyleConstants.Spacing.M,
flexDirection: 'row',
alignItems: 'center'
}}
onPress={customOnPress || onPress}
>
<GracefullyImage
uri={{ original: account.avatar, static: account.avatar_static }}
style={styles.itemAccountAvatar}
style={{
alignSelf: 'flex-start',
width: StyleConstants.Avatar.S,
height: StyleConstants.Avatar.S,
borderRadius: 6,
marginRight: StyleConstants.Spacing.S
}}
/>
<View>
<Text numberOfLines={1}>
<CustomText numberOfLines={1}>
<ParseEmojis
content={account.display_name || account.username}
emojis={account.emojis}
size='S'
fontBold
/>
</Text>
<Text
</CustomText>
<CustomText
numberOfLines={1}
style={[styles.itemAccountAcct, { color: colors.secondary }]}
style={{
marginTop: StyleConstants.Spacing.XS,
color: colors.secondary
}}
>
@{account.acct}
</Text>
</CustomText>
</View>
</Pressable>
)
}
const styles = StyleSheet.create({
itemDefault: {
paddingHorizontal: StyleConstants.Spacing.Global.PagePadding,
paddingVertical: StyleConstants.Spacing.M
},
itemAccount: {
flexDirection: 'row',
alignItems: 'center'
},
itemAccountAvatar: {
alignSelf: 'flex-start',
width: StyleConstants.Avatar.S,
height: StyleConstants.Avatar.S,
borderRadius: 6,
marginRight: StyleConstants.Spacing.S
},
itemAccountAcct: { marginTop: StyleConstants.Spacing.XS }
})
export default ComponentAccount

View File

@ -7,12 +7,11 @@ import {
AccessibilityProps,
Pressable,
StyleProp,
StyleSheet,
Text,
View,
ViewStyle
} from 'react-native'
import { Flow } from 'react-native-animated-spinkit'
import CustomText from './Text'
export interface Props {
accessibilityLabel?: AccessibilityProps['accessibilityLabel']
@ -116,7 +115,7 @@ const Button: React.FC<Props> = ({
case 'text':
return (
<>
<Text
<CustomText
style={{
color: mainColor,
fontSize:
@ -146,8 +145,10 @@ const Button: React.FC<Props> = ({
busy: loading
}}
style={[
styles.button,
{
borderRadius: 100,
justifyContent: 'center',
alignItems: 'center',
borderWidth: overlay ? 0 : 1,
borderColor: mainColor,
backgroundColor: colorBackground,
@ -170,12 +171,4 @@ const Button: React.FC<Props> = ({
)
}
const styles = StyleSheet.create({
button: {
borderRadius: 100,
justifyContent: 'center',
alignItems: 'center'
}
})
export default Button

View File

@ -1,3 +1,4 @@
import CustomText from '@components/Text'
import { useAppDispatch } from '@root/store'
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
import { countInstanceEmoji } from '@utils/slices/instancesSlice'
@ -11,8 +12,6 @@ import {
findNodeHandle,
Pressable,
SectionList,
StyleSheet,
Text,
View
} from 'react-native'
import FastImage from 'react-native-fast-image'
@ -30,7 +29,12 @@ const EmojisList = React.memo(
const listHeader = useCallback(
({ section: { title } }) => (
<Text style={[styles.group, { color: colors.secondary }]}>{title}</Text>
<CustomText
fontStyle='S'
style={{ position: 'absolute', color: colors.secondary }}
>
{title}
</CustomText>
),
[]
)
@ -38,7 +42,15 @@ const EmojisList = React.memo(
const listItem = useCallback(
({ index, item }: { item: Mastodon.Emoji[]; index: number }) => {
return (
<View key={index} style={styles.emojis}>
<View
key={index}
style={{
flex: 1,
flexWrap: 'wrap',
marginTop: StyleConstants.Spacing.M,
marginRight: StyleConstants.Spacing.S
}}
>
{item.map(emoji => {
const uri = reduceMotionEnabled ? emoji.static_url : emoji.url
if (validUrl.isHttpsUri(uri)) {
@ -64,7 +76,12 @@ const EmojisList = React.memo(
'screenCompose:content.root.footer.emojis.accessibilityHint'
)}
source={{ uri }}
style={styles.emoji}
style={{
width: 32,
height: 32,
padding: StyleConstants.Spacing.S,
margin: StyleConstants.Spacing.S
}}
/>
</Pressable>
)
@ -104,23 +121,4 @@ const EmojisList = React.memo(
() => true
)
const styles = StyleSheet.create({
group: {
position: 'absolute',
...StyleConstants.FontStyle.S
},
emojis: {
flex: 1,
flexWrap: 'wrap',
marginTop: StyleConstants.Spacing.M,
marginRight: StyleConstants.Spacing.S
},
emoji: {
width: 32,
height: 32,
padding: StyleConstants.Spacing.S,
margin: StyleConstants.Spacing.S
}
})
export default EmojisList

View File

@ -4,8 +4,9 @@ import { TabLocalStackParamList } from '@utils/navigation/navigators'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback } from 'react'
import { Pressable, StyleSheet, Text } from 'react-native'
import { Pressable } from 'react-native'
import analytics from './analytics'
import CustomText from './Text'
export interface Props {
hashtag: Mastodon.Tag
@ -30,23 +31,14 @@ const ComponentHashtag: React.FC<Props> = ({
return (
<Pressable
accessibilityRole='button'
style={styles.itemDefault}
style={{ padding: StyleConstants.Spacing.S * 1.5 }}
onPress={customOnPress || onPress}
>
<Text style={[styles.itemHashtag, { color: colors.primaryDefault }]}>
<CustomText fontStyle='M' style={{ color: colors.primaryDefault }}>
#{hashtag.name}
</Text>
</CustomText>
</Pressable>
)
}
const styles = StyleSheet.create({
itemDefault: {
padding: StyleConstants.Spacing.S * 1.5
},
itemHashtag: {
...StyleConstants.FontStyle.M
}
})
export default ComponentHashtag

View File

@ -1,7 +1,7 @@
import CustomText from '@components/Text'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { StyleSheet, Text } from 'react-native'
export interface Props {
content: string
@ -14,11 +14,12 @@ const HeaderCenter = React.memo(
const { colors } = useTheme()
return (
<Text
style={[
styles.text,
{ color: inverted ? colors.primaryOverlay : colors.primaryDefault }
]}
<CustomText
style={{
fontSize: 18,
fontWeight: StyleConstants.Font.Weight.Bold,
color: inverted ? colors.primaryOverlay : colors.primaryDefault
}}
children={content}
/>
)
@ -26,11 +27,4 @@ const HeaderCenter = React.memo(
(prev, next) => prev.content === next.content
)
const styles = StyleSheet.create({
text: {
fontSize: 18,
fontWeight: StyleConstants.Font.Weight.Bold
}
})
export default HeaderCenter

View File

@ -1,8 +1,9 @@
import Icon from '@components/Icon'
import CustomText from '@components/Text'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useMemo } from 'react'
import { Pressable, StyleSheet, Text } from 'react-native'
import { Pressable } from 'react-native'
export interface Props {
type?: 'icon' | 'text'
@ -34,8 +35,9 @@ const HeaderLeft: React.FC<Props> = ({
)
case 'text':
return (
<Text
style={[styles.text, { color: colors.primaryDefault }]}
<CustomText
fontStyle='M'
style={{ color: colors.primaryDefault }}
children={content}
/>
)
@ -46,38 +48,27 @@ const HeaderLeft: React.FC<Props> = ({
<Pressable
onPress={onPress}
children={children}
style={[
styles.base,
{
backgroundColor: background
? colors.backgroundOverlayDefault
: undefined,
minHeight: 44,
minWidth: 44,
marginLeft: native
? -StyleConstants.Spacing.S
: StyleConstants.Spacing.S,
...(type === 'icon' && {
borderRadius: 100
}),
...(type === 'text' && {
paddingHorizontal: StyleConstants.Spacing.S
})
}
]}
style={{
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: background
? colors.backgroundOverlayDefault
: undefined,
minHeight: 44,
minWidth: 44,
marginLeft: native
? -StyleConstants.Spacing.S
: StyleConstants.Spacing.S,
...(type === 'icon' && {
borderRadius: 100
}),
...(type === 'text' && {
paddingHorizontal: StyleConstants.Spacing.S
})
}}
/>
)
}
const styles = StyleSheet.create({
base: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center'
},
text: {
...StyleConstants.FontStyle.M
}
})
export default HeaderLeft

View File

@ -1,14 +1,9 @@
import Icon from '@components/Icon'
import CustomText from '@components/Text'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useMemo } from 'react'
import {
AccessibilityProps,
Pressable,
StyleSheet,
Text,
View
} from 'react-native'
import { AccessibilityProps, Pressable, View } from 'react-native'
import { Flow } from 'react-native-animated-spinkit'
export interface Props {
@ -72,14 +67,12 @@ const HeaderRight: React.FC<Props> = ({
case 'text':
return (
<>
<Text
style={[
styles.text,
{
color: disabled ? colors.secondary : colors.primaryDefault,
opacity: loading ? 0 : 1
}
]}
<CustomText
fontStyle='M'
style={{
color: disabled ? colors.secondary : colors.primaryDefault,
opacity: loading ? 0 : 1
}}
children={content}
/>
{loading && loadingSpinkit}
@ -97,38 +90,27 @@ const HeaderRight: React.FC<Props> = ({
onPress={onPress}
children={children}
disabled={disabled || loading}
style={[
styles.base,
{
backgroundColor: background
? colors.backgroundOverlayDefault
: undefined,
minHeight: 44,
minWidth: 44,
marginRight: native
? -StyleConstants.Spacing.S
: StyleConstants.Spacing.S,
...(type === 'icon' && {
borderRadius: 100
}),
...(type === 'text' && {
paddingHorizontal: StyleConstants.Spacing.S
})
}
]}
style={{
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: background
? colors.backgroundOverlayDefault
: undefined,
minHeight: 44,
minWidth: 44,
marginRight: native
? -StyleConstants.Spacing.S
: StyleConstants.Spacing.S,
...(type === 'icon' && {
borderRadius: 100
}),
...(type === 'text' && {
paddingHorizontal: StyleConstants.Spacing.S
})
}}
/>
)
}
const styles = StyleSheet.create({
base: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center'
},
text: {
...StyleConstants.FontStyle.M
}
})
export default HeaderRight

View File

@ -9,17 +9,11 @@ import React, {
useRef,
useState
} from 'react'
import {
Platform,
StyleSheet,
Text,
TextInput,
TextInputProps,
View
} from 'react-native'
import { Platform, TextInput, TextInputProps, View } from 'react-native'
import Animated, { useAnimatedStyle, withTiming } from 'react-native-reanimated'
import { ComponentEmojis, EmojisButton, EmojisList } from './Emojis'
import EmojisContext from './Emojis/helpers/EmojisContext'
import CustomText from './Text'
export interface Props {
autoFocus?: boolean
@ -106,14 +100,14 @@ const Input: React.FC<Props> = ({
maxLength={options?.maxLength}
>
<View
style={[
styles.base,
{
borderColor: colors.border,
flexDirection: multiline ? 'column' : 'row',
alignItems: 'stretch'
}
]}
style={{
borderWidth: 1,
marginVertical: StyleConstants.Spacing.S,
padding: StyleConstants.Spacing.S,
borderColor: colors.border,
flexDirection: multiline ? 'column' : 'row',
alignItems: 'stretch'
}}
>
<EmojisContext.Consumer>
{({ emojisDispatch }) => (
@ -124,16 +118,15 @@ const Input: React.FC<Props> = ({
setInputFocused(false)
emojisDispatch({ type: 'activate', payload: false })
}}
style={[
styles.textInput,
{
color: colors.primaryDefault,
minHeight:
Platform.OS === 'ios' && multiline
? StyleConstants.Font.LineHeight.M * 5
: undefined
}
]}
style={{
flex: 1,
fontSize: StyleConstants.Font.Size.M,
color: colors.primaryDefault,
minHeight:
Platform.OS === 'ios' && multiline
? StyleConstants.Font.LineHeight.M * 5
: undefined
}}
onChangeText={setValue}
onSelectionChange={onSelectionChange}
value={value}
@ -149,16 +142,25 @@ const Input: React.FC<Props> = ({
</EmojisContext.Consumer>
{title ? (
<Animated.Text
style={[styles.title, animateTitle, { color: colors.secondary }]}
style={[
animateTitle,
{ position: 'absolute', color: colors.secondary }
]}
>
{title}
</Animated.Text>
) : null}
<View style={{ flexDirection: 'row', alignSelf: 'flex-end' }}>
{options?.maxLength && value?.length ? (
<Text style={[styles.maxLength, { color: colors.secondary }]}>
<CustomText
fontStyle='S'
style={{
paddingLeft: StyleConstants.Spacing.XS,
color: colors.secondary
}}
>
{value?.length} / {options.maxLength}
</Text>
</CustomText>
) : null}
{inputFocused ? <EmojisButton /> : null}
</View>
@ -168,24 +170,4 @@ const Input: React.FC<Props> = ({
)
}
const styles = StyleSheet.create({
base: {
alignItems: 'flex-end',
borderWidth: 1,
marginVertical: StyleConstants.Spacing.S,
padding: StyleConstants.Spacing.S
},
title: {
position: 'absolute'
},
textInput: {
flex: 1,
fontSize: StyleConstants.Font.Size.M
},
maxLength: {
...StyleConstants.FontStyle.S,
paddingLeft: StyleConstants.Spacing.XS
}
})
export default Input

View File

@ -15,8 +15,6 @@ import {
Image,
KeyboardAvoidingView,
Platform,
StyleSheet,
Text,
TextInput,
View
} from 'react-native'
@ -26,6 +24,7 @@ import { Placeholder } from 'rn-placeholder'
import analytics from './analytics'
import InstanceAuth from './Instance/Auth'
import InstanceInfo from './Instance/Info'
import CustomText from './Text'
export interface Props {
scrollViewRef?: RefObject<ScrollView>
@ -134,40 +133,50 @@ const ComponentInstance: React.FC<Props> = ({
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
>
{!disableHeaderImage ? (
<View style={styles.imageContainer}>
<View style={{ flexDirection: 'row' }}>
<Image
source={require('assets/images/welcome.png')}
style={styles.image}
style={{ resizeMode: 'contain', flex: 1, aspectRatio: 16 / 9 }}
/>
</View>
) : null}
<View style={styles.base}>
<View style={styles.inputRow}>
<View
style={{
marginTop: StyleConstants.Spacing.L,
marginHorizontal: StyleConstants.Spacing.Global.PagePadding
}}
>
<View
style={{
flexDirection: 'row',
marginHorizontal: StyleConstants.Spacing.Global.PagePadding
}}
>
<TextInput
accessible={false}
accessibilityRole='none'
style={[
styles.prefix,
{
color: colors.primaryDefault,
borderBottomColor: instanceQuery.isError
? colors.red
: colors.border
}
]}
style={{
borderBottomWidth: 1,
...StyleConstants.FontStyle.M,
color: colors.primaryDefault,
borderBottomColor: instanceQuery.isError
? colors.red
: colors.border
}}
editable={false}
defaultValue='https://'
/>
<TextInput
style={[
styles.textInput,
{
color: colors.primaryDefault,
borderBottomColor: instanceQuery.isError
? colors.red
: colors.border
}
]}
style={{
flex: 1,
borderBottomWidth: 1,
...StyleConstants.FontStyle.M,
marginRight: StyleConstants.Spacing.M,
color: colors.primaryDefault,
borderBottomColor: instanceQuery.isError
? colors.red
: colors.border
}}
onChangeText={onChangeText}
autoCapitalize='none'
clearButtonMode='never'
@ -205,9 +214,9 @@ const ComponentInstance: React.FC<Props> = ({
content={instanceQuery.data?.title || undefined}
potentialWidth={2}
/>
<View style={styles.instanceStats}>
<View style={{ flex: 1, flexDirection: 'row' }}>
<InstanceInfo
style={styles.stat1}
style={{ alignItems: 'flex-start' }}
header={t('server.information.accounts')}
content={
instanceQuery.data?.stats?.user_count?.toString() || undefined
@ -215,7 +224,7 @@ const ComponentInstance: React.FC<Props> = ({
potentialWidth={4}
/>
<InstanceInfo
style={styles.stat2}
style={{ alignItems: 'center' }}
header={t('server.information.statuses')}
content={
instanceQuery.data?.stats?.status_count?.toString() ||
@ -224,7 +233,7 @@ const ComponentInstance: React.FC<Props> = ({
potentialWidth={4}
/>
<InstanceInfo
style={styles.stat3}
style={{ alignItems: 'flex-end' }}
header={t('server.information.domains')}
content={
instanceQuery.data?.stats?.domain_count?.toString() ||
@ -234,15 +243,28 @@ const ComponentInstance: React.FC<Props> = ({
/>
</View>
</Placeholder>
<View style={styles.disclaimer}>
<View
style={{
flexDirection: 'row',
marginHorizontal: StyleConstants.Spacing.Global.PagePadding,
marginVertical: StyleConstants.Spacing.M
}}
>
<Icon
name='Lock'
size={StyleConstants.Font.Size.S}
color={colors.secondary}
style={styles.disclaimerIcon}
style={{
marginTop:
(StyleConstants.Font.LineHeight.S -
StyleConstants.Font.Size.S) /
2,
marginRight: StyleConstants.Spacing.XS
}}
/>
<Text
style={[styles.disclaimerText, { color: colors.secondary }]}
<CustomText
fontStyle='S'
style={{ flex: 1, color: colors.secondary }}
accessibilityRole='link'
onPress={() => {
if (screenReaderEnabled) {
@ -254,7 +276,7 @@ const ComponentInstance: React.FC<Props> = ({
}}
>
{t('server.disclaimer.base')}
<Text
<CustomText
accessible
style={{ color: colors.blue }}
onPress={() => {
@ -265,8 +287,8 @@ const ComponentInstance: React.FC<Props> = ({
}}
>
{t('server.disclaimer.privacy')}
</Text>
</Text>
</CustomText>
</CustomText>
</View>
</View>
</View>
@ -276,54 +298,4 @@ const ComponentInstance: React.FC<Props> = ({
)
}
const styles = StyleSheet.create({
imageContainer: { flexDirection: 'row' },
image: { resizeMode: 'contain', flex: 1, aspectRatio: 16 / 9 },
base: {
marginTop: StyleConstants.Spacing.L,
marginHorizontal: StyleConstants.Spacing.Global.PagePadding
},
inputRow: {
flexDirection: 'row',
marginHorizontal: StyleConstants.Spacing.Global.PagePadding
},
prefix: {
borderBottomWidth: 1,
...StyleConstants.FontStyle.M
},
textInput: {
flex: 1,
borderBottomWidth: 1,
...StyleConstants.FontStyle.M,
marginRight: StyleConstants.Spacing.M
},
instanceStats: {
flex: 1,
flexDirection: 'row'
},
stat1: {
alignItems: 'flex-start'
},
stat2: {
alignItems: 'center'
},
stat3: {
alignItems: 'flex-end'
},
disclaimer: {
flexDirection: 'row',
marginHorizontal: StyleConstants.Spacing.Global.PagePadding,
marginVertical: StyleConstants.Spacing.M
},
disclaimerIcon: {
marginTop:
(StyleConstants.Font.LineHeight.S - StyleConstants.Font.Size.S) / 2,
marginRight: StyleConstants.Spacing.XS
},
disclaimerText: {
flex: 1,
...StyleConstants.FontStyle.S
}
})
export default ComponentInstance

View File

@ -1,7 +1,8 @@
import CustomText from '@components/Text'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { StyleSheet, Text, View, ViewStyle } from 'react-native'
import { View, ViewStyle } from 'react-native'
import { PlaceholderLine } from 'rn-placeholder'
export interface Props {
@ -16,14 +17,33 @@ const InstanceInfo = React.memo(
const { colors } = useTheme()
return (
<View style={[styles.base, style]} accessible>
<Text style={[styles.header, { color: colors.primaryDefault }]}>
{header}
</Text>
<View
style={[
{
flex: 1,
marginTop: StyleConstants.Spacing.M,
paddingLeft: StyleConstants.Spacing.Global.PagePadding,
paddingRight: StyleConstants.Spacing.Global.PagePadding
},
style
]}
accessible
>
<CustomText
fontStyle='S'
style={{
fontWeight: StyleConstants.Font.Weight.Bold,
marginBottom: StyleConstants.Spacing.XS,
color: colors.primaryDefault
}}
children={header}
/>
{content ? (
<Text style={[styles.content, { color: colors.primaryDefault }]}>
{content}
</Text>
<CustomText
fontStyle='M'
style={{ color: colors.primaryDefault }}
children={content}
/>
) : (
<PlaceholderLine
width={
@ -43,21 +63,4 @@ const InstanceInfo = React.memo(
(prev, next) => prev.content === next.content
)
const styles = StyleSheet.create({
base: {
flex: 1,
marginTop: StyleConstants.Spacing.M,
paddingLeft: StyleConstants.Spacing.Global.PagePadding,
paddingRight: StyleConstants.Spacing.Global.PagePadding
},
header: {
...StyleConstants.FontStyle.S,
fontWeight: StyleConstants.Font.Weight.Bold,
marginBottom: StyleConstants.Spacing.XS
},
content: {
...StyleConstants.FontStyle.M
}
})
export default InstanceInfo

View File

@ -1,7 +1,8 @@
import React from 'react'
import { StyleSheet, Text, View } from 'react-native'
import { View } from 'react-native'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import CustomText from '@components/Text'
export interface Props {
heading: string
@ -11,20 +12,16 @@ const MenuHeader: React.FC<Props> = ({ heading }) => {
const { colors } = useTheme()
return (
<View style={styles.base}>
<Text style={[styles.text, { color: colors.secondary }]}>{heading}</Text>
<View style={{ paddingBottom: StyleConstants.Spacing.S }}>
<CustomText
fontStyle='S'
fontWeight='Bold'
style={{ color: colors.secondary }}
>
{heading}
</CustomText>
</View>
)
}
const styles = StyleSheet.create({
base: {
paddingBottom: StyleConstants.Spacing.S
},
text: {
...StyleConstants.FontStyle.S,
fontWeight: StyleConstants.Font.Weight.Bold
}
})
export default MenuHeader

View File

@ -1,4 +1,5 @@
import Icon from '@components/Icon'
import CustomText from '@components/Text'
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
@ -99,12 +100,13 @@ const MenuRow: React.FC<Props> = ({
/>
) : null}
<View style={styles.main}>
<Text
style={[styles.title, { color: colors.primaryDefault }]}
<CustomText
fontStyle='M'
style={{ color: colors.primaryDefault }}
numberOfLines={1}
>
{title}
</Text>
</CustomText>
</View>
</View>
@ -112,18 +114,15 @@ const MenuRow: React.FC<Props> = ({
<View style={styles.back}>
{content ? (
typeof content === 'string' ? (
<Text
style={[
styles.content,
{
color: colors.secondary,
opacity: !iconBack && loading ? 0 : 1
}
]}
<CustomText
style={{
color: colors.secondary,
opacity: !iconBack && loading ? 0 : 1
}}
numberOfLines={1}
>
{content}
</Text>
</CustomText>
) : (
content
)
@ -150,9 +149,9 @@ const MenuRow: React.FC<Props> = ({
) : null}
</View>
{description ? (
<Text style={[styles.description, { color: colors.secondary }]}>
<CustomText fontStyle='S' style={{ color: colors.secondary }}>
{description}
</Text>
</CustomText>
) : null}
</View>
</TapGestureHandler>
@ -187,9 +186,6 @@ const styles = StyleSheet.create({
main: {
flex: 1
},
title: {
...StyleConstants.FontStyle.M
},
description: {
...StyleConstants.FontStyle.S
},

View File

@ -1,10 +1,11 @@
import CustomText from '@components/Text'
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
import { getSettingsFontsize } from '@utils/slices/settingsSlice'
import { StyleConstants } from '@utils/styles/constants'
import { adaptiveScale } from '@utils/styles/scaling'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useMemo } from 'react'
import { StyleSheet, Text } from 'react-native'
import { StyleSheet } from 'react-native'
import FastImage from 'react-native-fast-image'
import { useSelector } from 'react-redux'
import validUrl from 'valid-url'
@ -57,7 +58,7 @@ const ParseEmojis = React.memo(
}, [theme, adaptiveFontsize])
return (
<Text style={styles.text}>
<CustomText style={styles.text}>
{emojis ? (
content
.split(regexEmoji)
@ -69,30 +70,34 @@ const ParseEmojis = React.memo(
return emojiShortcode === `:${emoji.shortcode}:`
})
if (emojiIndex === -1) {
return <Text key={emojiShortcode + i}>{emojiShortcode}</Text>
return (
<CustomText key={emojiShortcode + i}>
{emojiShortcode}
</CustomText>
)
} else {
const uri = reduceMotionEnabled
? emojis[emojiIndex].static_url
: emojis[emojiIndex].url
if (validUrl.isHttpsUri(uri)) {
return (
<Text key={emojiShortcode + i}>
<CustomText key={emojiShortcode + i}>
{i === 0 ? ' ' : undefined}
<FastImage source={{ uri }} style={styles.image} />
</Text>
</CustomText>
)
} else {
return null
}
}
} else {
return <Text key={i}>{str}</Text>
return <CustomText key={i}>{str}</CustomText>
}
})
) : (
<Text>{content}</Text>
<CustomText>{content}</CustomText>
)}
</Text>
</CustomText>
)
},
(prev, next) => prev.content === next.content

View File

@ -2,6 +2,7 @@ import analytics from '@components/analytics'
import Icon from '@components/Icon'
import openLink from '@components/openLink'
import ParseEmojis from '@components/Parse/Emojis'
import CustomText from '@components/Text'
import { useNavigation, useRoute } from '@react-navigation/native'
import { StackNavigationProp } from '@react-navigation/stack'
import { TabLocalStackParamList } from '@utils/navigation/navigators'
@ -12,7 +13,7 @@ import { adaptiveScale } from '@utils/styles/scaling'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Pressable, Text, View } from 'react-native'
import { Pressable, View } from 'react-native'
import HTMLView from 'react-native-htmlview'
import { useSelector } from 'react-redux'
@ -53,7 +54,7 @@ const renderNode = ({
? routeParams.hashtag !== tag[1] && routeParams.hashtag !== tag[2]
: true
return (
<Text
<CustomText
accessible
key={index}
style={{
@ -72,7 +73,7 @@ const renderNode = ({
>
{node.children[0].data}
{node.children[1]?.children[0].data}
</Text>
</CustomText>
)
} else if (classes.includes('mention') && mentions) {
const accountIndex = mentions.findIndex(
@ -82,7 +83,7 @@ const renderNode = ({
? routeParams.account.id !== mentions[accountIndex]?.id
: true
return (
<Text
<CustomText
key={index}
style={{
color:
@ -102,7 +103,7 @@ const renderNode = ({
>
{node.children[0].data}
{node.children[1]?.children[0].data}
</Text>
</CustomText>
)
}
} else {
@ -113,7 +114,7 @@ const renderNode = ({
const shouldBeTag =
tags && tags.filter(tag => `#${tag.name}` === content).length > 0
return (
<Text
<CustomText
key={index}
style={{
color: colors.blue,
@ -142,7 +143,7 @@ const renderNode = ({
}}
/>
) : null}
</Text>
</CustomText>
)
}
break
@ -252,7 +253,7 @@ const ParseHTML = React.memo(
return (
<View style={{ overflow: 'hidden' }}>
<Text
<CustomText
children={children}
onTextLayout={onTextLayout}
numberOfLines={
@ -275,7 +276,7 @@ const ParseHTML = React.memo(
backgroundColor: colors.backgroundDefault
}}
>
<Text
<CustomText
style={{
textAlign: 'center',
...StyleConstants.FontStyle.S,

76
src/components/Text.tsx Normal file
View File

@ -0,0 +1,76 @@
import { StyleConstants } from '@utils/styles/constants'
import { useEffect, useState } from 'react'
import { AccessibilityInfo, Text, TextProps, TextStyle } from 'react-native'
type Props =
| {
style?: Omit<TextStyle, 'fontSize' | 'lineHeight' | 'fontWeight'>
fontStyle?: undefined
fontSize?: 'S' | 'M' | 'L'
lineHeight?: 'S' | 'M' | 'L'
fontWeight?: 'Normal' | 'Bold'
}
| {
style?: Omit<TextStyle, 'fontSize' | 'lineHeight' | 'fontWeight'>
fontStyle: 'S' | 'M' | 'L'
fontSize?: undefined
lineHeight?: undefined
fontWeight?: 'Normal' | 'Bold'
}
const CustomText: React.FC<Props & TextProps> = ({
children,
style,
fontStyle,
fontSize,
fontWeight = 'Normal',
lineHeight,
...rest
}) => {
const [isBoldText, setIsBoldText] = useState(false)
useEffect(() => {
const boldTextChangedSubscription = AccessibilityInfo.addEventListener(
'boldTextChanged',
boldTextChanged => {
setIsBoldText(boldTextChanged)
}
)
AccessibilityInfo.isBoldTextEnabled().then(boldTextEnabled => {
setIsBoldText(boldTextEnabled)
})
return () => {
boldTextChangedSubscription.remove()
}
}, [])
enum BoldMapping {
'Normal' = '600',
'Bold' = '800'
}
return (
<Text
style={[
style,
{ ...(fontStyle && StyleConstants.FontStyle[fontStyle]) },
{ ...(fontSize && { fontSize: StyleConstants.Font.Size[fontSize] }) },
{
...(lineHeight && {
lineHeight: StyleConstants.Font.LineHeight[lineHeight]
})
},
{
fontWeight: isBoldText
? BoldMapping[fontWeight]
: StyleConstants.Font.Weight[fontWeight]
}
]}
{...rest}
>
{children}
</Text>
)
}
export default CustomText

View File

@ -1,12 +1,13 @@
import analytics from '@components/analytics'
import Button from '@components/Button'
import Icon from '@components/Icon'
import CustomText from '@components/Text'
import { QueryKeyTimeline, useTimelineQuery } from '@utils/queryHooks/timeline'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { StyleSheet, Text, View } from 'react-native'
import { View } from 'react-native'
import { Circle } from 'react-native-animated-spinkit'
export interface Props {
@ -40,9 +41,16 @@ const TimelineEmpty = React.memo(
size={StyleConstants.Font.Size.L}
color={colors.primaryDefault}
/>
<Text style={[styles.error, { color: colors.primaryDefault }]}>
<CustomText
fontStyle='M'
style={{
marginTop: StyleConstants.Spacing.S,
marginBottom: StyleConstants.Spacing.L,
color: colors.primaryDefault
}}
>
{t('empty.error.message')}
</Text>
</CustomText>
<Button
type='text'
content={t('empty.error.button')}
@ -61,9 +69,16 @@ const TimelineEmpty = React.memo(
size={StyleConstants.Font.Size.L}
color={colors.primaryDefault}
/>
<Text style={[styles.error, { color: colors.primaryDefault }]}>
<CustomText
fontStyle='M'
style={{
marginTop: StyleConstants.Spacing.S,
marginBottom: StyleConstants.Spacing.L,
color: colors.primaryDefault
}}
>
{t('empty.success.message')}
</Text>
</CustomText>
</>
)
}
@ -85,12 +100,4 @@ const TimelineEmpty = React.memo(
() => true
)
const styles = StyleSheet.create({
error: {
...StyleConstants.FontStyle.M,
marginTop: StyleConstants.Spacing.S,
marginBottom: StyleConstants.Spacing.L
}
})
export default TimelineEmpty

View File

@ -1,10 +1,11 @@
import Icon from '@components/Icon'
import CustomText from '@components/Text'
import { QueryKeyTimeline, useTimelineQuery } from '@utils/queryHooks/timeline'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { Trans } from 'react-i18next'
import { Text, View } from 'react-native'
import { View } from 'react-native'
import { Circle } from 'react-native-animated-spinkit'
export interface Props {
@ -38,9 +39,7 @@ const TimelineFooter = React.memo(
{!disableInfinity && hasNextPage ? (
<Circle size={StyleConstants.Font.Size.L} color={colors.secondary} />
) : (
<Text
style={{ ...StyleConstants.FontStyle.S, color: colors.secondary }}
>
<CustomText fontStyle='S' style={{ color: colors.secondary }}>
<Trans
i18nKey='componentTimeline:end.message'
components={[
@ -51,7 +50,7 @@ const TimelineFooter = React.memo(
/>
]}
/>
</Text>
</CustomText>
)}
</View>
)

View File

@ -1,8 +1,9 @@
import CustomText from '@components/Text'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { Text, View } from 'react-native'
import { View } from 'react-native'
const TimelineLookback = React.memo(
() => {
@ -19,14 +20,9 @@ const TimelineLookback = React.memo(
backgroundColor: colors.backgroundDefault
}}
>
<Text
style={{
...StyleConstants.FontStyle.S,
color: colors.primaryDefault
}}
>
<CustomText fontStyle='S' style={{ color: colors.primaryDefault }}>
{t('lookback.message')}
</Text>
</CustomText>
</View>
)
},

View File

@ -1,5 +1,6 @@
import haptics from '@components/haptics'
import Icon from '@components/Icon'
import CustomText from '@components/Text'
import {
QueryKeyTimeline,
TimelineData,
@ -9,7 +10,7 @@ import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { RefObject, useCallback, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { FlatList, Platform, StyleSheet, Text, View } from 'react-native'
import { FlatList, Platform, View } from 'react-native'
import { Circle } from 'react-native-animated-spinkit'
import Animated, {
Extrapolate,
@ -251,9 +252,18 @@ const TimelineRefresh: React.FC<Props> = ({
return (
<Animated.View style={headerPadding}>
<View style={styles.base}>
<View
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
height: CONTAINER_HEIGHT * 2,
alignItems: 'center'
}}
>
{isFetching ? (
<View style={styles.container2}>
<View style={{ height: CONTAINER_HEIGHT, justifyContent: 'center' }}>
<Circle
size={StyleConstants.Font.Size.L}
color={colors.secondary}
@ -261,9 +271,19 @@ const TimelineRefresh: React.FC<Props> = ({
</View>
) : (
<>
<View style={styles.container1}>
<Text
style={[styles.explanation, { color: colors.primaryDefault }]}
<View
style={{
flex: 1,
flexDirection: 'row',
height: CONTAINER_HEIGHT
}}
>
<CustomText
fontStyle='S'
style={{
lineHeight: CONTAINER_HEIGHT,
color: colors.primaryDefault
}}
onLayout={onLayout}
children={t('refresh.fetchPreviousPage')}
/>
@ -285,9 +305,15 @@ const TimelineRefresh: React.FC<Props> = ({
}
/>
</View>
<View style={styles.container2}>
<Text
style={[styles.explanation, { color: colors.primaryDefault }]}
<View
style={{ height: CONTAINER_HEIGHT, justifyContent: 'center' }}
>
<CustomText
fontStyle='S'
style={{
lineHeight: CONTAINER_HEIGHT,
color: colors.primaryDefault
}}
onLayout={onLayout}
children={t('refresh.refetch')}
/>
@ -299,25 +325,4 @@ const TimelineRefresh: React.FC<Props> = ({
)
}
const styles = StyleSheet.create({
base: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
height: CONTAINER_HEIGHT * 2,
alignItems: 'center'
},
container1: {
flex: 1,
flexDirection: 'row',
height: CONTAINER_HEIGHT
},
container2: { height: CONTAINER_HEIGHT, justifyContent: 'center' },
explanation: {
fontSize: StyleConstants.Font.Size.S,
lineHeight: CONTAINER_HEIGHT
}
})
export default TimelineRefresh

View File

@ -1,6 +1,7 @@
import analytics from '@components/analytics'
import Icon from '@components/Icon'
import { displayMessage } from '@components/Message'
import CustomText from '@components/Text'
import { useNavigation } from '@react-navigation/native'
import { StackNavigationProp } from '@react-navigation/stack'
import { RootStackParamList } from '@utils/navigation/navigators'
@ -13,7 +14,7 @@ import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { Pressable, StyleSheet, Text, View } from 'react-native'
import { Pressable, StyleSheet, View } from 'react-native'
import { useQueryClient } from 'react-query'
export interface Props {
@ -185,7 +186,7 @@ const TimelineActions: React.FC<Props> = ({
size={StyleConstants.Font.Size.L}
/>
{status.replies_count > 0 ? (
<Text
<CustomText
style={{
color: colors.secondary,
fontSize: StyleConstants.Font.Size.M,
@ -193,7 +194,7 @@ const TimelineActions: React.FC<Props> = ({
}}
>
{status.replies_count}
</Text>
</CustomText>
) : null}
</>
),
@ -213,7 +214,7 @@ const TimelineActions: React.FC<Props> = ({
size={StyleConstants.Font.Size.L}
/>
{status.reblogs_count > 0 ? (
<Text
<CustomText
style={{
color: color(status.reblogged),
fontSize: StyleConstants.Font.Size.M,
@ -221,7 +222,7 @@ const TimelineActions: React.FC<Props> = ({
}}
>
{status.reblogs_count}
</Text>
</CustomText>
) : null}
</>
)
@ -236,7 +237,7 @@ const TimelineActions: React.FC<Props> = ({
size={StyleConstants.Font.Size.L}
/>
{status.favourites_count > 0 ? (
<Text
<CustomText
style={{
color: color(status.favourited),
fontSize: StyleConstants.Font.Size.M,
@ -245,7 +246,7 @@ const TimelineActions: React.FC<Props> = ({
}}
>
{status.favourites_count}
</Text>
</CustomText>
) : null}
</>
)
@ -269,7 +270,7 @@ const TimelineActions: React.FC<Props> = ({
: StyleConstants.Avatar.M + StyleConstants.Spacing.S
}}
>
<View style={styles.actions}>
<View style={{ flexDirection: 'row' }}>
<Pressable
{...(highlighted
? {
@ -334,9 +335,6 @@ const TimelineActions: React.FC<Props> = ({
}
const styles = StyleSheet.create({
actions: {
flexDirection: 'row'
},
action: {
flex: 1,
flexDirection: 'row',

View File

@ -1,11 +1,12 @@
import analytics from '@components/analytics'
import Button from '@components/Button'
import openLink from '@components/openLink'
import CustomText from '@components/Text'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { StyleSheet, Text, View } from 'react-native'
import { View } from 'react-native'
import { Blurhash } from 'react-native-blurhash'
import attachmentAspectRatio from './aspectRatio'
@ -27,10 +28,14 @@ const AttachmentUnsupported: React.FC<Props> = ({
return (
<View
style={[
styles.base,
{ aspectRatio: attachmentAspectRatio({ total, index }) }
]}
style={{
flex: 1,
flexBasis: '50%',
padding: StyleConstants.Spacing.XS / 2,
justifyContent: 'center',
alignItems: 'center',
aspectRatio: attachmentAspectRatio({ total, index })
}}
>
{attachment.blurhash ? (
<Blurhash
@ -44,18 +49,18 @@ const AttachmentUnsupported: React.FC<Props> = ({
) : null}
{!sensitiveShown ? (
<>
<Text
style={[
styles.text,
{
color: attachment.blurhash
? colors.backgroundDefault
: colors.primaryDefault
}
]}
<CustomText
fontStyle='S'
style={{
textAlign: 'center',
marginBottom: StyleConstants.Spacing.S,
color: attachment.blurhash
? colors.backgroundDefault
: colors.primaryDefault
}}
>
{t('shared.attachment.unsupported.text')}
</Text>
</CustomText>
{attachment.remote_url ? (
<Button
type='text'
@ -74,19 +79,4 @@ const AttachmentUnsupported: React.FC<Props> = ({
)
}
const styles = StyleSheet.create({
base: {
flex: 1,
flexBasis: '50%',
padding: StyleConstants.Spacing.XS / 2,
justifyContent: 'center',
alignItems: 'center'
},
text: {
...StyleConstants.FontStyle.S,
textAlign: 'center',
marginBottom: StyleConstants.Spacing.S
}
})
export default AttachmentUnsupported

View File

@ -1,11 +1,12 @@
import analytics from '@components/analytics'
import GracefullyImage from '@components/GracefullyImage'
import openLink from '@components/openLink'
import CustomText from '@components/Text'
import { useNavigation } from '@react-navigation/native'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { Pressable, StyleSheet, Text, View } from 'react-native'
import { Pressable, StyleSheet, View } from 'react-native'
export interface Props {
card: Pick<
@ -22,7 +23,16 @@ const TimelineCard = React.memo(({ card }: Props) => {
<Pressable
accessible
accessibilityRole='link'
style={[styles.card, { borderColor: colors.border }]}
style={{
flex: 1,
flexDirection: 'row',
height: StyleConstants.Font.LineHeight.M * 5,
marginTop: StyleConstants.Spacing.M,
borderWidth: StyleSheet.hairlineWidth,
borderRadius: 6,
overflow: 'hidden',
borderColor: colors.border
}}
onPress={async () => {
analytics('timeline_shared_card_press')
await openLink(card.url, navigation)
@ -33,71 +43,46 @@ const TimelineCard = React.memo(({ card }: Props) => {
<GracefullyImage
uri={{ original: card.image }}
blurhash={card.blurhash}
style={styles.left}
imageStyle={styles.image}
style={{ flexBasis: StyleConstants.Font.LineHeight.M * 5 }}
imageStyle={{ borderTopLeftRadius: 6, borderBottomLeftRadius: 6 }}
/>
) : null}
<View style={styles.right}>
<Text
<View style={{ flex: 1, padding: StyleConstants.Spacing.S }}>
<CustomText
fontStyle='S'
numberOfLines={2}
style={[styles.rightTitle, { color: colors.primaryDefault }]}
style={{
marginBottom: StyleConstants.Spacing.XS,
fontWeight: StyleConstants.Font.Weight.Bold,
color: colors.primaryDefault
}}
testID='title'
>
{card.title}
</Text>
</CustomText>
{card.description ? (
<Text
<CustomText
fontStyle='S'
numberOfLines={1}
style={[styles.rightDescription, { color: colors.primaryDefault }]}
style={{
marginBottom: StyleConstants.Spacing.XS,
color: colors.primaryDefault
}}
testID='description'
>
{card.description}
</Text>
</CustomText>
) : null}
<Text
<CustomText
fontStyle='S'
numberOfLines={1}
style={[styles.rightLink, { color: colors.secondary }]}
style={{ color: colors.secondary }}
>
{card.url}
</Text>
</CustomText>
</View>
</Pressable>
)
})
const styles = StyleSheet.create({
card: {
flex: 1,
flexDirection: 'row',
height: StyleConstants.Font.LineHeight.M * 5,
marginTop: StyleConstants.Spacing.M,
borderWidth: StyleSheet.hairlineWidth,
borderRadius: 6,
overflow: 'hidden'
},
left: {
flexBasis: StyleConstants.Font.LineHeight.M * 5
},
image: {
borderTopLeftRadius: 6,
borderBottomLeftRadius: 6
},
right: {
flex: 1,
padding: StyleConstants.Spacing.S
},
rightTitle: {
...StyleConstants.FontStyle.S,
marginBottom: StyleConstants.Spacing.XS,
fontWeight: StyleConstants.Font.Weight.Bold
},
rightDescription: {
...StyleConstants.FontStyle.S,
marginBottom: StyleConstants.Spacing.XS
},
rightLink: {
...StyleConstants.FontStyle.S
}
})
export default TimelineCard

View File

@ -1,4 +1,5 @@
import analytics from '@components/analytics'
import CustomText from '@components/Text'
import { useNavigation } from '@react-navigation/native'
import { StackNavigationProp } from '@react-navigation/stack'
import { TabLocalStackParamList } from '@utils/navigation/navigators'
@ -7,7 +8,7 @@ import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { StyleSheet, Text, View } from 'react-native'
import { StyleSheet, View } from 'react-native'
export interface Props {
status: Pick<
@ -37,7 +38,7 @@ const TimelineFeedback = React.memo(
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
<View style={{ flexDirection: 'row' }}>
{status.reblogs_count > 0 ? (
<Text
<CustomText
accessibilityLabel={t(
'shared.actionsUsers.reblogged_by.accessibilityLabel',
{
@ -64,10 +65,10 @@ const TimelineFeedback = React.memo(
{t('shared.actionsUsers.reblogged_by.text', {
count: status.reblogs_count
})}
</Text>
</CustomText>
) : null}
{status.favourites_count > 0 ? (
<Text
<CustomText
accessibilityLabel={t(
'shared.actionsUsers.favourited_by.accessibilityLabel',
{
@ -94,12 +95,12 @@ const TimelineFeedback = React.memo(
{t('shared.actionsUsers.favourited_by.text', {
count: status.favourites_count
})}
</Text>
</CustomText>
) : null}
</View>
<View>
{data && data.length > 1 ? (
<Text
<CustomText
accessibilityLabel={t(
'shared.actionsUsers.history.accessibilityLabel',
{
@ -121,7 +122,7 @@ const TimelineFeedback = React.memo(
{t('shared.actionsUsers.history.text', {
count: data.length - 1
})}
</Text>
</CustomText>
) : null}
</View>
</View>

View File

@ -1,3 +1,4 @@
import CustomText from '@components/Text'
import { store } from '@root/store'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import { getInstance, getInstanceAccount } from '@utils/slices/instancesSlice'
@ -6,7 +7,7 @@ import { useTheme } from '@utils/styles/ThemeManager'
import htmlparser2 from 'htmlparser2-without-node-native'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { Text, View } from 'react-native'
import { View } from 'react-native'
const TimelineFiltered = React.memo(
() => {
@ -15,9 +16,9 @@ const TimelineFiltered = React.memo(
return (
<View style={{ backgroundColor: colors.backgroundDefault }}>
<Text
<CustomText
fontStyle='S'
style={{
...StyleConstants.FontStyle.S,
color: colors.secondary,
textAlign: 'center',
paddingVertical: StyleConstants.Spacing.S,
@ -25,7 +26,7 @@ const TimelineFiltered = React.memo(
}}
>
{t('shared.filtered')}
</Text>
</CustomText>
</View>
)
},

View File

@ -1,9 +1,9 @@
import CustomText from '@components/Text'
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { Text } from 'react-native'
export interface Props {
queryKey?: QueryKeyTimeline
@ -22,15 +22,15 @@ const TimelineFullConversation = React.memo(
status.mentions.filter(
mention => mention.id !== status.in_reply_to_account_id
).length) ? (
<Text
<CustomText
fontStyle='S'
style={{
...StyleConstants.FontStyle.S,
color: colors.blue,
marginTop: StyleConstants.Spacing.S
}}
>
{t('shared.fullConversation')}
</Text>
</CustomText>
) : null
},
() => true

View File

@ -2,6 +2,7 @@ import analytics from '@components/analytics'
import Icon from '@components/Icon'
import { displayMessage } from '@components/Message'
import { ParseEmojis } from '@components/Parse'
import CustomText from '@components/Text'
import {
QueryKeyTimeline,
useTimelineMutation
@ -10,7 +11,7 @@ import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { Pressable, Text, View } from 'react-native'
import { Pressable, View } from 'react-native'
import { useQueryClient } from 'react-query'
import HeaderSharedCreated from './HeaderShared/Created'
import HeaderSharedMuted from './HeaderShared/Muted'
@ -20,22 +21,22 @@ const Names = ({ accounts }: { accounts: Mastodon.Account[] }) => {
const { colors } = useTheme()
return (
<Text
<CustomText
numberOfLines={1}
style={{ ...StyleConstants.FontStyle.M, color: colors.secondary }}
>
<Text>{t('shared.header.conversation.withAccounts')}</Text>
<CustomText>{t('shared.header.conversation.withAccounts')}</CustomText>
{accounts.map((account, index) => (
<Text key={account.id} numberOfLines={1}>
<CustomText key={account.id} numberOfLines={1}>
{index !== 0 ? t('common:separator') : undefined}
<ParseEmojis
content={account.display_name || account.username}
emojis={account.emojis}
fontBold
/>
</Text>
</CustomText>
))}
</Text>
</CustomText>
)
}

View File

@ -1,9 +1,10 @@
import CustomText from '@components/Text'
import { ParseEmojis } from '@root/components/Parse'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { StyleSheet, Text, View } from 'react-native'
import { View } from 'react-native'
export interface Props {
account: Mastodon.Account
@ -16,13 +17,13 @@ const HeaderSharedAccount = React.memo(
const { colors } = useTheme()
return (
<View style={styles.base}>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
{withoutName ? null : (
<Text
<CustomText
accessibilityHint={t(
'shared.header.shared.account.name.accessibilityHint'
)}
style={styles.name}
style={{ marginRight: StyleConstants.Spacing.XS }}
numberOfLines={1}
>
<ParseEmojis
@ -30,34 +31,21 @@ const HeaderSharedAccount = React.memo(
emojis={account.emojis}
fontBold
/>
</Text>
</CustomText>
)}
<Text
<CustomText
accessibilityHint={t(
'shared.header.shared.account.account.accessibilityHint'
)}
style={[styles.acct, { color: colors.secondary }]}
style={{ flexShrink: 1, color: colors.secondary }}
numberOfLines={1}
>
@{account.acct}
</Text>
</CustomText>
</View>
)
},
() => true
)
const styles = StyleSheet.create({
base: {
flexDirection: 'row',
alignItems: 'center'
},
name: {
marginRight: StyleConstants.Spacing.XS
},
acct: {
flexShrink: 1
}
})
export default HeaderSharedAccount

View File

@ -1,10 +1,10 @@
import analytics from '@components/analytics'
import openLink from '@components/openLink'
import CustomText from '@components/Text'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { StyleSheet, Text } from 'react-native'
export interface Props {
application?: Mastodon.Application
@ -16,7 +16,8 @@ const HeaderSharedApplication = React.memo(
const { t } = useTranslation('componentTimeline')
return application && application.name !== 'Web' ? (
<Text
<CustomText
fontStyle='S'
accessibilityRole='link'
onPress={async () => {
analytics('timeline_shared_header_application_press', {
@ -24,24 +25,20 @@ const HeaderSharedApplication = React.memo(
})
application.website && (await openLink(application.website))
}}
style={[styles.application, { color: colors.secondary }]}
style={{
flex: 1,
marginLeft: StyleConstants.Spacing.S,
color: colors.secondary
}}
numberOfLines={1}
>
{t('shared.header.shared.application', {
application: application.name
})}
</Text>
</CustomText>
) : null
},
() => true
)
const styles = StyleSheet.create({
application: {
flex: 1,
...StyleConstants.FontStyle.S,
marginLeft: StyleConstants.Spacing.S
}
})
export default HeaderSharedApplication

View File

@ -1,13 +1,13 @@
import Icon from '@components/Icon'
import RelativeTime from '@components/RelativeTime'
import CustomText from '@components/Text'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { Text } from 'react-native'
export interface Props {
created_at: Mastodon.Status['created_at']
created_at: Mastodon.Status['created_at'] | number
edited_at?: Mastodon.Status['edited_at']
}
@ -18,11 +18,9 @@ const HeaderSharedCreated = React.memo(
return (
<>
<Text
style={{ ...StyleConstants.FontStyle.S, color: colors.secondary }}
>
<CustomText fontStyle='S' style={{ color: colors.secondary }}>
<RelativeTime date={edited_at || created_at} />
</Text>
</CustomText>
{edited_at ? (
<Icon
accessibilityLabel={t(

View File

@ -5,6 +5,7 @@ import Icon from '@components/Icon'
import { displayMessage } from '@components/Message'
import { ParseEmojis } from '@components/Parse'
import RelativeTime from '@components/RelativeTime'
import CustomText from '@components/Text'
import {
MutationVarsTimelineUpdateStatusProperty,
QueryKeyTimeline,
@ -83,7 +84,7 @@ const TimelinePoll: React.FC<Props> = ({
if (!poll.expired) {
if (!sameAccount && !poll.voted) {
return (
<View style={styles.button}>
<View style={{ marginRight: StyleConstants.Spacing.S }}>
<Button
onPress={() => {
analytics('timeline_shared_vote_vote_press')
@ -110,7 +111,7 @@ const TimelinePoll: React.FC<Props> = ({
)
} else {
return (
<View style={styles.button}>
<View style={{ marginRight: StyleConstants.Spacing.S }}>
<Button
onPress={() => {
analytics('timeline_shared_vote_refresh_press')
@ -147,19 +148,19 @@ const TimelinePoll: React.FC<Props> = ({
const pollExpiration = useMemo(() => {
if (poll.expired) {
return (
<Text style={[styles.expiration, { color: colors.secondary }]}>
<CustomText fontStyle='S' style={{ color: colors.secondary }}>
{t('shared.poll.meta.expiration.expired')}
</Text>
</CustomText>
)
} else {
if (poll.expires_at) {
return (
<Text style={[styles.expiration, { color: colors.secondary }]}>
<CustomText fontStyle='S' style={{ color: colors.secondary }}>
<Trans
i18nKey='componentTimeline:shared.poll.meta.expiration.until'
components={[<RelativeTime date={poll.expires_at} />]}
/>
</Text>
</CustomText>
)
}
}
@ -179,10 +180,17 @@ const TimelinePoll: React.FC<Props> = ({
option => option.votes_count
)?.votes_count
return poll.options.map((option, index) => (
<View key={index} style={styles.optionContainer}>
<View style={styles.optionContent}>
<View
key={index}
style={{ flex: 1, paddingVertical: StyleConstants.Spacing.S }}
>
<View style={{ flex: 1, flexDirection: 'row' }}>
<Icon
style={styles.optionSelection}
style={{
paddingTop:
StyleConstants.Font.LineHeight.M - StyleConstants.Font.Size.M,
marginRight: StyleConstants.Spacing.S
}}
name={
`${poll.own_votes?.includes(index) ? 'Check' : ''}${
poll.multiple ? 'Square' : 'Circle'
@ -193,11 +201,18 @@ const TimelinePoll: React.FC<Props> = ({
poll.own_votes?.includes(index) ? colors.blue : colors.disabled
}
/>
<Text style={styles.optionText}>
<CustomText style={{ flex: 1 }}>
<ParseEmojis content={option.title} emojis={poll.emojis} />
</Text>
<Text
style={[styles.optionPercentage, { color: colors.primaryDefault }]}
</CustomText>
<CustomText
fontStyle='M'
style={{
alignSelf: 'center',
marginLeft: StyleConstants.Spacing.S,
flexBasis: '20%',
textAlign: 'center',
color: colors.primaryDefault
}}
>
{poll.votes_count
? Math.round(
@ -207,21 +222,24 @@ const TimelinePoll: React.FC<Props> = ({
)
: 0}
%
</Text>
</CustomText>
</View>
<View
style={[
styles.background,
{
width: `${Math.round(
(option.votes_count / (poll.voters_count || poll.votes_count)) *
100
)}%`,
backgroundColor:
option.votes_count === maxValue ? colors.blue : colors.disabled
}
]}
style={{
height: StyleConstants.Spacing.XS,
minWidth: 2,
borderTopRightRadius: 10,
borderBottomRightRadius: 10,
marginTop: StyleConstants.Spacing.XS,
marginBottom: StyleConstants.Spacing.S,
width: `${Math.round(
(option.votes_count / (poll.voters_count || poll.votes_count)) *
100
)}%`,
backgroundColor:
option.votes_count === maxValue ? colors.blue : colors.disabled
}}
/>
</View>
))
@ -230,7 +248,7 @@ const TimelinePoll: React.FC<Props> = ({
return poll.options.map((option, index) => (
<Pressable
key={index}
style={styles.optionContainer}
style={{ flex: 1, paddingVertical: StyleConstants.Spacing.S }}
onPress={() => {
analytics('timeline_shared_vote_option_press')
!allOptions[index] && haptics('Light')
@ -253,16 +271,20 @@ const TimelinePoll: React.FC<Props> = ({
}
}}
>
<View style={[styles.optionContent]}>
<View style={{ flex: 1, flexDirection: 'row' }}>
<Icon
style={styles.optionSelection}
style={{
paddingTop:
StyleConstants.Font.LineHeight.M - StyleConstants.Font.Size.M,
marginRight: StyleConstants.Spacing.S
}}
name={isSelected(index)}
size={StyleConstants.Font.Size.M}
color={colors.primaryDefault}
/>
<Text style={styles.optionText}>
<CustomText style={{ flex: 1 }}>
<ParseEmojis content={option.title} emojis={poll.emojis} />
</Text>
</CustomText>
</View>
</Pressable>
))
@ -271,25 +293,32 @@ const TimelinePoll: React.FC<Props> = ({
const pollVoteCounts = useMemo(() => {
if (poll.voters_count !== null) {
return (
<Text style={[styles.votes, { color: colors.secondary }]}>
<CustomText fontStyle='S' style={{ color: colors.secondary }}>
{t('shared.poll.meta.count.voters', { count: poll.voters_count })}
{' • '}
</Text>
</CustomText>
)
} else if (poll.votes_count !== null) {
return (
<Text style={[styles.votes, { color: colors.secondary }]}>
<CustomText fontStyle='S' style={{ color: colors.secondary }}>
{t('shared.poll.meta.count.votes', { count: poll.votes_count })}
{' • '}
</Text>
</CustomText>
)
}
}, [poll.voters_count, poll.votes_count])
return (
<View style={styles.base}>
<View style={{ marginTop: StyleConstants.Spacing.M }}>
{poll.expired || poll.voted ? pollBodyDisallow : pollBodyAllow}
<View style={styles.meta}>
<View
style={{
flex: 1,
flexDirection: 'row',
alignItems: 'center',
marginTop: StyleConstants.Spacing.XS
}}
>
{pollButton}
{pollVoteCounts}
{pollExpiration}
@ -298,55 +327,4 @@ const TimelinePoll: React.FC<Props> = ({
)
}
const styles = StyleSheet.create({
base: {
marginTop: StyleConstants.Spacing.M
},
optionContainer: {
flex: 1,
paddingVertical: StyleConstants.Spacing.S
},
optionContent: {
flex: 1,
flexDirection: 'row'
},
optionText: {
flex: 1
},
optionSelection: {
paddingTop: StyleConstants.Font.LineHeight.M - StyleConstants.Font.Size.M,
marginRight: StyleConstants.Spacing.S
},
optionPercentage: {
...StyleConstants.FontStyle.M,
alignSelf: 'center',
marginLeft: StyleConstants.Spacing.S,
flexBasis: '20%',
textAlign: 'center'
},
background: {
height: StyleConstants.Spacing.XS,
minWidth: 2,
borderTopRightRadius: 10,
borderBottomRightRadius: 10,
marginTop: StyleConstants.Spacing.XS,
marginBottom: StyleConstants.Spacing.S
},
meta: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
marginTop: StyleConstants.Spacing.XS
},
button: {
marginRight: StyleConstants.Spacing.S
},
votes: {
...StyleConstants.FontStyle.S
},
expiration: {
...StyleConstants.FontStyle.S
}
})
export default TimelinePoll

View File

@ -1,5 +1,6 @@
import analytics from '@components/analytics'
import { ParseHTML } from '@components/Parse'
import CustomText from '@components/Text'
import { useTranslateQuery } from '@utils/queryHooks/translate'
import { getSettingsLanguage } from '@utils/slices/settingsSlice'
import { StyleConstants } from '@utils/styles/constants'
@ -7,7 +8,7 @@ import { useTheme } from '@utils/styles/ThemeManager'
import * as Localization from 'expo-localization'
import React, { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Pressable, Text } from 'react-native'
import { Pressable } from 'react-native'
import { Circle } from 'react-native-animated-spinkit'
import { useSelector } from 'react-redux'
@ -85,9 +86,9 @@ const TimelineTranslate = React.memo(
}
}}
>
<Text
<CustomText
fontStyle='M'
style={{
...StyleConstants.FontStyle.M,
color:
isLoading || isSuccess
? colors.secondary
@ -106,14 +107,14 @@ const TimelineTranslate = React.memo(
source: data?.sourceLanguage
})
: t('shared.translate.default')}
</Text>
<Text>
</CustomText>
<CustomText>
{__DEV__
? ` Source: ${status.language}; Target: ${
Localization.locale || settingsLanguage || 'en'
}`
: undefined}
</Text>
</CustomText>
{isLoading ? (
<Circle
size={StyleConstants.Font.Size.M}

View File

@ -165,7 +165,8 @@
"content": {
"accessibilityHint": "Saved draft, tap to edit this draft",
"textEmpty": "Content empty"
}
},
"checkAttachment": "Checking attachments on the server..."
}
}
}

View File

@ -3,6 +3,7 @@ import Button from '@components/Button'
import haptics from '@components/haptics'
import { ParseHTML } from '@components/Parse'
import RelativeTime from '@components/RelativeTime'
import CustomText from '@components/Text'
import { BlurView } from '@react-native-community/blur'
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
import { RootStackScreenProps } from '@utils/navigation/navigators'
@ -14,14 +15,7 @@ import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback, useEffect, useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import {
Dimensions,
Platform,
Pressable,
StyleSheet,
Text,
View
} from 'react-native'
import { Dimensions, Platform, Pressable, StyleSheet, View } from 'react-native'
import { Circle } from 'react-native-animated-spinkit'
import FastImage from 'react-native-fast-image'
import { FlatList, ScrollView } from 'react-native-gesture-handler'
@ -64,27 +58,48 @@ const ScreenAnnouncements: React.FC<
const renderItem = useCallback(
({ item, index }: { item: Mastodon.Announcement; index: number }) => (
<View key={index} style={styles.announcementContainer}>
<View
key={index}
style={{
width: Dimensions.get('screen').width,
padding: StyleConstants.Spacing.Global.PagePadding,
marginVertical: StyleConstants.Spacing.Global.PagePadding,
justifyContent: 'center'
}}
>
<Pressable
style={styles.pressable}
style={StyleSheet.absoluteFillObject}
onPress={() => navigation.goBack()}
/>
<View
style={[
styles.announcement,
{
borderColor: colors.primaryDefault,
backgroundColor: colors.backgroundDefault
}
]}
style={{
flexShrink: 1,
padding: StyleConstants.Spacing.Global.PagePadding,
marginTop: StyleConstants.Spacing.Global.PagePadding,
borderWidth: 1,
borderRadius: 6,
borderColor: colors.primaryDefault,
backgroundColor: colors.backgroundDefault
}}
>
<Text style={[styles.published, { color: colors.secondary }]}>
<CustomText
fontStyle='S'
style={{
marginBottom: StyleConstants.Spacing.S,
color: colors.secondary
}}
>
<Trans
i18nKey='screenAnnouncements:content.published'
components={[<RelativeTime date={item.published_at} />]}
/>
</Text>
<ScrollView style={styles.scrollView} showsVerticalScrollIndicator>
</CustomText>
<ScrollView
style={{
marginBottom: StyleConstants.Spacing.Global.PagePadding / 2
}}
showsVerticalScrollIndicator
>
<ParseHTML
content={item.content}
size='M'
@ -95,21 +110,31 @@ const ScreenAnnouncements: React.FC<
/>
</ScrollView>
{item.reactions?.length ? (
<View style={styles.reactions}>
<View
style={{
flexDirection: 'row',
flexWrap: 'wrap',
marginBottom: StyleConstants.Spacing.Global.PagePadding / 2
}}
>
{item.reactions?.map(reaction => (
<Pressable
key={reaction.name}
style={[
styles.reaction,
{
borderColor: reaction.me
? colors.disabled
: colors.primaryDefault,
backgroundColor: reaction.me
? colors.disabled
: colors.backgroundDefault
}
]}
style={{
borderWidth: 1,
padding: StyleConstants.Spacing.Global.PagePadding / 2,
marginTop: StyleConstants.Spacing.Global.PagePadding / 2,
marginBottom: StyleConstants.Spacing.Global.PagePadding / 2,
marginRight: StyleConstants.Spacing.M,
borderRadius: 6,
flexDirection: 'row',
borderColor: reaction.me
? colors.disabled
: colors.primaryDefault,
backgroundColor: reaction.me
? colors.disabled
: colors.backgroundDefault
}}
onPress={() => {
analytics('accnouncement_reaction_press', {
current: reaction.me
@ -129,20 +154,24 @@ const ScreenAnnouncements: React.FC<
? reaction.static_url
: reaction.url
}}
style={[styles.reactionImage]}
style={{
width: StyleConstants.Font.LineHeight.M + 3,
height: StyleConstants.Font.LineHeight.M
}}
/>
) : (
<Text style={[styles.reactionText]}>{reaction.name}</Text>
<CustomText fontStyle='M'>{reaction.name}</CustomText>
)}
{reaction.count ? (
<Text
style={[
styles.reactionCount,
{ color: colors.primaryDefault }
]}
<CustomText
fontStyle='S'
style={{
marginLeft: StyleConstants.Spacing.S,
color: colors.primaryDefault
}}
>
{reaction.count}
</Text>
</CustomText>
) : null}
</Pressable>
))}
@ -210,10 +239,10 @@ const ScreenAnnouncements: React.FC<
<BlurView
blurType={mode}
blurAmount={20}
style={styles.base}
style={{ flex: 1 }}
reducedTransparencyFallbackColor={colors.backgroundDefault}
>
<SafeAreaView style={styles.base}>
<SafeAreaView style={{ flex: 1 }}>
<FlatList
horizontal
data={query.data}
@ -223,22 +252,30 @@ const ScreenAnnouncements: React.FC<
onMomentumScrollEnd={onMomentumScrollEnd}
ListEmptyComponent={ListEmptyComponent}
/>
<View style={styles.indicators}>
<View
style={{
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
minHeight: 49
}}
>
{query.data && query.data.length > 1 ? (
<>
{query.data.map((d, i) => (
<View
key={i}
style={[
styles.indicator,
{
borderColor: colors.primaryDefault,
backgroundColor:
i === index ? colors.primaryDefault : undefined,
marginLeft:
i === query.data.length ? 0 : StyleConstants.Spacing.S
}
]}
style={{
width: StyleConstants.Spacing.S,
height: StyleConstants.Spacing.S,
borderRadius: StyleConstants.Spacing.S,
borderWidth: 1,
borderColor: colors.primaryDefault,
backgroundColor:
i === index ? colors.primaryDefault : undefined,
marginLeft:
i === query.data.length ? 0 : StyleConstants.Spacing.S
}}
/>
))}
</>
@ -248,7 +285,7 @@ const ScreenAnnouncements: React.FC<
</BlurView>
) : (
<SafeAreaView
style={[styles.base, { backgroundColor: colors.backgroundDefault }]}
style={{ flex: 1, backgroundColor: colors.backgroundDefault }}
>
<FlatList
horizontal
@ -259,22 +296,30 @@ const ScreenAnnouncements: React.FC<
onMomentumScrollEnd={onMomentumScrollEnd}
ListEmptyComponent={ListEmptyComponent}
/>
<View style={styles.indicators}>
<View
style={{
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
minHeight: 49
}}
>
{query.data && query.data.length > 1 ? (
<>
{query.data.map((d, i) => (
<View
key={i}
style={[
styles.indicator,
{
borderColor: colors.primaryDefault,
backgroundColor:
i === index ? colors.primaryDefault : undefined,
marginLeft:
i === query.data.length ? 0 : StyleConstants.Spacing.S
}
]}
style={{
width: StyleConstants.Spacing.S,
height: StyleConstants.Spacing.S,
borderRadius: StyleConstants.Spacing.S,
borderWidth: 1,
borderColor: colors.primaryDefault,
backgroundColor:
i === index ? colors.primaryDefault : undefined,
marginLeft:
i === query.data.length ? 0 : StyleConstants.Spacing.S
}}
/>
))}
</>
@ -284,69 +329,4 @@ const ScreenAnnouncements: React.FC<
)
}
const styles = StyleSheet.create({
base: {
flex: 1
},
invisibleTextInput: { ...StyleSheet.absoluteFillObject },
announcementContainer: {
width: Dimensions.get('screen').width,
padding: StyleConstants.Spacing.Global.PagePadding,
marginVertical: StyleConstants.Spacing.Global.PagePadding,
justifyContent: 'center'
},
published: {
...StyleConstants.FontStyle.S,
marginBottom: StyleConstants.Spacing.S
},
pressable: { ...StyleSheet.absoluteFillObject },
announcement: {
flexShrink: 1,
padding: StyleConstants.Spacing.Global.PagePadding,
marginTop: StyleConstants.Spacing.Global.PagePadding,
borderWidth: 1,
borderRadius: 6
},
scrollView: {
marginBottom: StyleConstants.Spacing.Global.PagePadding / 2
},
reactions: {
flexDirection: 'row',
flexWrap: 'wrap',
marginBottom: StyleConstants.Spacing.Global.PagePadding / 2
},
reaction: {
borderWidth: 1,
padding: StyleConstants.Spacing.Global.PagePadding / 2,
marginTop: StyleConstants.Spacing.Global.PagePadding / 2,
marginBottom: StyleConstants.Spacing.Global.PagePadding / 2,
marginRight: StyleConstants.Spacing.M,
borderRadius: 6,
flexDirection: 'row'
},
reactionImage: {
width: StyleConstants.Font.LineHeight.M + 3,
height: StyleConstants.Font.LineHeight.M
},
reactionText: {
...StyleConstants.FontStyle.M
},
reactionCount: {
...StyleConstants.FontStyle.S,
marginLeft: StyleConstants.Spacing.S
},
indicators: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
minHeight: 49
},
indicator: {
width: StyleConstants.Spacing.S,
height: StyleConstants.Spacing.S,
borderRadius: StyleConstants.Spacing.S,
borderWidth: 1
}
})
export default ScreenAnnouncements

View File

@ -1,6 +1,7 @@
import apiInstance from '@api/instance'
import Icon from '@components/Icon'
import ComponentSeparator from '@components/Separator'
import CustomText from '@components/Text'
import HeaderSharedCreated from '@components/Timeline/Shared/HeaderShared/Created'
import { useNavigation } from '@react-navigation/native'
import { useAppDispatch } from '@root/store'
@ -18,8 +19,6 @@ import {
Modal,
Platform,
Pressable,
StyleSheet,
Text,
View
} from 'react-native'
import { PanGestureHandler } from 'react-native-gesture-handler'
@ -54,10 +53,15 @@ const ComposeDraftsListRoot: React.FC<Props> = ({ timestamp }) => {
const renderItem = useCallback(
({ item }: { item: ComposeStateDraft }) => {
console.log('timestamp', item.timestamp)
return (
<Pressable
accessibilityHint={t('content.draftsList.content.accessibilityHint')}
style={[styles.draft, { backgroundColor: colors.backgroundDefault }]}
style={{
flex: 1,
padding: StyleConstants.Spacing.Global.PagePadding,
backgroundColor: colors.backgroundDefault
}}
onPress={async () => {
setCheckingAttachments(true)
let tempDraft = item
@ -103,23 +107,42 @@ const ComposeDraftsListRoot: React.FC<Props> = ({ timestamp }) => {
>
<View style={{ flex: 1 }}>
<HeaderSharedCreated created_at={item.timestamp} />
<Text
<CustomText
fontStyle='M'
numberOfLines={2}
style={[styles.text, { color: colors.primaryDefault }]}
style={{
marginTop: StyleConstants.Spacing.XS,
color: colors.primaryDefault
}}
>
{item.text ||
item.spoiler ||
t('content.draftsList.content.textEmpty')}
</Text>
</CustomText>
{item.attachments?.uploads.length ? (
<View style={styles.attachments}>
<View
style={{
flex: 1,
flexDirection: 'row',
marginTop: StyleConstants.Spacing.S
}}
>
{item.attachments.uploads.map((attachment, index) => (
<Image
key={index}
style={[
styles.attachment,
{ marginLeft: index !== 0 ? StyleConstants.Spacing.S : 0 }
]}
style={{
width:
(Dimensions.get('screen').width -
StyleConstants.Spacing.Global.PagePadding * 2 -
StyleConstants.Spacing.S * 3) /
4,
height:
(Dimensions.get('screen').width -
StyleConstants.Spacing.Global.PagePadding * 2 -
StyleConstants.Spacing.S * 3) /
4,
marginLeft: index !== 0 ? StyleConstants.Spacing.S : 0
}}
source={{
uri:
attachment.local?.local_thumbnail ||
@ -138,10 +161,21 @@ const ComposeDraftsListRoot: React.FC<Props> = ({ timestamp }) => {
const renderHiddenItem = useCallback(
({ item }) => (
<View
style={[styles.hiddenBase, { backgroundColor: colors.red }]}
style={{
flex: 1,
flexDirection: 'row',
justifyContent: 'flex-end',
backgroundColor: colors.red
}}
children={
<Pressable
style={styles.action}
style={{
flexBasis:
StyleConstants.Font.Size.L +
StyleConstants.Spacing.Global.PagePadding * 4,
justifyContent: 'center',
alignItems: 'center'
}}
onPress={() => removeDraft(item.timestamp)}
children={
<Icon
@ -183,17 +217,17 @@ const ComposeDraftsListRoot: React.FC<Props> = ({ timestamp }) => {
visible={checkingAttachments}
children={
<View
style={[
styles.modal,
{ backgroundColor: colors.backgroundOverlayInvert }
]}
style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: colors.backgroundOverlayInvert
}}
children={
<Text
children='检查附件在服务器的状态…'
style={{
...StyleConstants.FontStyle.M,
color: colors.primaryOverlay
}}
<CustomText
fontStyle='M'
children={t('content.draftsList.checkAttachment')}
style={{ color: colors.primaryOverlay }}
/>
}
/>
@ -203,49 +237,4 @@ const ComposeDraftsListRoot: React.FC<Props> = ({ timestamp }) => {
)
}
const styles = StyleSheet.create({
draft: {
flex: 1,
padding: StyleConstants.Spacing.Global.PagePadding
},
text: {
marginTop: StyleConstants.Spacing.XS,
...StyleConstants.FontStyle.M
},
attachments: {
flex: 1,
flexDirection: 'row',
marginTop: StyleConstants.Spacing.S
},
attachment: {
width:
(Dimensions.get('screen').width -
StyleConstants.Spacing.Global.PagePadding * 2 -
StyleConstants.Spacing.S * 3) /
4,
height:
(Dimensions.get('screen').width -
StyleConstants.Spacing.Global.PagePadding * 2 -
StyleConstants.Spacing.S * 3) /
4
},
hiddenBase: {
flex: 1,
flexDirection: 'row',
justifyContent: 'flex-end'
},
action: {
flexBasis:
StyleConstants.Font.Size.L +
StyleConstants.Spacing.Global.PagePadding * 4,
justifyContent: 'center',
alignItems: 'center'
},
modal: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}
})
export default ComposeDraftsListRoot

View File

@ -1,9 +1,10 @@
import CustomText from '@components/Text'
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useContext } from 'react'
import { useTranslation } from 'react-i18next'
import { Dimensions, Image, StyleSheet, Text, View } from 'react-native'
import { Dimensions, Image, View } from 'react-native'
import { PanGestureHandler } from 'react-native-gesture-handler'
import Animated, {
Extrapolate,
@ -120,7 +121,7 @@ const ComposeEditAttachmentImage: React.FC<Props> = ({ index }) => {
return (
<>
<View style={styles.base}>
<View style={{ overflow: 'hidden', flex: 1, alignItems: 'center' }}>
<Image
style={{
width: imageDimensionis.width,
@ -168,20 +169,18 @@ const ComposeEditAttachmentImage: React.FC<Props> = ({ index }) => {
</PanGestureHandler>
</View>
{screenReaderEnabled ? null : (
<Text style={[styles.imageFocusText, { color: colors.primaryDefault }]}>
<CustomText
fontStyle='M'
style={{
padding: StyleConstants.Spacing.Global.PagePadding,
color: colors.primaryDefault
}}
>
{t('content.editAttachment.content.imageFocus')}
</Text>
</CustomText>
)}
</>
)
}
const styles = StyleSheet.create({
base: { overflow: 'hidden', flex: 1, alignItems: 'center' },
imageFocusText: {
...StyleConstants.FontStyle.M,
padding: StyleConstants.Spacing.Global.PagePadding
}
})
export default ComposeEditAttachmentImage

View File

@ -1,9 +1,10 @@
import CustomText from '@components/Text'
import AttachmentVideo from '@components/Timeline/Shared/Attachment/Video'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useContext, useMemo, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { ScrollView, StyleSheet, Text, TextInput, View } from 'react-native'
import { ScrollView, StyleSheet, TextInput, View } from 'react-native'
import ComposeContext from '../utils/createContext'
import ComposeEditAttachmentImage from './Image'
@ -60,17 +61,28 @@ const ComposeEditAttachmentRoot: React.FC<Props> = ({ index }) => {
return (
<ScrollView ref={scrollViewRef}>
{mediaDisplay}
<View style={styles.altTextContainer}>
<Text
style={[styles.altTextInputHeading, { color: colors.primaryDefault }]}
<View style={{ padding: StyleConstants.Spacing.Global.PagePadding }}>
<CustomText
fontStyle='M'
style={{
fontWeight: StyleConstants.Font.Weight.Bold,
color: colors.primaryDefault
}}
>
{t('content.editAttachment.content.altText.heading')}
</Text>
</CustomText>
<TextInput
style={[
styles.altTextInput,
{ borderColor: colors.border, color: colors.primaryDefault }
]}
style={{
height: 200,
...StyleConstants.FontStyle.M,
marginTop: StyleConstants.Spacing.M,
marginBottom: StyleConstants.Spacing.S,
padding: StyleConstants.Spacing.Global.PagePadding,
paddingTop: StyleConstants.Spacing.S * 1.5,
borderWidth: StyleSheet.hairlineWidth,
borderColor: colors.border,
color: colors.primaryDefault
}}
onFocus={() => scrollViewRef.current?.scrollToEnd()}
autoCapitalize='none'
autoCorrect={false}
@ -83,35 +95,20 @@ const ComposeEditAttachmentRoot: React.FC<Props> = ({ index }) => {
value={theAttachment.description}
keyboardAppearance={mode}
/>
<Text style={[styles.altTextLength, { color: colors.secondary }]}>
<CustomText
fontStyle='S'
style={{
textAlign: 'right',
marginRight: StyleConstants.Spacing.S,
marginBottom: StyleConstants.Spacing.M,
color: colors.secondary
}}
>
{theAttachment.description?.length || 0} / 1500
</Text>
</CustomText>
</View>
</ScrollView>
)
}
const styles = StyleSheet.create({
altTextContainer: { padding: StyleConstants.Spacing.Global.PagePadding },
altTextInputHeading: {
...StyleConstants.FontStyle.M,
fontWeight: StyleConstants.Font.Weight.Bold
},
altTextInput: {
height: 200,
...StyleConstants.FontStyle.M,
marginTop: StyleConstants.Spacing.M,
marginBottom: StyleConstants.Spacing.S,
padding: StyleConstants.Spacing.Global.PagePadding,
paddingTop: StyleConstants.Spacing.S * 1.5,
borderWidth: StyleSheet.hairlineWidth
},
altTextLength: {
textAlign: 'right',
marginRight: StyleConstants.Spacing.S,
...StyleConstants.FontStyle.S,
marginBottom: StyleConstants.Spacing.M
}
})
export default ComposeEditAttachmentRoot

View File

@ -2,6 +2,7 @@ import analytics from '@components/analytics'
import Button from '@components/Button'
import haptics from '@components/haptics'
import Icon from '@components/Icon'
import CustomText from '@components/Text'
import { useActionSheet } from '@expo/react-native-action-sheet'
import { useNavigation } from '@react-navigation/native'
import { StyleConstants } from '@utils/styles/constants'
@ -16,14 +17,7 @@ import React, {
useRef
} from 'react'
import { useTranslation } from 'react-i18next'
import {
FlatList,
Image,
Pressable,
StyleSheet,
Text,
View
} from 'react-native'
import { FlatList, Image, Pressable, StyleSheet, View } from 'react-native'
import { Circle } from 'react-native-animated-spinkit'
import ComposeContext from '../../utils/createContext'
import { ExtendedAttachment } from '../../utils/types'
@ -122,33 +116,46 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
return (
<View
key={index}
style={[styles.container, { width: calculateWidth(item) }]}
style={{
height: DEFAULT_HEIGHT,
marginLeft: StyleConstants.Spacing.Global.PagePadding,
marginTop: StyleConstants.Spacing.Global.PagePadding,
marginBottom: StyleConstants.Spacing.Global.PagePadding,
width: calculateWidth(item)
}}
>
<Image
style={styles.image}
style={{ width: '100%', height: '100%' }}
source={{
uri: item.local?.local_thumbnail || item.remote?.preview_url
}}
/>
{item.remote?.meta?.original?.duration ? (
<Text
style={[
styles.duration,
{
color: colors.backgroundDefault,
backgroundColor: colors.backgroundOverlayInvert
}
]}
<CustomText
fontStyle='S'
style={{
position: 'absolute',
bottom: StyleConstants.Spacing.S,
left: StyleConstants.Spacing.S,
paddingLeft: StyleConstants.Spacing.S,
paddingRight: StyleConstants.Spacing.S,
paddingTop: StyleConstants.Spacing.XS,
paddingBottom: StyleConstants.Spacing.XS,
color: colors.backgroundDefault,
backgroundColor: colors.backgroundOverlayInvert
}}
>
{item.remote.meta.original.duration}
</Text>
</CustomText>
) : null}
{item.uploading ? (
<View
style={[
styles.uploading,
{ backgroundColor: colors.backgroundOverlayInvert }
]}
style={{
...StyleSheet.absoluteFillObject,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: colors.backgroundOverlayInvert
}}
>
<Circle
size={StyleConstants.Font.Size.L}
@ -156,7 +163,15 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
/>
</View>
) : (
<View style={styles.actions}>
<View
style={{
...StyleSheet.absoluteFillObject,
justifyContent: 'space-between',
alignContent: 'flex-end',
alignItems: 'flex-end',
padding: StyleConstants.Spacing.S
}}
>
<Button
accessibilityLabel={t(
'content.root.footer.attachments.remove.accessibilityLabel',
@ -209,16 +224,20 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
accessibilityLabel={t(
'content.root.footer.attachments.upload.accessibilityLabel'
)}
style={[
styles.container,
{
width: DEFAULT_HEIGHT,
backgroundColor: colors.backgroundOverlayInvert
}
]}
style={{
height: DEFAULT_HEIGHT,
marginLeft: StyleConstants.Spacing.Global.PagePadding,
marginTop: StyleConstants.Spacing.Global.PagePadding,
marginBottom: StyleConstants.Spacing.Global.PagePadding,
width: DEFAULT_HEIGHT,
backgroundColor: colors.backgroundOverlayInvert
}}
onPress={async () => {
analytics('compose_attachment_add_container_press')
await chooseAndUploadAttachment({ composeDispatch, showActionSheetWithOptions })
await chooseAndUploadAttachment({
composeDispatch,
showActionSheetWithOptions
})
}}
>
<Button
@ -229,7 +248,10 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
overlay
onPress={async () => {
analytics('compose_attachment_add_button_press')
await chooseAndUploadAttachment({ composeDispatch, showActionSheetWithOptions })
await chooseAndUploadAttachment({
composeDispatch,
showActionSheetWithOptions
})
}}
style={{
position: 'absolute',
@ -250,16 +272,38 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
[]
)
return (
<View style={styles.base} ref={accessibleRefAttachments} accessible>
<Pressable style={styles.sensitive} onPress={sensitiveOnPress}>
<View
style={{
flex: 1,
marginRight: StyleConstants.Spacing.Global.PagePadding,
marginTop: StyleConstants.Spacing.M
}}
ref={accessibleRefAttachments}
accessible
>
<Pressable
style={{
flex: 1,
flexDirection: 'row',
alignItems: 'center',
marginLeft: StyleConstants.Spacing.Global.PagePadding
}}
onPress={sensitiveOnPress}
>
<Icon
name={composeState.attachments.sensitive ? 'CheckCircle' : 'Circle'}
size={StyleConstants.Font.Size.L}
color={colors.primaryDefault}
/>
<Text style={[styles.sensitiveText, { color: colors.primaryDefault }]}>
<CustomText
fontStyle='M'
style={{
marginLeft: StyleConstants.Spacing.S,
color: colors.primaryDefault
}}
>
{t('content.root.footer.attachments.sensitive')}
</Text>
</CustomText>
</Pressable>
<FlatList
horizontal
@ -283,54 +327,4 @@ const ComposeAttachments: React.FC<Props> = ({ accessibleRefAttachments }) => {
)
}
const styles = StyleSheet.create({
base: {
flex: 1,
marginRight: StyleConstants.Spacing.Global.PagePadding,
marginTop: StyleConstants.Spacing.M
},
sensitive: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
marginLeft: StyleConstants.Spacing.Global.PagePadding
},
sensitiveText: {
...StyleConstants.FontStyle.M,
marginLeft: StyleConstants.Spacing.S
},
container: {
height: DEFAULT_HEIGHT,
marginLeft: StyleConstants.Spacing.Global.PagePadding,
marginTop: StyleConstants.Spacing.Global.PagePadding,
marginBottom: StyleConstants.Spacing.Global.PagePadding
},
image: {
width: '100%',
height: '100%'
},
duration: {
position: 'absolute',
bottom: StyleConstants.Spacing.S,
left: StyleConstants.Spacing.S,
...StyleConstants.FontStyle.S,
paddingLeft: StyleConstants.Spacing.S,
paddingRight: StyleConstants.Spacing.S,
paddingTop: StyleConstants.Spacing.XS,
paddingBottom: StyleConstants.Spacing.XS
},
uploading: {
...StyleSheet.absoluteFillObject,
justifyContent: 'center',
alignItems: 'center'
},
actions: {
...StyleSheet.absoluteFillObject,
justifyContent: 'space-between',
alignContent: 'flex-end',
alignItems: 'flex-end',
padding: StyleConstants.Spacing.S
}
})
export default React.memo(ComposeAttachments, () => true)

View File

@ -1,4 +1,5 @@
import haptics from '@components/haptics'
import CustomText from '@components/Text'
import { useAppDispatch } from '@root/store'
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
import { countInstanceEmoji } from '@utils/slices/instancesSlice'
@ -11,8 +12,6 @@ import {
findNodeHandle,
Pressable,
SectionList,
StyleSheet,
Text,
View
} from 'react-native'
import FastImage from 'react-native-fast-image'
@ -40,7 +39,16 @@ const ComposeEmojis: React.FC<Props> = ({ accessibleRefEmojis }) => {
const listHeader = useCallback(
({ section: { title } }) => (
<Text style={[styles.group, { color: colors.secondary }]}>{title}</Text>
<CustomText
fontStyle='S'
style={{
position: 'absolute',
left: StyleConstants.Spacing.L,
color: colors.secondary
}}
>
{title}
</CustomText>
),
[]
)
@ -48,7 +56,15 @@ const ComposeEmojis: React.FC<Props> = ({ accessibleRefEmojis }) => {
const listItem = useCallback(
({ index, item }: { item: Mastodon.Emoji[]; index: number }) => {
return (
<View key={index} style={styles.emojis}>
<View
key={index}
style={{
flex: 1,
flexWrap: 'wrap',
marginTop: StyleConstants.Spacing.M,
marginLeft: StyleConstants.Spacing.M
}}
>
{item.map(emoji => {
const uri = reduceMotionEnabled ? emoji.static_url : emoji.url
if (validUrl.isHttpsUri(uri)) {
@ -77,7 +93,12 @@ const ComposeEmojis: React.FC<Props> = ({ accessibleRefEmojis }) => {
'screenCompose:content.root.footer.emojis.accessibilityHint'
)}
source={{ uri }}
style={styles.emoji}
style={{
width: 32,
height: 32,
padding: StyleConstants.Spacing.S,
margin: StyleConstants.Spacing.S
}}
/>
</Pressable>
)
@ -92,7 +113,15 @@ const ComposeEmojis: React.FC<Props> = ({ accessibleRefEmojis }) => {
)
return (
<View style={styles.base}>
<View
style={{
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'space-around',
height: 260
}}
>
<SectionList
accessible
ref={accessibleRefEmojis}
@ -108,31 +137,4 @@ const ComposeEmojis: React.FC<Props> = ({ accessibleRefEmojis }) => {
)
}
const styles = StyleSheet.create({
base: {
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'space-around',
height: 260
},
group: {
position: 'absolute',
left: StyleConstants.Spacing.L,
...StyleConstants.FontStyle.S
},
emojis: {
flex: 1,
flexWrap: 'wrap',
marginTop: StyleConstants.Spacing.M,
marginLeft: StyleConstants.Spacing.M
},
emoji: {
width: 32,
height: 32,
padding: StyleConstants.Spacing.S,
margin: StyleConstants.Spacing.S
}
})
export default React.memo(ComposeEmojis, () => true)

View File

@ -2,13 +2,14 @@ import analytics from '@components/analytics'
import Button from '@components/Button'
import Icon from '@components/Icon'
import { MenuRow } from '@components/Menu'
import CustomText from '@components/Text'
import { useActionSheet } from '@expo/react-native-action-sheet'
import { getInstanceConfigurationPoll } from '@utils/slices/instancesSlice'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useContext, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { StyleSheet, Text, TextInput, View } from 'react-native'
import { StyleSheet, TextInput, View } from 'react-native'
import { useSelector } from 'react-redux'
import ComposeContext from '../../utils/createContext'
@ -39,8 +40,21 @@ const ComposePoll: React.FC = () => {
}, [])
return (
<View style={[styles.base, { borderColor: colors.border }]}>
<View style={styles.options}>
<View
style={{
flex: 1,
borderWidth: StyleSheet.hairlineWidth,
borderRadius: 6,
margin: StyleConstants.Spacing.Global.PagePadding,
borderColor: colors.border
}}
>
<View
style={{
marginTop: StyleConstants.Spacing.M,
marginBottom: StyleConstants.Spacing.S
}}
>
{[...Array(total)].map((e, i) => {
const restOptions = Object.keys(options).filter(
o => parseInt(o) !== i && parseInt(o) < total
@ -66,13 +80,16 @@ const ComposePoll: React.FC = () => {
)}
keyboardAppearance={mode}
{...(i === 0 && firstRender && { autoFocus: true })}
style={[
styles.textInput,
{
borderColor: colors.border,
color: hasConflict ? colors.red : colors.primaryDefault
}
]}
style={{
flex: 1,
padding: StyleConstants.Spacing.S,
borderWidth: StyleSheet.hairlineWidth,
borderRadius: 6,
...StyleConstants.FontStyle.M,
marginLeft: StyleConstants.Spacing.S,
borderColor: colors.border,
color: hasConflict ? colors.red : colors.primaryDefault
}}
placeholder={
multiple
? t('content.root.footer.poll.option.placeholder.multiple')
@ -93,7 +110,15 @@ const ComposePoll: React.FC = () => {
)
})}
</View>
<View style={styles.controlAmount}>
<View
style={{
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-end',
marginRight: StyleConstants.Spacing.M
}}
>
<Button
{...(total > 2
? {
@ -121,9 +146,14 @@ const ComposePoll: React.FC = () => {
round
disabled={!(total > 2)}
/>
<Text style={[styles.controlCount, { color: colors.secondary }]}>
<CustomText
style={{
marginHorizontal: StyleConstants.Spacing.S,
color: colors.secondary
}}
>
{total} / {MAX_OPTIONS}
</Text>
</CustomText>
<Button
{...(total < MAX_OPTIONS
? {
@ -152,7 +182,9 @@ const ComposePoll: React.FC = () => {
disabled={!(total < MAX_OPTIONS)}
/>
</View>
<View style={styles.controlOptions}>
<View
style={{ paddingHorizontal: StyleConstants.Spacing.Global.PagePadding }}
>
<MenuRow
title={t('content.root.footer.poll.multiple.heading')}
content={
@ -238,43 +270,12 @@ const ComposePoll: React.FC = () => {
}
const styles = StyleSheet.create({
base: {
flex: 1,
borderWidth: StyleSheet.hairlineWidth,
borderRadius: 6,
margin: StyleConstants.Spacing.Global.PagePadding
},
options: {
marginTop: StyleConstants.Spacing.M,
marginBottom: StyleConstants.Spacing.S
},
option: {
marginLeft: StyleConstants.Spacing.M,
marginRight: StyleConstants.Spacing.M,
marginBottom: StyleConstants.Spacing.S,
flexDirection: 'row',
alignItems: 'center'
},
textInput: {
flex: 1,
padding: StyleConstants.Spacing.S,
borderWidth: StyleSheet.hairlineWidth,
borderRadius: 6,
...StyleConstants.FontStyle.M,
marginLeft: StyleConstants.Spacing.S
},
controlAmount: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-end',
marginRight: StyleConstants.Spacing.M
},
controlOptions: {
paddingHorizontal: StyleConstants.Spacing.Global.PagePadding
},
controlCount: {
marginHorizontal: StyleConstants.Spacing.S
}
})

View File

@ -1,12 +1,11 @@
import CustomText from '@components/Text'
import {
getInstanceAccount,
getInstanceUri
} from '@utils/slices/instancesSlice'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { StyleSheet, Text } from 'react-native'
import { useSelector } from 'react-redux'
const ComposePostingAs = React.memo(
@ -21,21 +20,15 @@ const ComposePostingAs = React.memo(
const instanceUri = useSelector(getInstanceUri)
return (
<Text style={[styles.text, { color: colors.secondary }]}>
<CustomText fontStyle='S' style={{ color: colors.secondary }}>
{t('content.root.header.postingAs', {
acct: instanceAccount?.acct,
domain: instanceUri
})}
</Text>
</CustomText>
)
},
() => true
)
const styles = StyleSheet.create({
text: {
...StyleConstants.FontStyle.S
}
})
export default ComposePostingAs

View File

@ -1,8 +1,9 @@
import CustomText from '@components/Text'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useContext, useEffect, useState } from 'react'
import React, { useContext } from 'react'
import { useTranslation } from 'react-i18next'
import { StyleSheet, Text, TextInput } from 'react-native'
import { TextInput } from 'react-native'
import formatText from '../../formatText'
import ComposeContext from '../../utils/createContext'
@ -14,13 +15,16 @@ const ComposeSpoilerInput: React.FC = () => {
return (
<TextInput
keyboardAppearance={mode}
style={[
styles.spoilerInput,
{
color: colors.primaryDefault,
borderBottomColor: colors.border
}
]}
style={{
...StyleConstants.FontStyle.M,
marginTop: StyleConstants.Spacing.S,
paddingBottom: StyleConstants.Spacing.M,
marginLeft: StyleConstants.Spacing.Global.PagePadding,
marginRight: StyleConstants.Spacing.Global.PagePadding,
borderBottomWidth: 0.5,
color: colors.primaryDefault,
borderBottomColor: colors.border
}}
autoCapitalize='none'
autoCorrect={false}
autoFocus
@ -53,20 +57,9 @@ const ComposeSpoilerInput: React.FC = () => {
})
}
>
<Text>{composeState.spoiler.formatted}</Text>
<CustomText>{composeState.spoiler.formatted}</CustomText>
</TextInput>
)
}
const styles = StyleSheet.create({
spoilerInput: {
...StyleConstants.FontStyle.M,
marginTop: StyleConstants.Spacing.S,
paddingBottom: StyleConstants.Spacing.M,
marginLeft: StyleConstants.Spacing.Global.PagePadding,
marginRight: StyleConstants.Spacing.Global.PagePadding,
borderBottomWidth: 0.5
}
})
export default ComposeSpoilerInput

View File

@ -1,8 +1,9 @@
import CustomText from '@components/Text'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useContext } from 'react'
import { useTranslation } from 'react-i18next'
import { StyleSheet, Text, TextInput } from 'react-native'
import { TextInput } from 'react-native'
import formatText from '../../formatText'
import ComposeContext from '../../utils/createContext'
@ -14,13 +15,15 @@ const ComposeTextInput: React.FC = () => {
return (
<TextInput
keyboardAppearance={mode}
style={[
styles.textInput,
{
color: colors.primaryDefault,
borderBottomColor: colors.border
}
]}
style={{
...StyleConstants.FontStyle.M,
marginTop: StyleConstants.Spacing.S,
paddingBottom: StyleConstants.Spacing.M,
marginLeft: StyleConstants.Spacing.Global.PagePadding,
marginRight: StyleConstants.Spacing.Global.PagePadding,
color: colors.primaryDefault,
borderBottomColor: colors.border
}}
autoFocus
enablesReturnKeyAutomatically
multiline
@ -52,19 +55,9 @@ const ComposeTextInput: React.FC = () => {
ref={composeState.textInputFocus.refs.text}
scrollEnabled={false}
>
<Text>{composeState.text.formatted}</Text>
<CustomText>{composeState.text.formatted}</CustomText>
</TextInput>
)
}
const styles = StyleSheet.create({
textInput: {
...StyleConstants.FontStyle.M,
marginTop: StyleConstants.Spacing.S,
paddingBottom: StyleConstants.Spacing.M,
marginLeft: StyleConstants.Spacing.Global.PagePadding,
marginRight: StyleConstants.Spacing.Global.PagePadding
}
})
export default ComposeTextInput

View File

@ -1,11 +1,11 @@
import { debounce, differenceWith, isEqual } from 'lodash'
import React, { createElement, Dispatch } from 'react'
import { Text } from 'react-native'
import { FetchOptions } from 'react-query/types/core/query'
import Autolinker from '@root/modules/autolinker'
import { useTheme } from '@utils/styles/ThemeManager'
import { ComposeAction, ComposeState } from './utils/types'
import { instanceConfigurationStatusCharsURL } from './Root'
import CustomText from '@components/Text'
export interface Params {
textInput: ComposeState['textInputFocus']['current']
@ -18,7 +18,7 @@ export interface Params {
const TagText = ({ text }: { text: string }) => {
const { colors } = useTheme()
return <Text style={{ color: colors.blue }}>{text}</Text>
return <CustomText style={{ color: colors.blue }}>{text}</CustomText>
}
const debouncedSuggestions = debounce(
@ -120,7 +120,7 @@ const formatText = ({
payload: {
count: contentLength,
raw: content,
formatted: createElement(Text, null, children)
formatted: createElement(CustomText, null, children)
}
})
}

View File

@ -1,5 +1,6 @@
import { HeaderLeft, HeaderRight } from '@components/Header'
import Input from '@components/Input'
import CustomText from '@components/Text'
import { TabMeProfileStackScreenProps } from '@utils/navigation/navigators'
import { useProfileMutation } from '@utils/queryHooks/profile'
import { StyleConstants } from '@utils/styles/constants'
@ -7,7 +8,7 @@ import { useTheme } from '@utils/styles/ThemeManager'
import { isEqual } from 'lodash'
import React, { RefObject, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Alert, StyleSheet, Text, View } from 'react-native'
import { Alert, View } from 'react-native'
import FlashMessage from 'react-native-flash-message'
import { ScrollView } from 'react-native-gesture-handler'
@ -100,13 +101,25 @@ const TabMeProfileFields: React.FC<
}, [theme, i18n.language, dirty, status, newFields])
return (
<ScrollView style={styles.base} keyboardShouldPersistTaps='always'>
<ScrollView
style={{
paddingHorizontal: StyleConstants.Spacing.Global.PagePadding,
marginBottom: StyleConstants.Spacing.L
}}
keyboardShouldPersistTaps='always'
>
<View style={{ marginBottom: StyleConstants.Spacing.L * 2 }}>
{Array.from(Array(4).keys()).map(index => (
<View key={index} style={styles.group}>
<Text style={[styles.headline, { color: colors.primaryDefault }]}>
<View key={index} style={{ marginBottom: StyleConstants.Spacing.M }}>
<CustomText
fontStyle='S'
style={{
marginBottom: StyleConstants.Spacing.XS,
color: colors.primaryDefault
}}
>
{t('me.profile.fields.group', { index: index + 1 })}
</Text>
</CustomText>
<Input
title={t('me.profile.fields.label')}
autoFocus={false}
@ -142,18 +155,4 @@ const TabMeProfileFields: React.FC<
)
}
const styles = StyleSheet.create({
base: {
paddingHorizontal: StyleConstants.Spacing.Global.PagePadding,
marginBottom: StyleConstants.Spacing.L
},
group: {
marginBottom: StyleConstants.Spacing.M
},
headline: {
...StyleConstants.FontStyle.S,
marginBottom: StyleConstants.Spacing.XS
}
})
export default TabMeProfileFields

View File

@ -2,6 +2,7 @@ import analytics from '@components/analytics'
import Button from '@components/Button'
import Icon from '@components/Icon'
import { MenuContainer, MenuRow } from '@components/Menu'
import CustomText from '@components/Text'
import { useAppDispatch } from '@root/store'
import { isDevelopment } from '@utils/checkEnvironment'
import { updateInstancePush } from '@utils/slices/instances/updatePush'
@ -20,7 +21,7 @@ import * as Notifications from 'expo-notifications'
import * as WebBrowser from 'expo-web-browser'
import React, { useState, useEffect, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { AppState, Linking, ScrollView, Text, View } from 'react-native'
import { AppState, Linking, ScrollView, View } from 'react-native'
import { useSelector } from 'react-redux'
const TabMePush: React.FC = () => {
@ -205,14 +206,9 @@ const TabMePush: React.FC = () => {
size={StyleConstants.Font.Size.L}
color={colors.primaryDefault}
/>
<Text
style={{
...StyleConstants.FontStyle.M,
color: colors.primaryDefault
}}
>
<CustomText fontStyle='M' style={{ color: colors.primaryDefault }}>
{t('me.push.notAvailable')}
</Text>
</CustomText>
</View>
)}
</ScrollView>

View File

@ -1,4 +1,5 @@
import { MenuContainer, MenuRow } from '@components/Menu'
import CustomText from '@components/Text'
import { useAppDispatch } from '@root/store'
import { getInstanceVersion } from '@utils/slices/instancesSlice'
import {
@ -10,7 +11,6 @@ import { useTheme } from '@utils/styles/ThemeManager'
import Constants from 'expo-constants'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { Text } from 'react-native'
import { useSelector } from 'react-redux'
const SettingsAnalytics: React.FC = () => {
@ -31,25 +31,25 @@ const SettingsAnalytics: React.FC = () => {
dispatch(changeAnalytics(!settingsAnalytics))
}
/>
<Text
<CustomText
fontStyle='S'
style={{
textAlign: 'center',
...StyleConstants.FontStyle.S,
marginTop: StyleConstants.Spacing.S,
color: colors.secondary
}}
>
{t('me.settings.version', { version: Constants.manifest?.version })}
</Text>
<Text
</CustomText>
<CustomText
fontStyle='S'
style={{
textAlign: 'center',
...StyleConstants.FontStyle.S,
color: colors.secondary
}}
>
{t('me.settings.instanceVersion', { version: instanceVersion })}
</Text>
</CustomText>
</MenuContainer>
)
}

View File

@ -1,13 +1,14 @@
import Button from '@components/Button'
import { MenuContainer, MenuRow } from '@components/Menu'
import { displayMessage } from '@components/Message'
import CustomText from '@components/Text'
import { useActionSheet } from '@expo/react-native-action-sheet'
import { persistor } from '@root/store'
import { getInstanceActive, getInstances } from '@utils/slices/instancesSlice'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { DevSettings, Text } from 'react-native'
import { DevSettings } from 'react-native'
import { useSelector } from 'react-redux'
const SettingsDev: React.FC = () => {
@ -18,16 +19,16 @@ const SettingsDev: React.FC = () => {
return (
<MenuContainer>
<Text
<CustomText
fontStyle='S'
selectable
style={{
paddingHorizontal: StyleConstants.Spacing.Global.PagePadding,
...StyleConstants.FontStyle.S,
color: colors.primaryDefault
}}
>
{instances[instanceActive]?.token}
</Text>
</CustomText>
<MenuRow
title={'Local active index'}
content={typeof instanceActive + ' - ' + instanceActive}

View File

@ -1,6 +1,7 @@
import Button from '@components/Button'
import haptics from '@components/haptics'
import ComponentSeparator from '@components/Separator'
import CustomText from '@components/Text'
import TimelineDefault from '@components/Timeline/Default'
import { useAppDispatch } from '@root/store'
import { TabMeStackScreenProps } from '@utils/navigation/navigators'
@ -14,7 +15,7 @@ import { adaptiveScale } from '@utils/styles/scaling'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { StyleSheet, Text, View } from 'react-native'
import { StyleSheet, View } from 'react-native'
import { ScrollView } from 'react-native-gesture-handler'
import { useSelector } from 'react-redux'
@ -76,31 +77,26 @@ const TabMeSettingsFontsize: React.FC<
return (
<>
{([-1, 0, 1, 2, 3] as [-1, 0, 1, 2, 3]).map(size => (
<Text
<CustomText
key={size}
style={[
styles.size,
{
fontSize: adaptiveScale(StyleConstants.Font.Size.M, size),
lineHeight: adaptiveScale(
StyleConstants.Font.LineHeight.M,
size
),
fontWeight:
initialSize === size
? StyleConstants.Font.Weight.Bold
: undefined,
color:
initialSize === size
? colors.primaryDefault
: colors.secondary,
borderWidth: StyleSheet.hairlineWidth,
borderColor: colors.border
}
]}
style={{
marginHorizontal: StyleConstants.Spacing.XS,
paddingHorizontal: StyleConstants.Spacing.XS,
marginBottom: StyleConstants.Spacing.M,
fontSize: adaptiveScale(StyleConstants.Font.Size.M, size),
lineHeight: adaptiveScale(StyleConstants.Font.LineHeight.M, size),
fontWeight:
initialSize === size
? StyleConstants.Font.Weight.Bold
: undefined,
color:
initialSize === size ? colors.primaryDefault : colors.secondary,
borderWidth: StyleSheet.hairlineWidth,
borderColor: colors.border
}}
>
{t(`me.fontSize.sizes.${mapFontsizeToName(size)}`)}
</Text>
</CustomText>
))}
</>
)
@ -108,9 +104,17 @@ const TabMeSettingsFontsize: React.FC<
return (
<ScrollView scrollEnabled={false}>
<Text style={[styles.header, { color: colors.primaryDefault }]}>
<CustomText
fontStyle='M'
style={{
textAlign: 'center',
marginTop: StyleConstants.Spacing.M,
marginBottom: StyleConstants.Spacing.M,
color: colors.primaryDefault
}}
>
{t('me.fontSize.showcase')}
</Text>
</CustomText>
<View>
<ComponentSeparator
extraMarginLeft={-StyleConstants.Spacing.Global.PagePadding}
@ -127,11 +131,33 @@ const TabMeSettingsFontsize: React.FC<
extraMarginRight={-StyleConstants.Spacing.Global.PagePadding}
/>
</View>
<Text style={[styles.header, { color: colors.primaryDefault }]}>
<CustomText
fontStyle='M'
style={{
textAlign: 'center',
marginTop: StyleConstants.Spacing.M,
marginBottom: StyleConstants.Spacing.M,
color: colors.primaryDefault
}}
>
{t('me.fontSize.availableSizes')}
</Text>
<View style={styles.sizesDemo}>{sizesDemo}</View>
<View style={styles.controls}>
</CustomText>
<View
style={{
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center'
}}
>
{sizesDemo}
</View>
<View
style={{
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center'
}}
>
<Button
onPress={() => {
if (initialSize > -1) {
@ -144,7 +170,7 @@ const TabMeSettingsFontsize: React.FC<
content='Minus'
round
disabled={initialSize <= -1}
style={styles.control}
style={{ marginHorizontal: StyleConstants.Spacing.S }}
/>
<Button
onPress={() => {
@ -158,38 +184,11 @@ const TabMeSettingsFontsize: React.FC<
content='Plus'
round
disabled={initialSize >= 3}
style={styles.control}
style={{ marginHorizontal: StyleConstants.Spacing.S }}
/>
</View>
</ScrollView>
)
}
const styles = StyleSheet.create({
header: {
...StyleConstants.FontStyle.M,
textAlign: 'center',
marginTop: StyleConstants.Spacing.M,
marginBottom: StyleConstants.Spacing.M
},
sizesDemo: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center'
},
size: {
marginHorizontal: StyleConstants.Spacing.XS,
paddingHorizontal: StyleConstants.Spacing.XS,
marginBottom: StyleConstants.Spacing.M
},
controls: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center'
},
control: {
marginHorizontal: StyleConstants.Spacing.S
}
})
export default TabMeSettingsFontsize

View File

@ -2,6 +2,7 @@ import analytics from '@components/analytics'
import Button from '@components/Button'
import haptics from '@components/haptics'
import ComponentInstance from '@components/Instance'
import CustomText from '@components/Text'
import { useNavigation } from '@react-navigation/native'
import initQuery from '@utils/initQuery'
import {
@ -13,13 +14,7 @@ import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useEffect, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import {
KeyboardAvoidingView,
Platform,
StyleSheet,
Text,
View
} from 'react-native'
import { KeyboardAvoidingView, Platform, StyleSheet, View } from 'react-native'
import { ScrollView } from 'react-native-gesture-handler'
import { useSelector } from 'react-redux'
@ -35,7 +30,10 @@ const AccountButton: React.FC<Props> = ({ instance, selected = false }) => {
<Button
type='text'
selected={selected}
style={styles.button}
style={{
marginBottom: StyleConstants.Spacing.M,
marginRight: StyleConstants.Spacing.M
}}
content={`@${instance.account.acct}@${instance.uri}${
selected ? ' ✓' : ''
}`}
@ -70,13 +68,20 @@ const TabMeSwitch: React.FC = () => {
>
<ScrollView
ref={scrollViewRef}
style={styles.base}
style={{ marginBottom: StyleConstants.Spacing.L * 2 }}
keyboardShouldPersistTaps='always'
>
<View>
<Text style={[styles.header, { color: colors.primaryDefault }]}>
<CustomText
fontStyle='M'
style={{
textAlign: 'center',
paddingVertical: StyleConstants.Spacing.S,
color: colors.primaryDefault
}}
>
{t('me.switch.new')}
</Text>
</CustomText>
<ComponentInstance
scrollViewRef={scrollViewRef}
disableHeaderImage
@ -85,12 +90,32 @@ const TabMeSwitch: React.FC = () => {
</View>
<View
style={[styles.firstSection, , { borderTopColor: colors.border }]}
style={{
marginTop: StyleConstants.Spacing.S,
paddingTop: StyleConstants.Spacing.M,
marginHorizontal: StyleConstants.Spacing.Global.PagePadding,
borderTopWidth: StyleSheet.hairlineWidth,
borderTopColor: colors.border
}}
>
<Text style={[styles.header, { color: colors.primaryDefault }]}>
<CustomText
fontStyle='M'
style={{
textAlign: 'center',
paddingVertical: StyleConstants.Spacing.S,
color: colors.primaryDefault
}}
>
{t('me.switch.existing')}
</Text>
<View style={styles.accountButtons}>
</CustomText>
<View
style={{
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
marginTop: StyleConstants.Spacing.M
}}
>
{instances.length
? instances
.slice()
@ -121,31 +146,4 @@ const TabMeSwitch: React.FC = () => {
)
}
const styles = StyleSheet.create({
base: {
marginBottom: StyleConstants.Spacing.L * 2
},
header: {
...StyleConstants.FontStyle.M,
textAlign: 'center',
paddingVertical: StyleConstants.Spacing.S
},
firstSection: {
marginTop: StyleConstants.Spacing.S,
paddingTop: StyleConstants.Spacing.M,
marginHorizontal: StyleConstants.Spacing.Global.PagePadding,
borderTopWidth: StyleSheet.hairlineWidth
},
accountButtons: {
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
marginTop: StyleConstants.Spacing.M
},
button: {
marginBottom: StyleConstants.Spacing.M,
marginRight: StyleConstants.Spacing.M
}
})
export default TabMeSwitch

View File

@ -1,4 +1,5 @@
import Icon from '@components/Icon'
import CustomText from '@components/Text'
import {
getInstanceAccount,
getInstanceUri
@ -6,7 +7,7 @@ import {
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useMemo } from 'react'
import { StyleSheet, Text, View } from 'react-native'
import { View } from 'react-native'
import { useSelector } from 'react-redux'
import { PlaceholderLine } from 'rn-placeholder'
@ -26,27 +27,19 @@ const AccountInformationAccount: React.FC<Props> = ({
)
const instanceUri = useSelector(getInstanceUri)
const movedStyle = useMemo(
() =>
StyleSheet.create({
base: {
textDecorationLine: account?.moved ? 'line-through' : undefined
}
}),
[account?.moved]
)
const movedContent = useMemo(() => {
if (account?.moved) {
return (
<Text
style={[
styles.moved,
{ color: colors.secondary, ...StyleConstants.FontStyle.M }
]}
<CustomText
fontStyle='M'
style={{
marginLeft: StyleConstants.Spacing.S,
color: colors.secondary
}}
selectable
>
@{account.moved.acct}
</Text>
</CustomText>
)
}
}, [account?.moved])
@ -54,26 +47,29 @@ const AccountInformationAccount: React.FC<Props> = ({
if (account || (localInstance && instanceAccount)) {
return (
<View
style={[styles.base, { flexDirection: 'row', alignItems: 'center' }]}
style={{
flexDirection: 'row',
alignItems: 'center',
borderRadius: 0,
marginBottom: StyleConstants.Spacing.L
}}
>
<Text
style={[
movedStyle.base,
{
color: colors.secondary,
...StyleConstants.FontStyle.M
}
]}
<CustomText
fontStyle='M'
style={{
textDecorationLine: account?.moved ? 'line-through' : undefined,
color: colors.secondary
}}
selectable
>
@{localInstance ? instanceAccount?.acct : account?.acct}
{localInstance ? `@${instanceUri}` : null}
</Text>
</CustomText>
{movedContent}
{account?.locked ? (
<Icon
name='Lock'
style={styles.type}
style={{ marginLeft: StyleConstants.Spacing.S }}
color={colors.secondary}
size={StyleConstants.Font.Size.M}
/>
@ -81,7 +77,7 @@ const AccountInformationAccount: React.FC<Props> = ({
{account?.bot ? (
<Icon
name='HardDrive'
style={styles.type}
style={{ marginLeft: StyleConstants.Spacing.S }}
color={colors.secondary}
size={StyleConstants.Font.Size.M}
/>
@ -95,23 +91,12 @@ const AccountInformationAccount: React.FC<Props> = ({
height={StyleConstants.Font.LineHeight.M}
color={colors.shimmerDefault}
noMargin
style={styles.base}
style={{ borderRadius: 0, marginBottom: StyleConstants.Spacing.L }}
/>
)
}
}
const styles = StyleSheet.create({
base: {
borderRadius: 0,
marginBottom: StyleConstants.Spacing.L
},
type: { marginLeft: StyleConstants.Spacing.S },
moved: {
marginLeft: StyleConstants.Spacing.S
}
})
export default React.memo(
AccountInformationAccount,
(_, next) => next.account === undefined

View File

@ -1,9 +1,10 @@
import Icon from '@components/Icon'
import CustomText from '@components/Text'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { StyleSheet, Text, View } from 'react-native'
import { View } from 'react-native'
import { PlaceholderLine } from 'rn-placeholder'
export interface Props {
@ -24,20 +25,20 @@ const AccountInformationCreated = React.memo(
if (account) {
return (
<View
style={[styles.base, { flexDirection: 'row', alignItems: 'center' }]}
style={{
flexDirection: 'row',
alignItems: 'center',
borderRadius: 0,
marginBottom: StyleConstants.Spacing.M
}}
>
<Icon
name='Calendar'
size={StyleConstants.Font.Size.S}
color={colors.secondary}
style={styles.icon}
style={{ marginRight: StyleConstants.Spacing.XS }}
/>
<Text
style={{
color: colors.secondary,
...StyleConstants.FontStyle.S
}}
>
<CustomText fontStyle='S' style={{ color: colors.secondary }}>
{t('shared.account.created_at', {
date: new Date(account.created_at || '').toLocaleDateString(
i18n.language,
@ -48,7 +49,7 @@ const AccountInformationCreated = React.memo(
}
)
})}
</Text>
</CustomText>
</View>
)
} else {
@ -58,7 +59,7 @@ const AccountInformationCreated = React.memo(
height={StyleConstants.Font.LineHeight.S}
color={colors.shimmerDefault}
noMargin
style={styles.base}
style={{ borderRadius: 0, marginBottom: StyleConstants.Spacing.M }}
/>
)
}
@ -66,14 +67,4 @@ const AccountInformationCreated = React.memo(
(_, next) => next.account === undefined
)
const styles = StyleSheet.create({
base: {
borderRadius: 0,
marginBottom: StyleConstants.Spacing.M
},
icon: {
marginRight: StyleConstants.Spacing.XS
}
})
export default AccountInformationCreated

View File

@ -1,9 +1,10 @@
import Input from '@components/Input'
import { ParseEmojis } from '@components/Parse'
import CustomText from '@components/Text'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useMemo, useState } from 'react'
import { StyleSheet, Text, View } from 'react-native'
import { View } from 'react-native'
import { PlaceholderLine } from 'rn-placeholder'
export interface Props {
@ -17,7 +18,7 @@ const AccountInformationName: React.FC<Props> = ({ account, edit }) => {
const movedContent = useMemo(() => {
if (account?.moved) {
return (
<View style={styles.moved}>
<View style={{ marginLeft: StyleConstants.Spacing.S }}>
<ParseEmojis
content={account.moved.display_name || account.moved.username}
emojis={account.moved.emojis}
@ -32,13 +33,20 @@ const AccountInformationName: React.FC<Props> = ({ account, edit }) => {
const [displatName, setDisplayName] = useState(account?.display_name)
return (
<View style={[styles.base, { flexDirection: 'row' }]}>
<View
style={{
borderRadius: 0,
marginTop: StyleConstants.Spacing.S,
marginBottom: StyleConstants.Spacing.XS,
flexDirection: 'row'
}}
>
{account ? (
edit ? (
<Input title='昵称' value={displatName} setValue={setDisplayName} />
) : (
<>
<Text
<CustomText
style={{
textDecorationLine: account?.moved ? 'line-through' : undefined
}}
@ -49,7 +57,7 @@ const AccountInformationName: React.FC<Props> = ({ account, edit }) => {
size='L'
fontBold
/>
</Text>
</CustomText>
{movedContent}
</>
)
@ -66,17 +74,6 @@ const AccountInformationName: React.FC<Props> = ({ account, edit }) => {
)
}
const styles = StyleSheet.create({
base: {
borderRadius: 0,
marginTop: StyleConstants.Spacing.S,
marginBottom: StyleConstants.Spacing.XS
},
moved: {
marginLeft: StyleConstants.Spacing.S
}
})
export default React.memo(
AccountInformationName,
(_, next) => next.account === undefined

View File

@ -1,4 +1,5 @@
import analytics from '@components/analytics'
import CustomText from '@components/Text'
import { useNavigation } from '@react-navigation/native'
import { StackNavigationProp } from '@react-navigation/stack'
import { StyleConstants } from '@root/utils/styles/constants'
@ -6,7 +7,7 @@ import { useTheme } from '@root/utils/styles/ThemeManager'
import { TabLocalStackParamList } from '@utils/navigation/navigators'
import React from 'react'
import { useTranslation } from 'react-i18next'
import { StyleSheet, Text, View } from 'react-native'
import { StyleSheet, View } from 'react-native'
import { PlaceholderLine } from 'rn-placeholder'
export interface Props {
@ -23,7 +24,7 @@ const AccountInformationStats: React.FC<Props> = ({ account, myInfo }) => {
return (
<View style={[styles.stats, { flexDirection: 'row' }]}>
{account ? (
<Text
<CustomText
style={[styles.stat, { color: colors.primaryDefault }]}
children={t('shared.account.summary.statuses_count', {
count: account.statuses_count || 0
@ -45,7 +46,7 @@ const AccountInformationStats: React.FC<Props> = ({ account, myInfo }) => {
/>
)}
{account ? (
<Text
<CustomText
style={[
styles.stat,
{ color: colors.primaryDefault, textAlign: 'right' }
@ -75,7 +76,7 @@ const AccountInformationStats: React.FC<Props> = ({ account, myInfo }) => {
/>
)}
{account ? (
<Text
<CustomText
style={[
styles.stat,
{ color: colors.primaryDefault, textAlign: 'center' }

View File

@ -1,8 +1,9 @@
import { ParseEmojis } from '@components/Parse'
import CustomText from '@components/Text'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { Dimensions, StyleSheet, Text, View } from 'react-native'
import { Dimensions, StyleSheet, View } from 'react-native'
import Animated, {
Extrapolate,
interpolate,
@ -46,29 +47,33 @@ const AccountNav = React.memo(
return (
<Animated.View
style={[
styles.base,
styleOpacity,
{ backgroundColor: colors.backgroundDefault, height: headerHeight }
{
...StyleSheet.absoluteFillObject,
zIndex: 99,
backgroundColor: colors.backgroundDefault,
height: headerHeight
}
]}
>
<View
style={[
styles.content,
{
marginTop:
useSafeAreaInsets().top + (44 - StyleConstants.Font.Size.L) / 2
}
]}
style={{
flex: 1,
alignItems: 'center',
overflow: 'hidden',
marginTop:
useSafeAreaInsets().top + (44 - StyleConstants.Font.Size.L) / 2
}}
>
<Animated.View style={[styles.display_name, styleMarginTop]}>
<Animated.View style={[{ flexDirection: 'row' }, styleMarginTop]}>
{account ? (
<Text numberOfLines={1}>
<CustomText numberOfLines={1}>
<ParseEmojis
content={account.display_name || account.username}
emojis={account.emojis}
fontBold
/>
</Text>
</CustomText>
) : null}
</Animated.View>
</View>
@ -78,19 +83,4 @@ const AccountNav = React.memo(
(_, next) => next.account === undefined
)
const styles = StyleSheet.create({
base: {
...StyleSheet.absoluteFillObject,
zIndex: 99
},
content: {
flex: 1,
alignItems: 'center',
overflow: 'hidden'
},
display_name: {
flexDirection: 'row'
}
})
export default AccountNav

View File

@ -1,6 +1,7 @@
import Icon from '@components/Icon'
import { ParseEmojis } from '@components/Parse'
import ComponentSeparator from '@components/Separator'
import CustomText from '@components/Text'
import TimelineAttachment from '@components/Timeline/Shared/Attachment'
import TimelineContent from '@components/Timeline/Shared/Content'
import HeaderSharedCreated from '@components/Timeline/Shared/HeaderShared/Created'
@ -9,7 +10,7 @@ import { useStatusHistory } from '@utils/queryHooks/statusesHistory'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react'
import { Text, View } from 'react-native'
import { View } from 'react-native'
import { ScrollView } from 'react-native-gesture-handler'
const ContentView = ({
@ -52,12 +53,12 @@ const ContentView = ({
size={StyleConstants.Font.Size.M}
color={colors.disabled}
/>
<Text style={{ flex: 1 }}>
<CustomText style={{ flex: 1 }}>
<ParseEmojis
content={option.title}
emojis={history.poll?.emojis}
/>
</Text>
</CustomText>
</View>
</View>
))

View File

@ -1,5 +1,6 @@
import { HeaderCenter, HeaderLeft } from '@components/Header'
import { ParseEmojis } from '@components/Parse'
import CustomText from '@components/Text'
import { createNativeStackNavigator } from '@react-navigation/native-stack'
import TabSharedAccount from '@screens/Tabs/Shared/Account'
import TabSharedAttachments from '@screens/Tabs/Shared/Attachments'
@ -14,7 +15,7 @@ import { useTheme } from '@utils/styles/ThemeManager'
import { debounce } from 'lodash'
import React from 'react'
import { Trans, useTranslation } from 'react-i18next'
import { Platform, StyleSheet, Text, TextInput, View } from 'react-native'
import { Platform, TextInput, View } from 'react-native'
const TabSharedRoot = ({
Stack
@ -61,7 +62,7 @@ const TabSharedRoot = ({
}: TabSharedStackScreenProps<'Tab-Shared-Attachments'>) => {
return {
headerTitle: () => (
<Text numberOfLines={1}>
<CustomText numberOfLines={1}>
<Trans
i18nKey='screenTabs:shared.attachments.name'
components={[
@ -70,16 +71,16 @@ const TabSharedRoot = ({
emojis={account.emojis}
fontBold
/>,
<Text
<CustomText
fontStyle='M'
style={{
...StyleConstants.FontStyle.M,
color: colors.primaryDefault,
fontWeight: StyleConstants.Font.Weight.Bold
}}
/>
]}
/>
</Text>
</CustomText>
)
}
}}
@ -126,28 +127,30 @@ const TabSharedRoot = ({
}
)
return (
<View style={styles.searchBar}>
<View
style={{
flexBasis: '80%',
flexDirection: 'row',
alignItems: 'center'
}}
>
<TextInput
editable={false}
style={[
styles.textInput,
{
color: colors.primaryDefault
}
]}
style={{
fontSize: StyleConstants.Font.Size.M,
color: colors.primaryDefault
}}
defaultValue={t('shared.search.header.prefix')}
/>
<TextInput
accessibilityRole='search'
keyboardAppearance={mode}
style={[
styles.textInput,
{
flex: 1,
color: colors.primaryDefault,
paddingLeft: StyleConstants.Spacing.XS
}
]}
style={{
fontSize: StyleConstants.Font.Size.M,
flex: 1,
color: colors.primaryDefault,
paddingLeft: StyleConstants.Spacing.XS
}}
autoFocus
onChangeText={onChangeText}
autoCapitalize='none'
@ -199,15 +202,4 @@ const TabSharedRoot = ({
)
}
const styles = StyleSheet.create({
searchBar: {
flexBasis: '80%',
flexDirection: 'row',
alignItems: 'center'
},
textInput: {
fontSize: StyleConstants.Font.Size.M
}
})
export default TabSharedRoot

View File

@ -1,6 +1,7 @@
import ComponentAccount from '@components/Account'
import ComponentHashtag from '@components/Hashtag'
import ComponentSeparator from '@components/Separator'
import CustomText from '@components/Text'
import TimelineDefault from '@components/Timeline/Default'
import { TabSharedStackScreenProps } from '@utils/navigation/navigators'
import { useSearchQuery } from '@utils/queryHooks/search'
@ -13,7 +14,6 @@ import {
Platform,
SectionList,
StyleSheet,
Text,
View
} from 'react-native'
import { Circle } from 'react-native-animated-spinkit'
@ -66,10 +66,15 @@ const TabSharedSearch: React.FC<
const listEmpty = useMemo(() => {
return (
<View style={styles.emptyBase}>
<View
style={{
marginVertical: StyleConstants.Spacing.Global.PagePadding,
alignItems: 'center'
}}
>
<View>
{status === 'loading' ? (
<View style={styles.loading}>
<View style={{ flex: 1, alignItems: 'center' }}>
<Circle
size={StyleConstants.Font.Size.M * 1.25}
color={colors.secondary}
@ -77,53 +82,61 @@ const TabSharedSearch: React.FC<
</View>
) : (
<>
<Text
style={[
styles.emptyDefault,
styles.emptyFontSize,
{ color: colors.primaryDefault }
]}
<CustomText
fontStyle='S'
style={{
marginBottom: StyleConstants.Spacing.L,
color: colors.primaryDefault
}}
>
<Trans
i18nKey='screenTabs:shared.search.empty.general'
components={{ bold: <Text style={styles.emptyFontBold} /> }}
components={{
bold: (
<CustomText
style={{ fontWeight: StyleConstants.Font.Weight.Bold }}
/>
)
}}
/>
</Text>
<Text
</CustomText>
<CustomText
style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}
>
{t('shared.search.empty.advanced.header')}
</Text>
<Text
</CustomText>
<CustomText
style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}
>
<Text style={{ color: colors.secondary }}>
<CustomText style={{ color: colors.secondary }}>
@username@domain
</Text>
</CustomText>
{' '}
{t('shared.search.empty.advanced.example.account')}
</Text>
<Text
</CustomText>
<CustomText
style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}
>
<Text style={{ color: colors.secondary }}>#example</Text>
<CustomText style={{ color: colors.secondary }}>
#example
</CustomText>
{' '}
{t('shared.search.empty.advanced.example.hashtag')}
</Text>
<Text
</CustomText>
<CustomText
style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}
>
<Text style={{ color: colors.secondary }}>URL</Text>
<CustomText style={{ color: colors.secondary }}>URL</CustomText>
{' '}
{t('shared.search.empty.advanced.example.statusLink')}
</Text>
<Text
</CustomText>
<CustomText
style={[styles.emptyAdvanced, { color: colors.primaryDefault }]}
>
<Text style={{ color: colors.secondary }}>URL</Text>
<CustomText style={{ color: colors.secondary }}>URL</CustomText>
{' '}
{t('shared.search.empty.advanced.example.accountLink')}
</Text>
</CustomText>
</>
)}
</View>
@ -133,16 +146,21 @@ const TabSharedSearch: React.FC<
const sectionHeader = useCallback(
({ section: { translation } }) => (
<View
style={[
styles.sectionHeader,
{ backgroundColor: colors.backgroundDefault }
]}
style={{
padding: StyleConstants.Spacing.M,
backgroundColor: colors.backgroundDefault
}}
>
<Text
style={[styles.sectionHeaderText, { color: colors.primaryDefault }]}
<CustomText
fontStyle='M'
style={{
fontWeight: StyleConstants.Font.Weight.Bold,
textAlign: 'center',
color: colors.primaryDefault
}}
>
{translation}
</Text>
</CustomText>
</View>
),
[]
@ -151,18 +169,27 @@ const TabSharedSearch: React.FC<
({ section: { data, translation } }) =>
!data.length ? (
<View
style={[
styles.sectionFooter,
{ backgroundColor: colors.backgroundDefault }
]}
style={{
padding: StyleConstants.Spacing.S,
backgroundColor: colors.backgroundDefault
}}
>
<Text style={[styles.sectionFooterText, { color: colors.secondary }]}>
<CustomText
fontStyle='S'
style={{ textAlign: 'center', color: colors.secondary }}
>
<Trans
i18nKey='screenTabs:shared.search.notFound'
values={{ searchTerm: text, type: translation }}
components={{ bold: <Text style={styles.emptyFontBold} /> }}
components={{
bold: (
<CustomText
style={{ fontWeight: StyleConstants.Font.Weight.Bold }}
/>
)
}}
/>
</Text>
</CustomText>
</View>
) : null,
[text]
@ -186,7 +213,7 @@ const TabSharedSearch: React.FC<
style={{ flex: 1 }}
>
<SectionList
style={styles.base}
style={{ minHeight: '100%' }}
renderItem={listItem}
stickySectionHeadersEnabled
sections={data || []}
@ -203,38 +230,8 @@ const TabSharedSearch: React.FC<
}
const styles = StyleSheet.create({
base: {
minHeight: '100%'
},
emptyBase: {
marginVertical: StyleConstants.Spacing.Global.PagePadding,
alignItems: 'center'
},
loading: { flex: 1, alignItems: 'center' },
emptyFontSize: { ...StyleConstants.FontStyle.S },
emptyFontBold: {
fontWeight: StyleConstants.Font.Weight.Bold
},
emptyDefault: {
marginBottom: StyleConstants.Spacing.L
},
emptyAdvanced: {
marginBottom: StyleConstants.Spacing.S
},
sectionHeader: {
padding: StyleConstants.Spacing.M
},
sectionHeaderText: {
...StyleConstants.FontStyle.M,
fontWeight: StyleConstants.Font.Weight.Bold,
textAlign: 'center'
},
sectionFooter: {
padding: StyleConstants.Spacing.S
},
sectionFooterText: {
...StyleConstants.FontStyle.S,
textAlign: 'center'
}
})

View File

@ -3,11 +3,7 @@ const Base = 4
export const StyleConstants = {
Font: {
Size: { S: 14, M: 16, L: 18 },
LineHeight: {
S: 20,
M: 22,
L: 28
},
LineHeight: { S: 20, M: 22, L: 28 },
Weight: { Normal: '400' as '400', Bold: '600' as '600' }
},
FontStyle: {