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 end
desc "Build and deploy Android app" 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) sh("echo #{ENV["ANDROID_KEYSTORE"]} | base64 -d | tee #{File.expand_path('..', Dir.pwd)}/android/tooot.jks >/dev/null", log: false)
case ENVIRONMENT case ENVIRONMENT

View File

@ -19,7 +19,7 @@
"android": "react-native run-android", "android": "react-native run-android",
"iphone": "react-native run-ios", "iphone": "react-native run-ios",
"ipad": "react-native run-ios --simulator 'iPad mini (6th generation)'", "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", "release": "scripts/release.sh",
"clean": "react-native-clean-project", "clean": "react-native-clean-project",
"postinstall": "patch-package" "postinstall": "patch-package"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,8 @@
import CustomText from '@components/Text'
import { StyleConstants } from '@utils/styles/constants' import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react' import React from 'react'
import { StyleSheet, Text, View, ViewStyle } from 'react-native' import { View, ViewStyle } from 'react-native'
import { PlaceholderLine } from 'rn-placeholder' import { PlaceholderLine } from 'rn-placeholder'
export interface Props { export interface Props {
@ -16,14 +17,33 @@ const InstanceInfo = React.memo(
const { colors } = useTheme() const { colors } = useTheme()
return ( return (
<View style={[styles.base, style]} accessible> <View
<Text style={[styles.header, { color: colors.primaryDefault }]}> style={[
{header} {
</Text> 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 ? ( {content ? (
<Text style={[styles.content, { color: colors.primaryDefault }]}> <CustomText
{content} fontStyle='M'
</Text> style={{ color: colors.primaryDefault }}
children={content}
/>
) : ( ) : (
<PlaceholderLine <PlaceholderLine
width={ width={
@ -43,21 +63,4 @@ const InstanceInfo = React.memo(
(prev, next) => prev.content === next.content (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 export default InstanceInfo

View File

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

View File

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

View File

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

View File

@ -2,6 +2,7 @@ import analytics from '@components/analytics'
import Icon from '@components/Icon' import Icon from '@components/Icon'
import openLink from '@components/openLink' import openLink from '@components/openLink'
import ParseEmojis from '@components/Parse/Emojis' import ParseEmojis from '@components/Parse/Emojis'
import CustomText from '@components/Text'
import { useNavigation, useRoute } from '@react-navigation/native' import { useNavigation, useRoute } from '@react-navigation/native'
import { StackNavigationProp } from '@react-navigation/stack' import { StackNavigationProp } from '@react-navigation/stack'
import { TabLocalStackParamList } from '@utils/navigation/navigators' import { TabLocalStackParamList } from '@utils/navigation/navigators'
@ -12,7 +13,7 @@ import { adaptiveScale } from '@utils/styles/scaling'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback, useState } from 'react' import React, { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next' 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 HTMLView from 'react-native-htmlview'
import { useSelector } from 'react-redux' import { useSelector } from 'react-redux'
@ -53,7 +54,7 @@ const renderNode = ({
? routeParams.hashtag !== tag[1] && routeParams.hashtag !== tag[2] ? routeParams.hashtag !== tag[1] && routeParams.hashtag !== tag[2]
: true : true
return ( return (
<Text <CustomText
accessible accessible
key={index} key={index}
style={{ style={{
@ -72,7 +73,7 @@ const renderNode = ({
> >
{node.children[0].data} {node.children[0].data}
{node.children[1]?.children[0].data} {node.children[1]?.children[0].data}
</Text> </CustomText>
) )
} else if (classes.includes('mention') && mentions) { } else if (classes.includes('mention') && mentions) {
const accountIndex = mentions.findIndex( const accountIndex = mentions.findIndex(
@ -82,7 +83,7 @@ const renderNode = ({
? routeParams.account.id !== mentions[accountIndex]?.id ? routeParams.account.id !== mentions[accountIndex]?.id
: true : true
return ( return (
<Text <CustomText
key={index} key={index}
style={{ style={{
color: color:
@ -102,7 +103,7 @@ const renderNode = ({
> >
{node.children[0].data} {node.children[0].data}
{node.children[1]?.children[0].data} {node.children[1]?.children[0].data}
</Text> </CustomText>
) )
} }
} else { } else {
@ -113,7 +114,7 @@ const renderNode = ({
const shouldBeTag = const shouldBeTag =
tags && tags.filter(tag => `#${tag.name}` === content).length > 0 tags && tags.filter(tag => `#${tag.name}` === content).length > 0
return ( return (
<Text <CustomText
key={index} key={index}
style={{ style={{
color: colors.blue, color: colors.blue,
@ -142,7 +143,7 @@ const renderNode = ({
}} }}
/> />
) : null} ) : null}
</Text> </CustomText>
) )
} }
break break
@ -252,7 +253,7 @@ const ParseHTML = React.memo(
return ( return (
<View style={{ overflow: 'hidden' }}> <View style={{ overflow: 'hidden' }}>
<Text <CustomText
children={children} children={children}
onTextLayout={onTextLayout} onTextLayout={onTextLayout}
numberOfLines={ numberOfLines={
@ -275,7 +276,7 @@ const ParseHTML = React.memo(
backgroundColor: colors.backgroundDefault backgroundColor: colors.backgroundDefault
}} }}
> >
<Text <CustomText
style={{ style={{
textAlign: 'center', textAlign: 'center',
...StyleConstants.FontStyle.S, ...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 analytics from '@components/analytics'
import Button from '@components/Button' import Button from '@components/Button'
import Icon from '@components/Icon' import Icon from '@components/Icon'
import CustomText from '@components/Text'
import { QueryKeyTimeline, useTimelineQuery } from '@utils/queryHooks/timeline' import { QueryKeyTimeline, useTimelineQuery } from '@utils/queryHooks/timeline'
import { StyleConstants } from '@utils/styles/constants' import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import React from 'react' import React from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { StyleSheet, Text, View } from 'react-native' import { View } from 'react-native'
import { Circle } from 'react-native-animated-spinkit' import { Circle } from 'react-native-animated-spinkit'
export interface Props { export interface Props {
@ -40,9 +41,16 @@ const TimelineEmpty = React.memo(
size={StyleConstants.Font.Size.L} size={StyleConstants.Font.Size.L}
color={colors.primaryDefault} 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')} {t('empty.error.message')}
</Text> </CustomText>
<Button <Button
type='text' type='text'
content={t('empty.error.button')} content={t('empty.error.button')}
@ -61,9 +69,16 @@ const TimelineEmpty = React.memo(
size={StyleConstants.Font.Size.L} size={StyleConstants.Font.Size.L}
color={colors.primaryDefault} 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')} {t('empty.success.message')}
</Text> </CustomText>
</> </>
) )
} }
@ -85,12 +100,4 @@ const TimelineEmpty = React.memo(
() => true () => true
) )
const styles = StyleSheet.create({
error: {
...StyleConstants.FontStyle.M,
marginTop: StyleConstants.Spacing.S,
marginBottom: StyleConstants.Spacing.L
}
})
export default TimelineEmpty export default TimelineEmpty

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,9 +1,10 @@
import CustomText from '@components/Text'
import { useAccessibility } from '@utils/accessibility/AccessibilityManager' import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
import { StyleConstants } from '@utils/styles/constants' import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import React, { useContext } from 'react' import React, { useContext } from 'react'
import { useTranslation } from 'react-i18next' 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 { PanGestureHandler } from 'react-native-gesture-handler'
import Animated, { import Animated, {
Extrapolate, Extrapolate,
@ -120,7 +121,7 @@ const ComposeEditAttachmentImage: React.FC<Props> = ({ index }) => {
return ( return (
<> <>
<View style={styles.base}> <View style={{ overflow: 'hidden', flex: 1, alignItems: 'center' }}>
<Image <Image
style={{ style={{
width: imageDimensionis.width, width: imageDimensionis.width,
@ -168,20 +169,18 @@ const ComposeEditAttachmentImage: React.FC<Props> = ({ index }) => {
</PanGestureHandler> </PanGestureHandler>
</View> </View>
{screenReaderEnabled ? null : ( {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')} {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 export default ComposeEditAttachmentImage

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,11 +1,11 @@
import { debounce, differenceWith, isEqual } from 'lodash' import { debounce, differenceWith, isEqual } from 'lodash'
import React, { createElement, Dispatch } from 'react' import React, { createElement, Dispatch } from 'react'
import { Text } from 'react-native'
import { FetchOptions } from 'react-query/types/core/query' import { FetchOptions } from 'react-query/types/core/query'
import Autolinker from '@root/modules/autolinker' import Autolinker from '@root/modules/autolinker'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import { ComposeAction, ComposeState } from './utils/types' import { ComposeAction, ComposeState } from './utils/types'
import { instanceConfigurationStatusCharsURL } from './Root' import { instanceConfigurationStatusCharsURL } from './Root'
import CustomText from '@components/Text'
export interface Params { export interface Params {
textInput: ComposeState['textInputFocus']['current'] textInput: ComposeState['textInputFocus']['current']
@ -18,7 +18,7 @@ export interface Params {
const TagText = ({ text }: { text: string }) => { const TagText = ({ text }: { text: string }) => {
const { colors } = useTheme() const { colors } = useTheme()
return <Text style={{ color: colors.blue }}>{text}</Text> return <CustomText style={{ color: colors.blue }}>{text}</CustomText>
} }
const debouncedSuggestions = debounce( const debouncedSuggestions = debounce(
@ -120,7 +120,7 @@ const formatText = ({
payload: { payload: {
count: contentLength, count: contentLength,
raw: content, 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 { HeaderLeft, HeaderRight } from '@components/Header'
import Input from '@components/Input' import Input from '@components/Input'
import CustomText from '@components/Text'
import { TabMeProfileStackScreenProps } from '@utils/navigation/navigators' import { TabMeProfileStackScreenProps } from '@utils/navigation/navigators'
import { useProfileMutation } from '@utils/queryHooks/profile' import { useProfileMutation } from '@utils/queryHooks/profile'
import { StyleConstants } from '@utils/styles/constants' import { StyleConstants } from '@utils/styles/constants'
@ -7,7 +8,7 @@ import { useTheme } from '@utils/styles/ThemeManager'
import { isEqual } from 'lodash' import { isEqual } from 'lodash'
import React, { RefObject, useEffect, useState } from 'react' import React, { RefObject, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next' 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 FlashMessage from 'react-native-flash-message'
import { ScrollView } from 'react-native-gesture-handler' import { ScrollView } from 'react-native-gesture-handler'
@ -100,13 +101,25 @@ const TabMeProfileFields: React.FC<
}, [theme, i18n.language, dirty, status, newFields]) }, [theme, i18n.language, dirty, status, newFields])
return ( 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 }}> <View style={{ marginBottom: StyleConstants.Spacing.L * 2 }}>
{Array.from(Array(4).keys()).map(index => ( {Array.from(Array(4).keys()).map(index => (
<View key={index} style={styles.group}> <View key={index} style={{ marginBottom: StyleConstants.Spacing.M }}>
<Text style={[styles.headline, { color: colors.primaryDefault }]}> <CustomText
fontStyle='S'
style={{
marginBottom: StyleConstants.Spacing.XS,
color: colors.primaryDefault
}}
>
{t('me.profile.fields.group', { index: index + 1 })} {t('me.profile.fields.group', { index: index + 1 })}
</Text> </CustomText>
<Input <Input
title={t('me.profile.fields.label')} title={t('me.profile.fields.label')}
autoFocus={false} 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 export default TabMeProfileFields

View File

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

View File

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

View File

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

View File

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

View File

@ -2,6 +2,7 @@ import analytics from '@components/analytics'
import Button from '@components/Button' import Button from '@components/Button'
import haptics from '@components/haptics' import haptics from '@components/haptics'
import ComponentInstance from '@components/Instance' import ComponentInstance from '@components/Instance'
import CustomText from '@components/Text'
import { useNavigation } from '@react-navigation/native' import { useNavigation } from '@react-navigation/native'
import initQuery from '@utils/initQuery' import initQuery from '@utils/initQuery'
import { import {
@ -13,13 +14,7 @@ import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import React, { useEffect, useRef } from 'react' import React, { useEffect, useRef } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { import { KeyboardAvoidingView, Platform, StyleSheet, View } from 'react-native'
KeyboardAvoidingView,
Platform,
StyleSheet,
Text,
View
} from 'react-native'
import { ScrollView } from 'react-native-gesture-handler' import { ScrollView } from 'react-native-gesture-handler'
import { useSelector } from 'react-redux' import { useSelector } from 'react-redux'
@ -35,7 +30,10 @@ const AccountButton: React.FC<Props> = ({ instance, selected = false }) => {
<Button <Button
type='text' type='text'
selected={selected} selected={selected}
style={styles.button} style={{
marginBottom: StyleConstants.Spacing.M,
marginRight: StyleConstants.Spacing.M
}}
content={`@${instance.account.acct}@${instance.uri}${ content={`@${instance.account.acct}@${instance.uri}${
selected ? ' ✓' : '' selected ? ' ✓' : ''
}`} }`}
@ -70,13 +68,20 @@ const TabMeSwitch: React.FC = () => {
> >
<ScrollView <ScrollView
ref={scrollViewRef} ref={scrollViewRef}
style={styles.base} style={{ marginBottom: StyleConstants.Spacing.L * 2 }}
keyboardShouldPersistTaps='always' keyboardShouldPersistTaps='always'
> >
<View> <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')} {t('me.switch.new')}
</Text> </CustomText>
<ComponentInstance <ComponentInstance
scrollViewRef={scrollViewRef} scrollViewRef={scrollViewRef}
disableHeaderImage disableHeaderImage
@ -85,12 +90,32 @@ const TabMeSwitch: React.FC = () => {
</View> </View>
<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')} {t('me.switch.existing')}
</Text> </CustomText>
<View style={styles.accountButtons}> <View
style={{
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
marginTop: StyleConstants.Spacing.M
}}
>
{instances.length {instances.length
? instances ? instances
.slice() .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 export default TabMeSwitch

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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