mirror of
				https://github.com/tooot-app/app
				synced 2025-06-05 22:19:13 +02:00 
			
		
		
		
	Added font size settings
This commit is contained in:
		
							
								
								
									
										1
									
								
								src/@types/react-navigation.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								src/@types/react-navigation.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -118,6 +118,7 @@ declare namespace Nav { | ||||
|       title: Mastodon.List['title'] | ||||
|     } | ||||
|     'Tab-Me-Settings': undefined | ||||
|     'Tab-Me-Settings-Fontsize': undefined | ||||
|     'Tab-Me-Settings-Push': undefined | ||||
|     'Tab-Me-Switch': undefined | ||||
|   } & TabSharedStackParamList | ||||
|   | ||||
| @@ -1,8 +1,6 @@ | ||||
| import { ParseHTML } from '@components/Parse' | ||||
| import { StyleConstants } from '@utils/styles/constants' | ||||
| import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import React from 'react' | ||||
| import { useTranslation } from 'react-i18next' | ||||
| import { StyleSheet, Text, View, ViewStyle } from 'react-native' | ||||
| import { PlaceholderLine } from 'rn-placeholder' | ||||
|  | ||||
| @@ -15,19 +13,15 @@ export interface Props { | ||||
|  | ||||
| const InstanceInfo = React.memo( | ||||
|   ({ style, header, content, potentialWidth }: Props) => { | ||||
|     const { t } = useTranslation('componentInstance') | ||||
|     const { theme } = useTheme() | ||||
|  | ||||
|     return ( | ||||
|       <View style={[styles.base, style]}> | ||||
|         <Text style={[styles.header, { color: theme.primary }]}>{header}</Text> | ||||
|         {content ? ( | ||||
|           <ParseHTML | ||||
|             content={content} | ||||
|             size={'M'} | ||||
|             numberOfLines={5} | ||||
|             expandHint={t('server.information.description.expandHint')} | ||||
|           /> | ||||
|           <Text style={[styles.content, { color: theme.primary }]}> | ||||
|             {content} | ||||
|           </Text> | ||||
|         ) : ( | ||||
|           <PlaceholderLine | ||||
|             width={ | ||||
| @@ -58,6 +52,9 @@ const styles = StyleSheet.create({ | ||||
|     ...StyleConstants.FontStyle.S, | ||||
|     fontWeight: StyleConstants.Font.Weight.Bold, | ||||
|     marginBottom: StyleConstants.Spacing.XS | ||||
|   }, | ||||
|   content: { | ||||
|     ...StyleConstants.FontStyle.M | ||||
|   } | ||||
| }) | ||||
|  | ||||
|   | ||||
| @@ -1,8 +1,10 @@ | ||||
| import { StyleConstants } from '@utils/styles/constants' | ||||
| import { getSettingsFontsize } from '@utils/slices/settingsSlice' | ||||
| import { adaptiveScale, StyleConstants } from '@utils/styles/constants' | ||||
| import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import React, { useMemo } from 'react' | ||||
| import { StyleSheet, Text } from 'react-native' | ||||
| import FastImage from 'react-native-fast-image' | ||||
| import { useSelector } from 'react-redux' | ||||
|  | ||||
| const regexEmoji = new RegExp(/(:[A-Za-z0-9_]+:)/) | ||||
|  | ||||
| @@ -10,26 +12,44 @@ export interface Props { | ||||
|   content: string | ||||
|   emojis?: Mastodon.Emoji[] | ||||
|   size?: 'S' | 'M' | 'L' | ||||
|   adaptiveSize?: boolean | ||||
|   fontBold?: boolean | ||||
| } | ||||
|  | ||||
| const ParseEmojis = React.memo( | ||||
|   ({ content, emojis, size = 'M', fontBold = false }: Props) => { | ||||
|   ({ | ||||
|     content, | ||||
|     emojis, | ||||
|     size = 'M', | ||||
|     adaptiveSize = false, | ||||
|     fontBold = false | ||||
|   }: Props) => { | ||||
|     const adaptiveFontsize = useSelector(getSettingsFontsize) | ||||
|     const adaptedFontsize = adaptiveScale( | ||||
|       StyleConstants.Font.Size[size], | ||||
|       adaptiveSize ? adaptiveFontsize : 0 | ||||
|     ) | ||||
|     const adaptedLineheight = adaptiveScale( | ||||
|       StyleConstants.Font.LineHeight[size], | ||||
|       adaptiveSize ? adaptiveFontsize : 0 | ||||
|     ) | ||||
|  | ||||
|     const { mode, theme } = useTheme() | ||||
|     const styles = useMemo(() => { | ||||
|       return StyleSheet.create({ | ||||
|         text: { | ||||
|           color: theme.primary, | ||||
|           ...StyleConstants.FontStyle[size], | ||||
|           fontSize: adaptedFontsize, | ||||
|           lineHeight: adaptedLineheight, | ||||
|           ...(fontBold && { fontWeight: StyleConstants.Font.Weight.Bold }) | ||||
|         }, | ||||
|         image: { | ||||
|           width: StyleConstants.Font.Size[size], | ||||
|           height: StyleConstants.Font.Size[size], | ||||
|           transform: [{ translateY: size === 'L' ? -3 : -1 }] | ||||
|           width: adaptedFontsize, | ||||
|           height: adaptedFontsize, | ||||
|           transform: [{ translateY: -2 }] | ||||
|         } | ||||
|       }) | ||||
|     }, [mode]) | ||||
|     }, [mode, adaptiveFontsize]) | ||||
|  | ||||
|     return ( | ||||
|       <Text style={styles.text}> | ||||
| @@ -50,6 +70,7 @@ const ParseEmojis = React.memo( | ||||
|                     {/* When emoji starts a paragraph, lineHeight will break */} | ||||
|                     {i === 0 ? <Text> </Text> : null} | ||||
|                     <FastImage | ||||
|                       key={adaptiveFontsize} | ||||
|                       source={{ uri: emojis[emojiIndex].url }} | ||||
|                       style={styles.image} | ||||
|                     /> | ||||
|   | ||||
| @@ -4,7 +4,8 @@ import openLink from '@components/openLink' | ||||
| import ParseEmojis from '@components/Parse/Emojis' | ||||
| import { useNavigation, useRoute } from '@react-navigation/native' | ||||
| import { StackNavigationProp } from '@react-navigation/stack' | ||||
| import { StyleConstants } from '@utils/styles/constants' | ||||
| import { getSettingsFontsize } from '@utils/slices/settingsSlice' | ||||
| import { adaptiveScale, StyleConstants } from '@utils/styles/constants' | ||||
| import layoutAnimation from '@utils/styles/layoutAnimation' | ||||
| import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import { LinearGradient } from 'expo-linear-gradient' | ||||
| @@ -12,6 +13,7 @@ import React, { useCallback, useState } from 'react' | ||||
| import { useTranslation } from 'react-i18next' | ||||
| import { Platform, Pressable, Text, View } from 'react-native' | ||||
| import HTMLView from 'react-native-htmlview' | ||||
| import { useSelector } from 'react-redux' | ||||
|  | ||||
| // Prevent going to the same hashtag multiple times | ||||
| const renderNode = ({ | ||||
| @@ -19,7 +21,8 @@ const renderNode = ({ | ||||
|   theme, | ||||
|   node, | ||||
|   index, | ||||
|   size, | ||||
|   adaptedFontsize, | ||||
|   adaptedLineheight, | ||||
|   navigation, | ||||
|   mentions, | ||||
|   tags, | ||||
| @@ -30,7 +33,8 @@ const renderNode = ({ | ||||
|   theme: any | ||||
|   node: any | ||||
|   index: number | ||||
|   size: 'S' | 'M' | 'L' | ||||
|   adaptedFontsize: number | ||||
|   adaptedLineheight: number | ||||
|   navigation: StackNavigationProp<Nav.TabLocalStackParamList> | ||||
|   mentions?: Mastodon.Mention[] | ||||
|   tags?: Mastodon.Tag[] | ||||
| @@ -52,7 +56,8 @@ const renderNode = ({ | ||||
|               key={index} | ||||
|               style={{ | ||||
|                 color: theme.blue, | ||||
|                 ...StyleConstants.FontStyle[size] | ||||
|                 fontSize: adaptedFontsize, | ||||
|                 lineHeight: adaptedLineheight | ||||
|               }} | ||||
|               onPress={() => { | ||||
|                 analytics('status_hashtag_press') | ||||
| @@ -79,7 +84,8 @@ const renderNode = ({ | ||||
|               key={index} | ||||
|               style={{ | ||||
|                 color: accountIndex !== -1 ? theme.blue : undefined, | ||||
|                 ...StyleConstants.FontStyle[size] | ||||
|                 fontSize: adaptedFontsize, | ||||
|                 lineHeight: adaptedLineheight | ||||
|               }} | ||||
|               onPress={() => { | ||||
|                 analytics('status_mention_press') | ||||
| @@ -108,8 +114,9 @@ const renderNode = ({ | ||||
|             key={index} | ||||
|             style={{ | ||||
|               color: theme.blue, | ||||
|               ...StyleConstants.FontStyle[size], | ||||
|               alignItems: 'center' | ||||
|               alignItems: 'center', | ||||
|               fontSize: adaptedFontsize, | ||||
|               lineHeight: adaptedLineheight | ||||
|             }} | ||||
|             onPress={async () => { | ||||
|               analytics('status_link_press') | ||||
| @@ -125,9 +132,9 @@ const renderNode = ({ | ||||
|               <Icon | ||||
|                 color={theme.blue} | ||||
|                 name='ExternalLink' | ||||
|                 size={StyleConstants.Font.Size[size]} | ||||
|                 size={adaptedFontsize} | ||||
|                 style={{ | ||||
|                   transform: [{ translateY: size === 'L' ? -3 : -1 }] | ||||
|                   transform: [{ translateY: -2 }] | ||||
|                 }} | ||||
|               /> | ||||
|             ) : null} | ||||
| @@ -146,6 +153,7 @@ const renderNode = ({ | ||||
| export interface Props { | ||||
|   content: string | ||||
|   size?: 'S' | 'M' | 'L' | ||||
|   adaptiveSize?: boolean | ||||
|   emojis?: Mastodon.Emoji[] | ||||
|   mentions?: Mastodon.Mention[] | ||||
|   tags?: Mastodon.Tag[] | ||||
| @@ -158,6 +166,7 @@ export interface Props { | ||||
| const ParseHTML: React.FC<Props> = ({ | ||||
|   content, | ||||
|   size = 'M', | ||||
|   adaptiveSize = false, | ||||
|   emojis, | ||||
|   mentions, | ||||
|   tags, | ||||
| @@ -166,6 +175,16 @@ const ParseHTML: React.FC<Props> = ({ | ||||
|   expandHint, | ||||
|   disableDetails = false | ||||
| }) => { | ||||
|   const adaptiveFontsize = useSelector(getSettingsFontsize) | ||||
|   const adaptedFontsize = adaptiveScale( | ||||
|     StyleConstants.Font.Size[size], | ||||
|     adaptiveSize ? adaptiveFontsize : 0 | ||||
|   ) | ||||
|   const adaptedLineheight = adaptiveScale( | ||||
|     StyleConstants.Font.LineHeight[size], | ||||
|     adaptiveSize ? adaptiveFontsize : 0 | ||||
|   ) | ||||
|  | ||||
|   const navigation = useNavigation< | ||||
|     StackNavigationProp<Nav.TabLocalStackParamList> | ||||
|   >() | ||||
| @@ -183,7 +202,8 @@ const ParseHTML: React.FC<Props> = ({ | ||||
|         theme, | ||||
|         node, | ||||
|         index, | ||||
|         size, | ||||
|         adaptedFontsize, | ||||
|         adaptedLineheight, | ||||
|         navigation, | ||||
|         mentions, | ||||
|         tags, | ||||
| @@ -199,6 +219,7 @@ const ParseHTML: React.FC<Props> = ({ | ||||
|           content={children.toString()} | ||||
|           emojis={emojis} | ||||
|           size={size} | ||||
|           adaptiveSize={adaptiveSize} | ||||
|         /> | ||||
|       ) | ||||
|     } else { | ||||
| @@ -208,7 +229,6 @@ const ParseHTML: React.FC<Props> = ({ | ||||
|   const rootComponent = useCallback( | ||||
|     ({ children }) => { | ||||
|       const { t } = useTranslation('componentParse') | ||||
|       const lineHeight = StyleConstants.Font.LineHeight[size] | ||||
|  | ||||
|       const [expandAllow, setExpandAllow] = useState(false) | ||||
|       const [expanded, setExpanded] = useState(false) | ||||
| @@ -234,10 +254,6 @@ const ParseHTML: React.FC<Props> = ({ | ||||
|             children={children} | ||||
|             onTextLayout={onTextLayout} | ||||
|             numberOfLines={expanded ? 999 : numberOfLines + 1} | ||||
|             style={{ | ||||
|               ...StyleConstants.FontStyle[size], | ||||
|               color: theme.primary | ||||
|             }} | ||||
|           /> | ||||
|           {expandAllow ? ( | ||||
|             <Pressable | ||||
| @@ -249,7 +265,7 @@ const ParseHTML: React.FC<Props> = ({ | ||||
|               style={{ | ||||
|                 marginTop: expanded | ||||
|                   ? 0 | ||||
|                   : -lineHeight * (numberOfLines === 0 ? 1 : 2) | ||||
|                   : -adaptedLineheight * (numberOfLines === 0 ? 1 : 2) | ||||
|               }} | ||||
|             > | ||||
|               <LinearGradient | ||||
| @@ -257,10 +273,7 @@ const ParseHTML: React.FC<Props> = ({ | ||||
|                   theme.backgroundGradientStart, | ||||
|                   theme.backgroundGradientEnd | ||||
|                 ]} | ||||
|                 locations={[ | ||||
|                   0, | ||||
|                   lineHeight / (StyleConstants.Font.Size[size] * 5) | ||||
|                 ]} | ||||
|                 locations={[0, adaptedLineheight / (adaptedFontsize * 5)]} | ||||
|                 style={{ | ||||
|                   paddingTop: StyleConstants.Font.Size.S * 2, | ||||
|                   paddingBottom: StyleConstants.Font.Size.S | ||||
|   | ||||
| @@ -28,6 +28,7 @@ const TimelineContent = React.memo( | ||||
|               <ParseHTML | ||||
|                 content={status.spoiler_text} | ||||
|                 size={highlighted ? 'L' : 'M'} | ||||
|                 adaptiveSize | ||||
|                 emojis={status.emojis} | ||||
|                 mentions={status.mentions} | ||||
|                 tags={status.tags} | ||||
| @@ -38,6 +39,7 @@ const TimelineContent = React.memo( | ||||
|             <ParseHTML | ||||
|               content={status.content} | ||||
|               size={highlighted ? 'L' : 'M'} | ||||
|               adaptiveSize | ||||
|               emojis={status.emojis} | ||||
|               mentions={status.mentions} | ||||
|               tags={status.tags} | ||||
| @@ -50,6 +52,7 @@ const TimelineContent = React.memo( | ||||
|           <ParseHTML | ||||
|             content={status.content} | ||||
|             size={highlighted ? 'L' : 'M'} | ||||
|             adaptiveSize | ||||
|             emojis={status.emojis} | ||||
|             mentions={status.mentions} | ||||
|             tags={status.tags} | ||||
|   | ||||
| @@ -14,6 +14,7 @@ export default { | ||||
|   meLists: require('./screens/meLists').default, | ||||
|   meListsList: require('./screens/meListsList').default, | ||||
|   meSettings: require('./screens/meSettings').default, | ||||
|   meSettingsFontsize: require('./screens/meSettingsFontsize').default, | ||||
|   meSettingsPush: require('./screens/meSettingsPush').default, | ||||
|   meSwitch: require('./screens/meSwitch').default, | ||||
|  | ||||
|   | ||||
| @@ -8,6 +8,16 @@ export default { | ||||
|         disabled: 'Disabled' | ||||
|       } | ||||
|     }, | ||||
|     fontsize: { | ||||
|       heading: '$t(meSettingsFontsize:heading)', | ||||
|       content: { | ||||
|         S: '$t(meSettingsFontsize:content.sizes.S)', | ||||
|         M: '$t(meSettingsFontsize:content.sizes.M)', | ||||
|         L: '$t(meSettingsFontsize:content.sizes.L)', | ||||
|         XL: '$t(meSettingsFontsize:content.sizes.XL)', | ||||
|         XXL: '$t(meSettingsFontsize:content.sizes.XXL)' | ||||
|       } | ||||
|     }, | ||||
|     language: { | ||||
|       heading: 'Language', | ||||
|       options: { | ||||
| @@ -50,6 +60,6 @@ export default { | ||||
|       heading: 'Help us improve', | ||||
|       description: 'Collecting only non-user relative usage' | ||||
|     }, | ||||
|     version: 'Version v{{version}}  ({{releaseChannel}})' | ||||
|     version: 'Version v{{version}}' | ||||
|   } | ||||
| } | ||||
|   | ||||
							
								
								
									
										8
									
								
								src/i18n/en/screens/meSettingsFontsize.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/i18n/en/screens/meSettingsFontsize.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| export default { | ||||
|   heading: 'Toot font size', | ||||
|   content: { | ||||
|     showcase: 'Example toot', | ||||
|     availableSizes: 'Available sizes', | ||||
|     sizes: { S: 'S', M: 'M - Default', L: 'L', XL: 'XL', XXL: 'XXL' } | ||||
|   } | ||||
| } | ||||
| @@ -14,6 +14,7 @@ export default { | ||||
|   meLists: require('./screens/meLists').default, | ||||
|   meListsList: require('./screens/meListsList').default, | ||||
|   meSettings: require('./screens/meSettings').default, | ||||
|   meSettingsFontsize: require('./screens/meSettingsFontsize').default, | ||||
|   meSettingsPush: require('./screens/meSettingsPush').default, | ||||
|   meSwitch: require('./screens/meSwitch').default, | ||||
|  | ||||
|   | ||||
| @@ -8,6 +8,16 @@ export default { | ||||
|         disabled: '已关闭' | ||||
|       } | ||||
|     }, | ||||
|     fontsize: { | ||||
|       heading: '$t(meSettingsFontsize:heading)', | ||||
|       content: { | ||||
|         S: '$t(meSettingsFontsize:content.sizes.S)', | ||||
|         M: '$t(meSettingsFontsize:content.sizes.M)', | ||||
|         L: '$t(meSettingsFontsize:content.sizes.L)', | ||||
|         XL: '$t(meSettingsFontsize:content.sizes.XL)', | ||||
|         XXL: '$t(meSettingsFontsize:content.sizes.XXL)' | ||||
|       } | ||||
|     }, | ||||
|     language: { | ||||
|       heading: '切换语言', | ||||
|       options: { | ||||
| @@ -50,6 +60,6 @@ export default { | ||||
|       heading: '帮助我们改进', | ||||
|       description: '收集不与用户相关联的使用信息' | ||||
|     }, | ||||
|     version: '版本 v{{version}} ({{releaseChannel}})' | ||||
|     version: '版本 v{{version}}' | ||||
|   } | ||||
| } | ||||
|   | ||||
							
								
								
									
										8
									
								
								src/i18n/zh-Hans/screens/meSettingsFontsize.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/i18n/zh-Hans/screens/meSettingsFontsize.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| export default { | ||||
|   heading: '嘟文字号', | ||||
|   content: { | ||||
|     showcase: '嘟文示例', | ||||
|     availableSizes: '可选字号', | ||||
|     sizes: { S: '小号', M: '默认', L: '大号', XL: '特大号', XXL: '超大号' } | ||||
|   } | ||||
| } | ||||
| @@ -12,6 +12,7 @@ import React from 'react' | ||||
| import { useTranslation } from 'react-i18next' | ||||
| import { Platform } from 'react-native' | ||||
| import { createNativeStackNavigator } from 'react-native-screens/native-stack' | ||||
| import ScreenMeSettingsFontsize from './Me/Fontsize' | ||||
| import ScreenMeSettingsPush from './Me/Push' | ||||
|  | ||||
| const Stack = createNativeStackNavigator<Nav.TabMeStackParamList>() | ||||
| @@ -115,6 +116,19 @@ const TabMe = React.memo( | ||||
|             headerLeft: () => <HeaderLeft onPress={() => navigation.pop(1)} /> | ||||
|           })} | ||||
|         /> | ||||
|         <Stack.Screen | ||||
|           name='Tab-Me-Settings-Fontsize' | ||||
|           component={ScreenMeSettingsFontsize} | ||||
|           options={({ navigation }: any) => ({ | ||||
|             headerTitle: t('meSettingsFontsize:heading'), | ||||
|             ...(Platform.OS === 'android' && { | ||||
|               headerCenter: () => ( | ||||
|                 <HeaderCenter content={t('meSettingsFontsize:heading')} /> | ||||
|               ) | ||||
|             }), | ||||
|             headerLeft: () => <HeaderLeft onPress={() => navigation.pop(1)} /> | ||||
|           })} | ||||
|         /> | ||||
|         <Stack.Screen | ||||
|           name='Tab-Me-Settings-Push' | ||||
|           component={ScreenMeSettingsPush} | ||||
|   | ||||
							
								
								
									
										184
									
								
								src/screens/Tabs/Me/Fontsize.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								src/screens/Tabs/Me/Fontsize.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,184 @@ | ||||
| import Button from '@components/Button' | ||||
| import haptics from '@components/haptics' | ||||
| import ComponentSeparator from '@components/Separator' | ||||
| import TimelineDefault from '@components/Timeline/Default' | ||||
| import { StackScreenProps } from '@react-navigation/stack' | ||||
| import { | ||||
|   changeFontsize, | ||||
|   getSettingsFontsize, | ||||
|   SettingsState | ||||
| } from '@utils/slices/settingsSlice' | ||||
| import { adaptiveScale, StyleConstants } from '@utils/styles/constants' | ||||
| import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import React, { useMemo } from 'react' | ||||
| import { useTranslation } from 'react-i18next' | ||||
| import { StyleSheet, Text, View } from 'react-native' | ||||
| import { ScrollView } from 'react-native-gesture-handler' | ||||
| import { useDispatch, useSelector } from 'react-redux' | ||||
|  | ||||
| export const mapFontsizeToName = (size: SettingsState['fontsize']) => { | ||||
|   switch (size) { | ||||
|     case -1: | ||||
|       return 'S' | ||||
|     case 0: | ||||
|       return 'M' | ||||
|     case 1: | ||||
|       return 'L' | ||||
|     case 2: | ||||
|       return 'XL' | ||||
|     case 3: | ||||
|       return 'XXL' | ||||
|   } | ||||
| } | ||||
|  | ||||
| const ScreenMeSettingsFontsize: React.FC<StackScreenProps< | ||||
|   Nav.TabMeStackParamList, | ||||
|   'Tab-Me-Settings-Fontsize' | ||||
| >> = () => { | ||||
|   const { mode, theme } = useTheme() | ||||
|   const { t } = useTranslation('meSettingsFontsize') | ||||
|   const initialSize = useSelector(getSettingsFontsize) | ||||
|   const dispatch = useDispatch() | ||||
|  | ||||
|   const item = { | ||||
|     id: 'demo', | ||||
|     uri: 'https://tooot.app', | ||||
|     created_at: new Date(), | ||||
|     sensitive: false, | ||||
|     visibility: 'public', | ||||
|     replies_count: 0, | ||||
|     reblogs_count: 0, | ||||
|     favourites_count: 0, | ||||
|     favourited: true, | ||||
|     reblogged: false, | ||||
|     muted: false, | ||||
|     bookmarked: false, | ||||
|     content: | ||||
|       '<p>- tooot supports multiple accounts<br />- tooot supports browsing external instance<br />- tooot aims to support multiple languages</p>', | ||||
|     reblog: null, | ||||
|     application: { | ||||
|       name: 'tooot', | ||||
|       website: 'https://tooot.app' | ||||
|     }, | ||||
|     account: { | ||||
|       id: 'demo', | ||||
|       url: 'https://tooot.app', | ||||
|       username: 'tooot📱', | ||||
|       acct: 'tooot@xmflsct.com', | ||||
|       display_name: 'tooot📱', | ||||
|       avatar_static: 'https://avatars.githubusercontent.com/u/77554750?s=100' | ||||
|     }, | ||||
|     media_attachments: [], | ||||
|     mentions: [] | ||||
|   } | ||||
|  | ||||
|   const sizesDemo = useMemo(() => { | ||||
|     return ( | ||||
|       <> | ||||
|         {([-1, 0, 1, 2, 3] as [-1, 0, 1, 2, 3]).map(size => ( | ||||
|           <Text | ||||
|             style={[ | ||||
|               styles.size, | ||||
|               { | ||||
|                 fontSize: adaptiveScale(StyleConstants.Font.Size.M, size), | ||||
|                 lineHeight: adaptiveScale( | ||||
|                   StyleConstants.Font.LineHeight.M, | ||||
|                   size | ||||
|                 ), | ||||
|                 fontWeight: | ||||
|                   initialSize === size | ||||
|                     ? StyleConstants.Font.Weight.Bold | ||||
|                     : undefined, | ||||
|                 color: initialSize === size ? theme.primary : theme.secondary, | ||||
|                 borderWidth: StyleSheet.hairlineWidth, | ||||
|                 borderColor: theme.border | ||||
|               } | ||||
|             ]} | ||||
|           > | ||||
|             {t(`content.sizes.${mapFontsizeToName(size)}`)} | ||||
|           </Text> | ||||
|         ))} | ||||
|       </> | ||||
|     ) | ||||
|   }, [mode, initialSize]) | ||||
|  | ||||
|   return ( | ||||
|     <ScrollView scrollEnabled={false}> | ||||
|       <Text style={[styles.header, { color: theme.primary }]}> | ||||
|         {t('content.showcase')} | ||||
|       </Text> | ||||
|       <View> | ||||
|         <ComponentSeparator | ||||
|           extraMarginLeft={-StyleConstants.Spacing.Global.PagePadding} | ||||
|           extraMarginRight={-StyleConstants.Spacing.Global.PagePadding} | ||||
|         /> | ||||
|         <TimelineDefault item={item} disableDetails disableOnPress /> | ||||
|         <ComponentSeparator | ||||
|           extraMarginLeft={-StyleConstants.Spacing.Global.PagePadding} | ||||
|           extraMarginRight={-StyleConstants.Spacing.Global.PagePadding} | ||||
|         /> | ||||
|       </View> | ||||
|       <Text style={[styles.header, { color: theme.primary }]}> | ||||
|         {t('content.availableSizes')} | ||||
|       </Text> | ||||
|       <View style={styles.sizesDemo}>{sizesDemo}</View> | ||||
|       <View style={styles.controls}> | ||||
|         <Button | ||||
|           onPress={() => { | ||||
|             if (initialSize > -1) { | ||||
|               haptics('Light') | ||||
|               dispatch(changeFontsize(initialSize - 1)) | ||||
|             } | ||||
|           }} | ||||
|           type='icon' | ||||
|           content='Minus' | ||||
|           round | ||||
|           disabled={initialSize <= -1} | ||||
|           style={styles.control} | ||||
|         /> | ||||
|         <Button | ||||
|           onPress={() => { | ||||
|             if (initialSize < 3) { | ||||
|               haptics('Light') | ||||
|               dispatch(changeFontsize(initialSize + 1)) | ||||
|             } | ||||
|           }} | ||||
|           type='icon' | ||||
|           content='Plus' | ||||
|           round | ||||
|           disabled={initialSize >= 3} | ||||
|           style={styles.control} | ||||
|         /> | ||||
|       </View> | ||||
|     </ScrollView> | ||||
|   ) | ||||
| } | ||||
|  | ||||
| const styles = StyleSheet.create({ | ||||
|   header: { | ||||
|     ...StyleConstants.FontStyle.M, | ||||
|     textAlign: 'center', | ||||
|     marginTop: StyleConstants.Spacing.M, | ||||
|     marginBottom: StyleConstants.Spacing.M | ||||
|   }, | ||||
|   sizesDemo: { | ||||
|     flexDirection: 'row', | ||||
|     alignItems: 'center', | ||||
|     justifyContent: 'center' | ||||
|   }, | ||||
|   size: { | ||||
|     marginHorizontal: StyleConstants.Spacing.XS, | ||||
|     paddingHorizontal: StyleConstants.Spacing.XS, | ||||
|     marginBottom: StyleConstants.Spacing.M | ||||
|   }, | ||||
|   controls: { | ||||
|     flexDirection: 'row', | ||||
|     alignItems: 'center', | ||||
|     justifyContent: 'center' | ||||
|   }, | ||||
|   control: { | ||||
|     marginHorizontal: StyleConstants.Spacing.S | ||||
|   } | ||||
| }) | ||||
|  | ||||
| export default ScreenMeSettingsFontsize | ||||
| @@ -71,7 +71,7 @@ const ScreenMeSettingsPush: React.FC = () => { | ||||
|           /> | ||||
|         )) | ||||
|       : null | ||||
|   }, [instancePush?.global, instancePush?.alerts, isLoading]) | ||||
|   }, [pushEnabled, instancePush?.global, instancePush?.alerts, isLoading]) | ||||
|  | ||||
|   return ( | ||||
|     <ScrollView> | ||||
|   | ||||
| @@ -6,7 +6,6 @@ import { | ||||
| import { StyleConstants } from '@utils/styles/constants' | ||||
| import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import Constants from 'expo-constants' | ||||
| import * as Updates from 'expo-updates' | ||||
| import React from 'react' | ||||
| import { useTranslation } from 'react-i18next' | ||||
| import { StyleSheet, Text } from 'react-native' | ||||
| @@ -30,10 +29,7 @@ const SettingsAnalytics: React.FC = () => { | ||||
|         } | ||||
|       /> | ||||
|       <Text style={[styles.version, { color: theme.secondary }]}> | ||||
|         {t('content.version', { | ||||
|           version: Constants.manifest.version, | ||||
|           releaseChannel: Updates.releaseChannel | ||||
|         })} | ||||
|         {t('content.version', { version: Constants.manifest.version })} | ||||
|       </Text> | ||||
|     </MenuContainer> | ||||
|   ) | ||||
|   | ||||
| @@ -16,7 +16,8 @@ import { | ||||
|   changeTheme, | ||||
|   getSettingsLanguage, | ||||
|   getSettingsTheme, | ||||
|   getSettingsBrowser | ||||
|   getSettingsBrowser, | ||||
|   getSettingsFontsize | ||||
| } from '@utils/slices/settingsSlice' | ||||
| import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import * as Notifications from 'expo-notifications' | ||||
| @@ -24,6 +25,7 @@ import React from 'react' | ||||
| import { useTranslation } from 'react-i18next' | ||||
| import { Platform } from 'react-native' | ||||
| import { useDispatch, useSelector } from 'react-redux' | ||||
| import { mapFontsizeToName } from '../Fontsize' | ||||
|  | ||||
| const SettingsApp: React.FC = () => { | ||||
|   const navigation = useNavigation() | ||||
| @@ -34,6 +36,7 @@ const SettingsApp: React.FC = () => { | ||||
|  | ||||
|   const instances = useSelector(getInstances, () => true) | ||||
|   const instanceActive = useSelector(getInstanceActive) | ||||
|   const settingsFontsize = useSelector(getSettingsFontsize) | ||||
|   const settingsLanguage = useSelector(getSettingsLanguage) | ||||
|   const settingsTheme = useSelector(getSettingsTheme) | ||||
|   const settingsBrowser = useSelector(getSettingsBrowser) | ||||
| @@ -45,18 +48,30 @@ const SettingsApp: React.FC = () => { | ||||
|   return ( | ||||
|     <MenuContainer> | ||||
|       {instanceActive !== -1 ? ( | ||||
|         <MenuRow | ||||
|           title={t('content.push.heading')} | ||||
|           content={ | ||||
|             instancePush?.global.value | ||||
|               ? t('content.push.content.enabled') | ||||
|               : t('content.push.content.disabled') | ||||
|           } | ||||
|           iconBack='ChevronRight' | ||||
|           onPress={() => { | ||||
|             navigation.navigate('Tab-Me-Settings-Push') | ||||
|           }} | ||||
|         /> | ||||
|         <> | ||||
|           <MenuRow | ||||
|             title={t('content.push.heading')} | ||||
|             content={ | ||||
|               instancePush?.global.value | ||||
|                 ? t('content.push.content.enabled') | ||||
|                 : t('content.push.content.disabled') | ||||
|             } | ||||
|             iconBack='ChevronRight' | ||||
|             onPress={() => { | ||||
|               navigation.navigate('Tab-Me-Settings-Push') | ||||
|             }} | ||||
|           /> | ||||
|           <MenuRow | ||||
|             title={t('content.fontsize.heading')} | ||||
|             content={t( | ||||
|               `content.fontsize.content.${mapFontsizeToName(settingsFontsize)}` | ||||
|             )} | ||||
|             iconBack='ChevronRight' | ||||
|             onPress={() => { | ||||
|               navigation.navigate('Tab-Me-Settings-Fontsize') | ||||
|             }} | ||||
|           /> | ||||
|         </> | ||||
|       ) : null} | ||||
|       <MenuRow | ||||
|         title={t('content.language.heading')} | ||||
|   | ||||
| @@ -46,7 +46,7 @@ const SettingsDev: React.FC = () => { | ||||
|                 .concat(['Cancel']), | ||||
|               cancelButtonIndex: instances.length | ||||
|             }, | ||||
|             buttonIndex => {} | ||||
|             () => {} | ||||
|           ) | ||||
|         } | ||||
|       /> | ||||
|   | ||||
| @@ -3,7 +3,7 @@ import TimelineDefault from '@components/Timeline/Default' | ||||
| import { useNavigation } from '@react-navigation/native' | ||||
| import { QueryKeyTimeline } from '@utils/queryHooks/timeline' | ||||
| import { findIndex } from 'lodash' | ||||
| import React, { useCallback, useEffect, useRef, useState } from 'react' | ||||
| import React, { useCallback, useEffect, useRef } from 'react' | ||||
| import { FlatList } from 'react-native' | ||||
| import { InfiniteQueryObserver, useQueryClient } from 'react-query' | ||||
| import { SharedTootProp } from './sharedScreens' | ||||
| @@ -20,7 +20,6 @@ const TabSharedToot: React.FC<SharedTootProp> = ({ | ||||
|  | ||||
|   const flRef = useRef<FlatList>(null) | ||||
|  | ||||
|   const [testState, setTestState] = useState(false) | ||||
|   const scrolled = useRef(false) | ||||
|   const navigation = useNavigation() | ||||
|   const queryClient = useQueryClient() | ||||
| @@ -28,7 +27,6 @@ const TabSharedToot: React.FC<SharedTootProp> = ({ | ||||
|   useEffect(() => { | ||||
|     const unsubscribe = observer.subscribe(result => { | ||||
|       if (result.isSuccess) { | ||||
|         setTestState(true) | ||||
|         const flattenData = result.data?.pages | ||||
|           ? // @ts-ignore | ||||
|             result.data.pages.flatMap(d => [...d.body]) | ||||
| @@ -42,7 +40,7 @@ const TabSharedToot: React.FC<SharedTootProp> = ({ | ||||
|           const pointer = findIndex(flattenData, ['id', toot.id]) | ||||
|           setTimeout(() => { | ||||
|             flRef.current?.scrollToIndex({ | ||||
|               index: pointer, | ||||
|               index: pointer === -1 ? 0 : pointer, | ||||
|               viewOffset: 100 | ||||
|             }) | ||||
|           }, 500) | ||||
| @@ -79,7 +77,7 @@ const TabSharedToot: React.FC<SharedTootProp> = ({ | ||||
|     <Timeline | ||||
|       flRef={flRef} | ||||
|       queryKey={queryKey} | ||||
|       customProps={{ renderItem, ...(testState && onScrollToIndexFailed) }} | ||||
|       customProps={{ renderItem, onScrollToIndexFailed }} | ||||
|       disableRefresh | ||||
|       disableInfinity | ||||
|     /> | ||||
|   | ||||
| @@ -18,6 +18,7 @@ export const changeAnalytics = createAsyncThunk( | ||||
| ) | ||||
|  | ||||
| export type SettingsState = { | ||||
|   fontsize: -1 | 0 | 1 | 2 | 3 | ||||
|   language: keyof availableLanguages | ||||
|   theme: 'light' | 'dark' | 'auto' | ||||
|   browser: 'internal' | 'external' | ||||
| @@ -25,6 +26,7 @@ export type SettingsState = { | ||||
| } | ||||
|  | ||||
| export const settingsInitialState = { | ||||
|   fontsize: 0, | ||||
|   notification: { | ||||
|     enabled: false | ||||
|   }, | ||||
| @@ -46,6 +48,12 @@ const settingsSlice = createSlice({ | ||||
|   name: 'settings', | ||||
|   initialState: settingsInitialState as SettingsState, | ||||
|   reducers: { | ||||
|     changeFontsize: ( | ||||
|       state, | ||||
|       action: PayloadAction<SettingsState['fontsize']> | ||||
|     ) => { | ||||
|       state.fontsize = action.payload | ||||
|     }, | ||||
|     changeLanguage: ( | ||||
|       state, | ||||
|       action: PayloadAction<NonNullable<SettingsState['language']>> | ||||
| @@ -72,6 +80,8 @@ const settingsSlice = createSlice({ | ||||
|   } | ||||
| }) | ||||
|  | ||||
| export const getSettingsFontsize = (state: RootState) => | ||||
|   state.settings.fontsize || 0 | ||||
| export const getSettingsLanguage = (state: RootState) => state.settings.language | ||||
| export const getSettingsTheme = (state: RootState) => state.settings.theme | ||||
| export const getSettingsBrowser = (state: RootState) => state.settings.browser | ||||
| @@ -79,6 +89,7 @@ export const getSettingsAnalytics = (state: RootState) => | ||||
|   state.settings.analytics | ||||
|  | ||||
| export const { | ||||
|   changeFontsize, | ||||
|   changeLanguage, | ||||
|   changeTheme, | ||||
|   changeBrowser | ||||
|   | ||||
| @@ -7,25 +7,25 @@ const guidelineBaseWidth = 375 | ||||
|  | ||||
| const scale = (size: number) => (width / guidelineBaseWidth) * size | ||||
| // const verticalScale = (size: number) => (height / guidelineBaseHeight) * size | ||||
| const moderateScale = (size: number, factor = 0.5) => | ||||
| export const adaptiveScale = (size: number, factor: number = 0) => | ||||
|   size + (scale(size) - size) * factor | ||||
|  | ||||
| const Base = 4 | ||||
|  | ||||
| export const StyleConstants = { | ||||
|   Font: { | ||||
|     Size: { S: moderateScale(14), M: moderateScale(16), L: moderateScale(18) }, | ||||
|     Size: { S: 14, M: 16, L: 18 }, | ||||
|     LineHeight: { | ||||
|       S: moderateScale(20), | ||||
|       M: moderateScale(22), | ||||
|       L: moderateScale(30) | ||||
|       S: 20, | ||||
|       M: 22, | ||||
|       L: 30 | ||||
|     }, | ||||
|     Weight: { Normal: '400' as '400', Bold: '600' as '600' } | ||||
|   }, | ||||
|   FontStyle: { | ||||
|     S: { fontSize: moderateScale(14), lineHeight: moderateScale(20) }, | ||||
|     M: { fontSize: moderateScale(16), lineHeight: moderateScale(22) }, | ||||
|     L: { fontSize: moderateScale(20), lineHeight: moderateScale(30) } | ||||
|     S: { fontSize: 14, lineHeight: 20 }, | ||||
|     M: { fontSize: 16, lineHeight: 22 }, | ||||
|     L: { fontSize: 20, lineHeight: 30 } | ||||
|   }, | ||||
|  | ||||
|   Spacing: { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user