Restructure some files

This commit is contained in:
Zhiyuan Zheng 2020-12-29 16:19:04 +01:00
parent b92a01e2a4
commit e841409523
No known key found for this signature in database
GPG Key ID: 078A93AB607D85E0
18 changed files with 331 additions and 285 deletions

View File

@ -1,3 +1,4 @@
import 'react-native-gesture-handler'
import NetInfo from '@react-native-community/netinfo' import NetInfo from '@react-native-community/netinfo'
import client from '@root/api/client' import client from '@root/api/client'
import Index from '@root/Index' import Index from '@root/Index'
@ -5,9 +6,9 @@ import { persistor, store } from '@root/store'
import { resetLocal } from '@root/utils/slices/instancesSlice' import { resetLocal } from '@root/utils/slices/instancesSlice'
import ThemeManager from '@utils/styles/ThemeManager' import ThemeManager from '@utils/styles/ThemeManager'
import chalk from 'chalk' import chalk from 'chalk'
import * as Analytics from 'expo-firebase-analytics'
import * as SplashScreen from 'expo-splash-screen' import * as SplashScreen from 'expo-splash-screen'
import React, { useCallback, useEffect, useState } from 'react' import React, { useCallback, useEffect, useState } from 'react'
import { Platform, Text } from 'react-native'
import { enableScreens } from 'react-native-screens' import { enableScreens } from 'react-native-screens'
import { onlineManager, QueryClient, QueryClientProvider } from 'react-query' import { onlineManager, QueryClient, QueryClientProvider } from 'react-query'
import { Provider } from 'react-redux' import { Provider } from 'react-redux'
@ -30,6 +31,8 @@ const startingLog = (type: 'log' | 'warn' | 'error', message: string) => {
} }
if (__DEV__) { if (__DEV__) {
Analytics.setDebugModeEnabled(true)
startingLog('log', 'initializing wdyr') startingLog('log', 'initializing wdyr')
const whyDidYouRender = require('@welldone-software/why-did-you-render') const whyDidYouRender = require('@welldone-software/why-did-you-render')
whyDidYouRender(React, { whyDidYouRender(React, {

View File

@ -5,7 +5,7 @@ export default (): ExpoConfig => ({
description: 'This is a description', description: 'This is a description',
slug: 'mastodon-app', slug: 'mastodon-app',
privacy: 'hidden', privacy: 'hidden',
version: '1.0.0', version: '0.1.0',
platforms: ['ios'], platforms: ['ios'],
orientation: 'portrait', orientation: 'portrait',
userInterfaceStyle: 'automatic', userInterfaceStyle: 'automatic',
@ -33,6 +33,18 @@ export default (): ExpoConfig => ({
// } // }
// }, // },
assetBundlePatterns: ['assets/*'], assetBundlePatterns: ['assets/*'],
hooks: {
postPublish: [
{
file: 'sentry-expo/upload-sourcemaps'
// config: {
// organization: "your sentry organization's short name here",
// project: "your sentry project's name here",
// authToken: 'your auth token here'
// }
}
]
},
web: { web: {
config: { config: {
firebase: { firebase: {

View File

@ -17,7 +17,7 @@
"@react-navigation/bottom-tabs": "^5.11.2", "@react-navigation/bottom-tabs": "^5.11.2",
"@react-navigation/native": "^5.8.10", "@react-navigation/native": "^5.8.10",
"@reduxjs/toolkit": "^1.5.0", "@reduxjs/toolkit": "^1.5.0",
"axios": "^0.21.0", "axios": "^0.21.1",
"buffer": "^6.0.3", "buffer": "^6.0.3",
"expo": "^40.0.0", "expo": "^40.0.0",
"expo-auth-session": "~3.0.0", "expo-auth-session": "~3.0.0",
@ -45,7 +45,7 @@
"pretty-bytes": "^5.5.0", "pretty-bytes": "^5.5.0",
"react": "16.13.1", "react": "16.13.1",
"react-dom": "16.13.1", "react-dom": "16.13.1",
"react-i18next": "^11.8.4", "react-i18next": "^11.8.5",
"react-native": "https://github.com/expo/react-native/archive/sdk-40.0.0.tar.gz", "react-native": "https://github.com/expo/react-native/archive/sdk-40.0.0.tar.gz",
"react-native-animated-spinkit": "^1.4.2", "react-native-animated-spinkit": "^1.4.2",
"react-native-expo-image-cache": "^4.1.0", "react-native-expo-image-cache": "^4.1.0",
@ -58,9 +58,9 @@
"react-native-shimmer-placeholder": "^2.0.6", "react-native-shimmer-placeholder": "^2.0.6",
"react-native-svg": "12.1.0", "react-native-svg": "12.1.0",
"react-native-tab-view": "^2.15.2", "react-native-tab-view": "^2.15.2",
"react-native-toast-message": "^1.3.4", "react-native-toast-message": "^1.4.2",
"react-navigation": "^4.4.3", "react-navigation": "^4.4.3",
"react-query": "^3.3.2", "react-query": "^3.5.6",
"react-redux": "^7.2.2", "react-redux": "^7.2.2",
"redux-persist": "^6.0.0", "redux-persist": "^6.0.0",
"redux-persist-expo-securestore": "^2.0.0", "redux-persist-expo-securestore": "^2.0.0",
@ -87,13 +87,13 @@
"@types/react-navigation": "^3.4.0", "@types/react-navigation": "^3.4.0",
"@types/react-redux": "^7.1.12", "@types/react-redux": "^7.1.12",
"@types/react-test-renderer": "^17.0.0", "@types/react-test-renderer": "^17.0.0",
"@welldone-software/why-did-you-render": "^6.0.3", "@welldone-software/why-did-you-render": "^6.0.4",
"babel-plugin-module-resolver": "^4.1.0", "babel-plugin-module-resolver": "^4.1.0",
"chalk": "^4.1.0", "chalk": "^4.1.0",
"jest": "^26.6.3", "jest": "^26.6.3",
"jest-expo": "^40.0.1", "jest-expo": "^40.0.1",
"react-test-renderer": "^16.13.1", "react-test-renderer": "^16.13.1",
"typescript": "~4.0.0" "typescript": "~4.1.3"
}, },
"jest": { "jest": {
"preset": "jest-expo", "preset": "jest-expo",

View File

@ -1,37 +1,30 @@
import 'react-native-gesture-handler' import client from '@api/client'
import { Feather } from '@expo/vector-icons'
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs' import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
import { import {
NavigationContainer, NavigationContainer,
NavigationContainerRef NavigationContainerRef
} from '@react-navigation/native' } from '@react-navigation/native'
import * as Analytics from 'expo-firebase-analytics'
import React, { useEffect, useRef, useState } from 'react'
import { StatusBar } from 'react-native'
import Toast from 'react-native-toast-message'
import { Feather } from '@expo/vector-icons'
import ScreenLocal from '@screens/Local' import ScreenLocal from '@screens/Local'
import ScreenPublic from '@screens/Public' import ScreenPublic from '@screens/Public'
import ScreenNotifications from '@screens/Notifications' import ScreenNotifications from '@screens/Notifications'
import ScreenMe from '@screens/Me' import ScreenMe from '@screens/Me'
import { timelineFetch } from '@utils/fetches/timelineFetch'
import { themes } from '@utils/styles/themes'
import { useTheme } from '@utils/styles/ThemeManager'
import getCurrentTab from '@utils/getCurrentTab'
import { toast, toastConfig } from '@components/toast'
import { useTranslation } from 'react-i18next'
import { useDispatch, useSelector } from 'react-redux'
import { import {
getLocalNotification, getLocalNotification,
getLocalUrl, getLocalUrl,
updateLocalAccountPreferences, updateLocalAccountPreferences,
updateNotification updateNotification
} from '@utils/slices/instancesSlice' } from '@utils/slices/instancesSlice'
import { useTheme } from '@utils/styles/ThemeManager'
import { themes } from '@utils/styles/themes'
import { toast, toastConfig } from '@components/toast'
import * as Analytics from 'expo-firebase-analytics'
import React, { useCallback, useEffect, useMemo, useRef } from 'react'
import { StatusBar } from 'react-native'
import Toast from 'react-native-toast-message'
import { useDispatch, useSelector } from 'react-redux'
import { useInfiniteQuery } from 'react-query' import { useInfiniteQuery } from 'react-query'
import client from './api/client'
import { timelineFetch } from './utils/fetches/timelineFetch'
import { useNetInfo } from '@react-native-community/netinfo'
const Tab = createBottomTabNavigator<RootStackParamList>() const Tab = createBottomTabNavigator<RootStackParamList>()
@ -50,25 +43,27 @@ export interface Props {
const Index: React.FC<Props> = ({ localCorrupt }) => { const Index: React.FC<Props> = ({ localCorrupt }) => {
const dispatch = useDispatch() const dispatch = useDispatch()
const localInstance = useSelector(getLocalUrl) const localInstance = useSelector(getLocalUrl)
const { i18n } = useTranslation()
const { mode, theme } = useTheme() const { mode, theme } = useTheme()
enum barStyle { enum barStyle {
light = 'dark-content', light = 'dark-content',
dark = 'light-content' dark = 'light-content'
} }
const isConnected = useNetInfo().isConnected const routeNameRef = useRef<string | undefined>()
const [firstRender, setFirstRender] = useState(false) const navigationRef = useRef<NavigationContainerRef>(null)
useEffect(() => {
if (firstRender) { // const isConnected = useNetInfo().isConnected
// bug in netInfo on first render as false // const [firstRender, setFirstRender] = useState(false)
if (isConnected !== false) { // useEffect(() => {
toast({ type: 'error', content: '手机🈚️网络', autoHide: false }) // if (firstRender) {
} // // bug in netInfo on first render as false
} else { // if (isConnected !== false) {
setFirstRender(true) // toast({ type: 'error', content: '手机🈚️网络', autoHide: false })
} // }
}, [isConnected, firstRender]) // } else {
// setFirstRender(true)
// }
// }, [isConnected, firstRender])
// On launch display login credentials corrupt information // On launch display login credentials corrupt information
useEffect(() => { useEffect(() => {
@ -84,8 +79,8 @@ const Index: React.FC<Props> = ({ localCorrupt }) => {
}, [localCorrupt]) }, [localCorrupt])
// On launch check if there is any unread announcements // On launch check if there is any unread announcements
const navigationRef = useRef<NavigationContainerRef>(null)
useEffect(() => { useEffect(() => {
console.log('Checking announcements')
localInstance && localInstance &&
client({ client({
method: 'get', method: 'get',
@ -99,7 +94,7 @@ const Index: React.FC<Props> = ({ localCorrupt }) => {
}) })
} }
}) })
.catch(() => null) .catch(() => {})
}, []) }, [])
// On launch check if there is any unread noficiations // On launch check if there is any unread noficiations
@ -145,104 +140,149 @@ const Index: React.FC<Props> = ({ localCorrupt }) => {
} }
}, []) }, [])
// Callbacks
const navigationContainerOnReady = useCallback(
() =>
(routeNameRef.current = navigationRef.current?.getCurrentRoute()?.name),
[]
)
const navigationContainerOnStateChange = useCallback(() => {
const previousRouteName = routeNameRef.current
const currentRouteName = navigationRef.current?.getCurrentRoute()?.name
if (previousRouteName !== currentRouteName) {
Analytics.setCurrentScreen(currentRouteName)
}
routeNameRef.current = currentRouteName
}, [])
const tabNavigatorScreenOptions = useCallback(
({ route }) => ({
tabBarIcon: ({
focused,
color,
size
}: {
focused: boolean
color: string
size: number
}) => {
let name: any
let updateColor: string = color
switch (route.name) {
case 'Screen-Local':
name = 'home'
break
case 'Screen-Public':
name = 'globe'
!focused && (updateColor = theme.secondary)
break
case 'Screen-Post':
name = 'plus'
break
case 'Screen-Notifications':
name = 'bell'
break
case 'Screen-Me':
name = focused ? 'meh' : 'smile'
!focused && (updateColor = theme.secondary)
break
default:
name = 'alert-octagon'
break
}
return <Feather name={name} size={size} color={updateColor} />
}
}),
[]
)
const tabNavigatorTabBarOptions = useMemo(
() => ({
activeTintColor: theme.primary,
inactiveTintColor: localInstance ? theme.secondary : theme.disabled,
showLabel: false
}),
[]
)
const tabScreenLocalListeners = useCallback(
() => ({
tabPress: (e: any) => {
if (!localInstance) {
e.preventDefault()
}
}
}),
[]
)
const tabScreenComposeListeners = useCallback(
({ navigation }) => ({
tabPress: (e: any) => {
e.preventDefault()
if (localInstance) {
navigation.navigate('Screen-Shared-Compose')
}
}
}),
[]
)
const tabScreenComposeComponent = useCallback(() => null, [])
const tabScreenNotificationsListeners = useCallback(
() => ({
tabPress: (e: any) => {
if (!localInstance) {
e.preventDefault()
}
}
}),
[]
)
const tabScreenNotificationsOptions = useMemo(
() => ({
tabBarBadge: prevNotification && prevNotification.unread ? '' : undefined,
tabBarBadgeStyle: {
transform: [{ scale: 0.5 }],
backgroundColor: theme.red
}
}),
[]
)
return ( return (
<> <>
<StatusBar barStyle={barStyle[mode]} /> <StatusBar barStyle={barStyle[mode]} />
<NavigationContainer <NavigationContainer
ref={navigationRef} ref={navigationRef}
theme={themes[mode]} theme={themes[mode]}
key={i18n.language} // key={i18n.language}
onStateChange={state => { onReady={navigationContainerOnReady}
Analytics.setCurrentScreen(state?.routes[state.index].name) onStateChange={navigationContainerOnStateChange}
}}
> >
<Tab.Navigator <Tab.Navigator
initialRouteName={localInstance ? 'Screen-Local' : 'Screen-Public'} initialRouteName={localInstance ? 'Screen-Local' : 'Screen-Public'}
screenOptions={({ route }) => ({ screenOptions={tabNavigatorScreenOptions}
tabBarIcon: ({ focused, color, size }) => { tabBarOptions={tabNavigatorTabBarOptions}
let name: any
let updateColor: string = color
switch (route.name) {
case 'Screen-Local':
name = 'home'
break
case 'Screen-Public':
name = 'globe'
!focused && (updateColor = theme.secondary)
break
case 'Screen-Post':
name = 'plus'
break
case 'Screen-Notifications':
name = 'bell'
break
case 'Screen-Me':
name = focused ? 'meh' : 'smile'
!focused && (updateColor = theme.secondary)
break
default:
name = 'alert-octagon'
break
}
return <Feather name={name} size={size} color={updateColor} />
}
})}
tabBarOptions={{
activeTintColor: theme.primary,
inactiveTintColor: localInstance ? theme.secondary : theme.disabled,
showLabel: false
}}
> >
<Tab.Screen <Tab.Screen
name='Screen-Local' name='Screen-Local'
component={ScreenLocal} component={ScreenLocal}
listeners={({ navigation }) => ({ listeners={tabScreenLocalListeners}
tabPress: e => {
if (!localInstance) {
e.preventDefault()
}
}
})}
/> />
<Tab.Screen name='Screen-Public' component={ScreenPublic} /> <Tab.Screen name='Screen-Public' component={ScreenPublic} />
<Tab.Screen <Tab.Screen
name='Screen-Post' name='Screen-Post'
listeners={({ navigation }) => ({ component={tabScreenComposeComponent}
tabPress: e => { listeners={tabScreenComposeListeners}
e.preventDefault() />
if (localInstance) {
navigation.navigate(getCurrentTab(navigation), {
screen: 'Screen-Shared-Compose'
})
}
}
})}
>
{() => null}
</Tab.Screen>
<Tab.Screen <Tab.Screen
name='Screen-Notifications' name='Screen-Notifications'
component={ScreenNotifications} component={ScreenNotifications}
options={{ listeners={tabScreenNotificationsListeners}
tabBarBadge: options={tabScreenNotificationsOptions}
prevNotification && prevNotification.unread ? '' : undefined,
tabBarBadgeStyle: {
transform: [{ scale: 0.5 }],
backgroundColor: theme.red
}
}}
listeners={() => ({
tabPress: e => {
if (!localInstance) {
e.preventDefault()
}
}
})}
/> />
<Tab.Screen name='Screen-Me' component={ScreenMe} /> <Tab.Screen name='Screen-Me' component={ScreenMe} />
</Tab.Navigator> </Tab.Navigator>
<Toast ref={(ref: any) => Toast.setRef(ref)} config={toastConfig} /> <Toast ref={Toast.setRef} config={toastConfig} />
</NavigationContainer> </NavigationContainer>
</> </>
) )

View File

@ -3,7 +3,7 @@ import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import { ColorDefinitions } from '@utils/styles/themes' import { ColorDefinitions } from '@utils/styles/themes'
import React, { useMemo } from 'react' import React, { useMemo } from 'react'
import { Pressable, StyleSheet, Text, View } from 'react-native' import { Pressable, StyleSheet, Switch, Text, View } from 'react-native'
import { Chase } from 'react-native-animated-spinkit' import { Chase } from 'react-native-animated-spinkit'
export interface Props { export interface Props {
@ -11,8 +11,13 @@ export interface Props {
iconFrontColor?: ColorDefinitions iconFrontColor?: ColorDefinitions
title: string title: string
description?: string
content?: string content?: string
switchValue?: boolean
switchDisabled?: boolean
switchOnValueChange?: () => void
iconBack?: 'chevron-right' | 'check' iconBack?: 'chevron-right' | 'check'
iconBackColor?: ColorDefinitions iconBackColor?: ColorDefinitions
@ -24,7 +29,11 @@ const MenuRow: React.FC<Props> = ({
iconFront, iconFront,
iconFrontColor = 'primary', iconFrontColor = 'primary',
title, title,
description,
content, content,
switchValue,
switchDisabled,
switchOnValueChange,
iconBack, iconBack,
iconBackColor = 'secondary', iconBackColor = 'secondary',
loading = false, loading = false,
@ -61,45 +70,59 @@ const MenuRow: React.FC<Props> = ({
style={styles.iconFront} style={styles.iconFront}
/> />
)} )}
<Text <View style={styles.main}>
style={[styles.text, { color: theme.primary }]} <Text
numberOfLines={1} style={[styles.title, { color: theme.primary }]}
> numberOfLines={1}
{title} >
</Text> {title}
</View> </Text>
{(content || iconBack) && ( {description ? (
<View style={styles.back}> <Text style={[styles.description, { color: theme.secondary }]}>
{content && content.length ? ( {description}
<> </Text>
<Text
style={[
styles.content,
{
color: theme.secondary,
opacity: !iconBack && loading ? 0 : 1
}
]}
numberOfLines={1}
>
{content}
</Text>
{loading && !iconBack && loadingSpinkit}
</>
) : null} ) : null}
{iconBack && (
<>
<Feather
name={iconBack}
size={StyleConstants.Font.Size.M + 2}
color={theme[iconBackColor]}
style={[styles.iconBack, { opacity: loading ? 0 : 1 }]}
/>
{loading && loadingSpinkit}
</>
)}
</View> </View>
)} </View>
<View style={styles.back}>
{content && content.length ? (
<>
<Text
style={[
styles.content,
{
color: theme.secondary,
opacity: !iconBack && loading ? 0 : 1
}
]}
numberOfLines={1}
>
{content}
</Text>
{loading && !iconBack && loadingSpinkit}
</>
) : null}
{switchValue !== undefined ? (
<Switch
value={switchValue}
onValueChange={switchOnValueChange}
disabled={switchDisabled}
trackColor={{ true: theme.blue, false: theme.disabled }}
/>
) : null}
{iconBack ? (
<>
<Feather
name={iconBack}
size={StyleConstants.Font.Size.M + 2}
color={theme[iconBackColor]}
style={[styles.iconBack, { opacity: loading ? 0 : 1 }]}
/>
{loading && loadingSpinkit}
</>
) : null}
</View>
</View> </View>
</Pressable> </Pressable>
) )
@ -131,10 +154,16 @@ const styles = StyleSheet.create({
iconFront: { iconFront: {
marginRight: 8 marginRight: 8
}, },
text: { main: {
flex: 1, flex: 1
},
title: {
...StyleConstants.FontStyle.M ...StyleConstants.FontStyle.M
}, },
description: {
...StyleConstants.FontStyle.S,
marginTop: StyleConstants.Spacing.XS
},
content: { content: {
...StyleConstants.FontStyle.M ...StyleConstants.FontStyle.M
}, },

View File

@ -76,6 +76,7 @@ const renderNode = ({
} }
} else { } else {
const domain = href.split(new RegExp(/:\/\/(.[^\/]+)/)) const domain = href.split(new RegExp(/:\/\/(.[^\/]+)/))
// Need example here
const content = node.children && node.children[0].data const content = node.children && node.children[0].data
const shouldBeTag = const shouldBeTag =
tags && tags.filter(tag => `#${tag.name}` === content).length > 0 tags && tags.filter(tag => `#${tag.name}` === content).length > 0

View File

@ -9,7 +9,6 @@ import sharedScreens from '@screens/Shared/sharedScreens'
import { getLocalUrl, getRemoteUrl } from '@utils/slices/instancesSlice' import { getLocalUrl, getRemoteUrl } from '@utils/slices/instancesSlice'
import { useTheme } from '@utils/styles/ThemeManager' import { useTheme } from '@utils/styles/ThemeManager'
import { useNavigation } from '@react-navigation/native' import { useNavigation } from '@react-navigation/native'
import getCurrentTab from '@utils/getCurrentTab'
import { HeaderRight } from './Header' import { HeaderRight } from './Header'
import { TabView } from 'react-native-tab-view' import { TabView } from 'react-native-tab-view'
@ -28,9 +27,7 @@ const Timelines: React.FC<Props> = ({ name, content }) => {
const [segment, setSegment] = useState(0) const [segment, setSegment] = useState(0)
const onPressSearch = useCallback(() => { const onPressSearch = useCallback(() => {
navigation.navigate(getCurrentTab(navigation), { navigation.navigate('Screen-Shared-Search')
screen: 'Screen-Shared-Search'
})
}, []) }, [])
const routes = content const routes = content

View File

@ -8,7 +8,6 @@ import { useTheme } from '@utils/styles/ThemeManager'
import { toast } from '@components/toast' import { toast } from '@components/toast'
import { StyleConstants } from '@utils/styles/constants' import { StyleConstants } from '@utils/styles/constants'
import { useNavigation } from '@react-navigation/native' import { useNavigation } from '@react-navigation/native'
import getCurrentTab from '@utils/getCurrentTab'
import { findIndex } from 'lodash' import { findIndex } from 'lodash'
import { TimelineData } from '../../Timeline' import { TimelineData } from '../../Timeline'
@ -124,13 +123,10 @@ const TimelineActions: React.FC<Props> = ({ queryKey, status, reblog }) => {
const onPressReply = useCallback( const onPressReply = useCallback(
() => () =>
navigation.navigate(getCurrentTab(navigation), { navigation.navigate('Screen-Shared-Compose', {
screen: 'Screen-Shared-Compose', type: 'reply',
params: { incomingStatus: status,
type: 'reply', visibilityLock: status.visibility === 'direct'
incomingStatus: status,
visibilityLock: status.visibility === 'direct'
}
}), }),
[] []
) )

View File

@ -5,7 +5,6 @@ import { useMutation, useQueryClient } from 'react-query'
import client from '@api/client' import client from '@api/client'
import { MenuContainer, MenuHeader, MenuRow } from '@components/Menu' import { MenuContainer, MenuHeader, MenuRow } from '@components/Menu'
import { toast } from '@components/toast' import { toast } from '@components/toast'
import getCurrentTab from '@utils/getCurrentTab'
import { TimelineData } from '@root/components/Timelines/Timeline' import { TimelineData } from '@root/components/Timelines/Timeline'
import { findIndex } from 'lodash' import { findIndex } from 'lodash'
@ -155,9 +154,9 @@ const HeaderDefaultActionsStatus: React.FC<Props> = ({
.then(res => { .then(res => {
queryClient.invalidateQueries(queryKey) queryClient.invalidateQueries(queryKey)
setBottomSheetVisible(false) setBottomSheetVisible(false)
navigation.navigate(getCurrentTab(navigation), { navigation.navigate('Screen-Shared-Compose', {
screen: 'Screen-Shared-Compose', type: 'edit',
params: { type: 'edit', incomingStatus: res.body } incomingStatus: res.body
}) })
}) })
.catch(() => { .catch(() => {

View File

@ -63,7 +63,7 @@ const ToastBase = ({ config }: { config: Config }) => {
<SafeAreaView <SafeAreaView
style={[ style={[
styles.base, styles.base,
{ backgroundColor: theme.background, shadowColor: theme.primary } { backgroundColor: theme.background, borderBottomColor: theme.primary }
]} ]}
> >
<View style={styles.container}> <View style={styles.container}>
@ -97,15 +97,14 @@ const toastConfig = {
const styles = StyleSheet.create({ const styles = StyleSheet.create({
base: { base: {
width: '100%', width: '100%',
shadowOpacity: 1, borderBottomWidth: 1
shadowRadius: 6
}, },
container: { container: {
flex: 1, flex: 1,
flexDirection: 'row', flexDirection: 'row',
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
padding: StyleConstants.Spacing.M padding: StyleConstants.Spacing.L
}, },
texts: { texts: {
marginLeft: StyleConstants.Spacing.S marginLeft: StyleConstants.Spacing.S

View File

@ -29,6 +29,10 @@ export default {
cache: { cache: {
heading: '清空缓存' heading: '清空缓存'
}, },
analytics: {
heading: '帮助我们改进',
description: '允许我们收集不与用户相关联的使用信息'
},
copyrights: { copyrights: {
heading: '版权信息' heading: '版权信息'
}, },

View File

@ -1,20 +1,22 @@
import prettyBytes from 'pretty-bytes'
import React, { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { ActionSheetIOS, StyleSheet, Text } from 'react-native'
import { CacheManager } from 'react-native-expo-image-cache'
import { useDispatch, useSelector } from 'react-redux'
import { MenuContainer, MenuRow } from '@components/Menu' import { MenuContainer, MenuRow } from '@components/Menu'
import { import {
changeAnalytics,
changeBrowser, changeBrowser,
changeLanguage, changeLanguage,
changeTheme, changeTheme,
getSettingsAnalytics,
getSettingsBrowser, getSettingsBrowser,
getSettingsLanguage, getSettingsLanguage,
getSettingsTheme getSettingsTheme
} from '@utils/slices/settingsSlice' } from '@utils/slices/settingsSlice'
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 prettyBytes from 'pretty-bytes'
import React, { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { ActionSheetIOS, StyleSheet, Text } from 'react-native'
import { CacheManager } from 'react-native-expo-image-cache'
import { useDispatch, useSelector } from 'react-redux'
const ScreenMeSettings: React.FC = () => { const ScreenMeSettings: React.FC = () => {
const { t, i18n } = useTranslation('meSettings') const { t, i18n } = useTranslation('meSettings')
@ -22,6 +24,7 @@ const ScreenMeSettings: React.FC = () => {
const settingsLanguage = useSelector(getSettingsLanguage) const settingsLanguage = useSelector(getSettingsLanguage)
const settingsTheme = useSelector(getSettingsTheme) const settingsTheme = useSelector(getSettingsTheme)
const settingsBrowser = useSelector(getSettingsBrowser) const settingsBrowser = useSelector(getSettingsBrowser)
const settingsAnalytics = useSelector(getSettingsAnalytics)
const dispatch = useDispatch() const dispatch = useDispatch()
const [cacheSize, setCacheSize] = useState<number>() const [cacheSize, setCacheSize] = useState<number>()
@ -132,6 +135,14 @@ const ScreenMeSettings: React.FC = () => {
setCacheSize(0) setCacheSize(0)
}} }}
/> />
<MenuRow
title={t('content.analytics.heading')}
description={t('content.analytics.description')}
switchValue={settingsAnalytics}
switchOnValueChange={() =>
dispatch(changeAnalytics(!settingsAnalytics))
}
/>
<MenuRow <MenuRow
title={t('content.copyrights.heading')} title={t('content.copyrights.heading')}
iconBack='chevron-right' iconBack='chevron-right'

View File

@ -3,7 +3,6 @@ import client from '@root/api/client'
import Button from '@root/components/Button' import Button from '@root/components/Button'
import { toast } from '@root/components/toast' import { toast } from '@root/components/toast'
import { relationshipFetch } from '@root/utils/fetches/relationshipFetch' import { relationshipFetch } from '@root/utils/fetches/relationshipFetch'
import getCurrentTab from '@root/utils/getCurrentTab'
import { StyleConstants } from '@root/utils/styles/constants' import { StyleConstants } from '@root/utils/styles/constants'
import { useTheme } from '@root/utils/styles/ThemeManager' import { useTheme } from '@root/utils/styles/ThemeManager'
import React, { useEffect, useMemo } from 'react' import React, { useEffect, useMemo } from 'react'
@ -130,12 +129,9 @@ const AccountInformationActions: React.FC<Props> = ({ account }) => {
content='mail' content='mail'
round round
onPress={() => onPress={() =>
navigation.navigate(getCurrentTab(navigation), { navigation.navigate('Screen-Shared-Compose', {
screen: 'Screen-Shared-Compose', type: 'conversation',
params: { incomingStatus: { account }
type: 'conversation',
incomingStatus: { account }
}
}) })
} }
style={styles.actionConversation} style={styles.actionConversation}

View File

@ -63,14 +63,14 @@ const AccountNav: React.FC<Props> = ({ accountState, scrollY, account }) => {
<Emojis <Emojis
content={account?.display_name || account?.username} content={account?.display_name || account?.username}
emojis={account.emojis} emojis={account.emojis}
size='L' size='M'
fontBold={true} fontBold={true}
/> />
) : ( ) : (
<Text <Text
style={{ style={{
color: theme.primary, color: theme.primary,
...StyleConstants.FontStyle.L, ...StyleConstants.FontStyle.M,
fontWeight: StyleConstants.Font.Weight.Bold fontWeight: StyleConstants.Font.Weight.Bold
}} }}
> >

View File

@ -1,3 +1,12 @@
import client from '@api/client'
import { HeaderLeft, HeaderRight } from '@components/Header'
import { store } from '@root/store'
import formatText from '@screens/Shared/Compose/formatText'
import ComposeRoot from '@screens/Shared/Compose/Root'
import { getLocalAccountPreferences } from '@utils/slices/instancesSlice'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import * as Crypto from 'expo-crypto'
import React, { import React, {
createContext, createContext,
createRef, createRef,
@ -10,7 +19,6 @@ import React, {
useState useState
} from 'react' } from 'react'
import { import {
ActivityIndicator,
Alert, Alert,
Keyboard, Keyboard,
KeyboardAvoidingView, KeyboardAvoidingView,
@ -20,19 +28,7 @@ import {
} from 'react-native' } from 'react-native'
import { SafeAreaView } from 'react-native-safe-area-context' import { SafeAreaView } from 'react-native-safe-area-context'
import { createNativeStackNavigator } from 'react-native-screens/native-stack' import { createNativeStackNavigator } from 'react-native-screens/native-stack'
import * as Crypto from 'expo-crypto'
import { store } from '@root/store'
import ComposeRoot from '@screens/Shared/Compose/Root'
import client from '@api/client'
import { getLocalAccountPreferences } from '@utils/slices/instancesSlice'
import { HeaderLeft, HeaderRight } from '@components/Header'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import formatText from '@screens/Shared/Compose/formatText'
import { useQueryClient } from 'react-query' import { useQueryClient } from 'react-query'
import Toast from 'react-native-toast-message'
import { toastConfig } from '@root/components/toast'
const Stack = createNativeStackNavigator() const Stack = createNativeStackNavigator()
@ -583,6 +579,15 @@ const Compose: React.FC<Props> = ({ route: { params }, navigation }) => {
[isSubmitting, rawCount, totalTextCount] [isSubmitting, rawCount, totalTextCount]
) )
const screenComponent = useCallback(
() => (
<ComposeContext.Provider value={{ composeState, composeDispatch }}>
<ComposeRoot />
</ComposeContext.Provider>
),
[]
)
return ( return (
<KeyboardAvoidingView behavior='padding' style={{ flex: 1 }}> <KeyboardAvoidingView behavior='padding' style={{ flex: 1 }}>
<SafeAreaView <SafeAreaView
@ -591,17 +596,10 @@ const Compose: React.FC<Props> = ({ route: { params }, navigation }) => {
> >
<Stack.Navigator> <Stack.Navigator>
<Stack.Screen <Stack.Screen
name='PostMain' name='Screen-Shared-Compose-Root'
options={{ headerLeft, headerCenter, headerRight }} options={{ headerLeft, headerCenter, headerRight }}
> component={screenComponent}
{() => ( />
<ComposeContext.Provider
value={{ composeState, composeDispatch }}
>
<ComposeRoot />
</ComposeContext.Provider>
)}
</Stack.Screen>
</Stack.Navigator> </Stack.Navigator>
</SafeAreaView> </SafeAreaView>
</KeyboardAvoidingView> </KeyboardAvoidingView>

View File

@ -1,8 +0,0 @@
const getCurrentTab = (navigation: any) => {
const { length, [length - 1]: last } =
navigation.dangerouslyGetState().history ||
navigation.dangerouslyGetParent()?.dangerouslyGetState().history
return `Screen-${last.key.split(new RegExp(/Screen-(.*?)-/))[1]}`
}
export default getCurrentTab

View File

@ -1,61 +1,28 @@
import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit' import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit'
import { RootState } from '@root/store' import { RootState } from '@root/store'
// import client from 'src/api/client' import * as Analytics from 'expo-firebase-analytics'
export type SettingsState = { export type SettingsState = {
language: 'zh' | 'en' | undefined language: 'zh' | 'en' | undefined
theme: 'light' | 'dark' | 'auto' theme: 'light' | 'dark' | 'auto'
browser: 'internal' | 'external' browser: 'internal' | 'external'
analytics: boolean
} }
const initialState = { const initialState = {
language: undefined, language: undefined,
theme: 'auto', theme: 'auto',
browser: 'internal' browser: 'internal',
analytics: false
} }
// export const updateLocal = createAsyncThunk( export const changeAnalytics = createAsyncThunk(
// 'instances/updateLocal', 'settings/changeAnalytics',
// async ({ async (newValue: SettingsState['analytics']) => {
// url, await Analytics.setAnalyticsCollectionEnabled(newValue)
// token return newValue
// }: { }
// url?: InstancesState['local']['url'] )
// token?: InstancesState['local']['token']
// }) => {
// if (!url || !token) {
// return initialStateLocal
// }
// const {
// body: { id }
// } = await client({
// method: 'get',
// instance: 'remote',
// instanceUrl: url,
// endpoint: `accounts/verify_credentials`,
// headers: { Authorization: `Bearer ${token}` }
// })
// const { body: preferences } = await client({
// method: 'get',
// instance: 'remote',
// instanceUrl: url,
// endpoint: `preferences`,
// headers: { Authorization: `Bearer ${token}` }
// })
// return {
// url,
// token,
// account: {
// id,
// preferences
// }
// }
// }
// )
const settingsSlice = createSlice({ const settingsSlice = createSlice({
name: 'settings', name: 'settings',
@ -79,17 +46,19 @@ const settingsSlice = createSlice({
) => { ) => {
state.browser = action.payload state.browser = action.payload
} }
},
extraReducers: builder => {
builder.addCase(changeAnalytics.fulfilled, (state, action) => {
state.analytics = action.payload
})
} }
// extraReducers: builder => {
// builder.addCase(updateLocal.fulfilled, (state, action) => {
// state.local = action.payload
// })
// }
}) })
export const getSettingsLanguage = (state: RootState) => state.settings.language export const getSettingsLanguage = (state: RootState) => state.settings.language
export const getSettingsTheme = (state: RootState) => state.settings.theme export const getSettingsTheme = (state: RootState) => state.settings.theme
export const getSettingsBrowser = (state: RootState) => state.settings.browser export const getSettingsBrowser = (state: RootState) => state.settings.browser
export const getSettingsAnalytics = (state: RootState) =>
state.settings.analytics
export const { export const {
changeLanguage, changeLanguage,

View File

@ -2262,7 +2262,7 @@
invariant "^2.2.4" invariant "^2.2.4"
lodash "^4.5.0" lodash "^4.5.0"
"@welldone-software/why-did-you-render@^6.0.3": "@welldone-software/why-did-you-render@^6.0.4":
version "6.0.4" version "6.0.4"
resolved "https://registry.yarnpkg.com/@welldone-software/why-did-you-render/-/why-did-you-render-6.0.4.tgz#f8787a603b94fe0ef8aa824aecefd72b0a6c9e2a" resolved "https://registry.yarnpkg.com/@welldone-software/why-did-you-render/-/why-did-you-render-6.0.4.tgz#f8787a603b94fe0ef8aa824aecefd72b0a6c9e2a"
integrity sha512-hOExlpwqPK/A0XRqgg42jSpbOb6AJBdgrI/X3BRj65ItQks0KS/nIT8HWPt8rR+BJb6OD5bm+vc1pcWSmxwd6A== integrity sha512-hOExlpwqPK/A0XRqgg42jSpbOb6AJBdgrI/X3BRj65ItQks0KS/nIT8HWPt8rR+BJb6OD5bm+vc1pcWSmxwd6A==
@ -2609,7 +2609,7 @@ aws4@^1.8.0:
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
axios@^0.21.0: axios@^0.21.1:
version "0.21.1" version "0.21.1"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8"
integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA== integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==
@ -8078,10 +8078,10 @@ react-dom@16.13.1:
prop-types "^15.6.2" prop-types "^15.6.2"
scheduler "^0.19.1" scheduler "^0.19.1"
react-i18next@^11.8.4: react-i18next@^11.8.5:
version "11.8.4" version "11.8.5"
resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.8.4.tgz#5407d2edcaa704c38e4034e7ac06413914ed6e6d" resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.8.5.tgz#a093335822e36252cda6efc0f55facef6253643f"
integrity sha512-QlPJfX+Roi+jEQ6frBSsLHHH+VWbUoCl6wZDT8XHMd6PsSgepjgD2sZf/h7F46JnHeuy0U+SxY3TtrJF+aDIyg== integrity sha512-2jY/8NkhNv2KWBnZuhHxTn13aMxAbvhiDUNskm+1xVVnrPId78l8fA7fCyVeO3XU1kptM0t4MtvxV1Nu08cjLw==
dependencies: dependencies:
"@babel/runtime" "^7.3.1" "@babel/runtime" "^7.3.1"
html-parse-stringify2 "2.0.1" html-parse-stringify2 "2.0.1"
@ -8186,7 +8186,7 @@ react-native-tab-view@^2.15.2:
resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-2.15.2.tgz#4bc7832d33a119306614efee667509672a7ee64e" resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-2.15.2.tgz#4bc7832d33a119306614efee667509672a7ee64e"
integrity sha512-2hxLkBnZtEKFDyfvNO5EUywhy3f/EiLOBO8SWqKj4BMBTO0QwnybaPE5MVF00Fhz+VA4+h/iI40Dkrrtq70dGg== integrity sha512-2hxLkBnZtEKFDyfvNO5EUywhy3f/EiLOBO8SWqKj4BMBTO0QwnybaPE5MVF00Fhz+VA4+h/iI40Dkrrtq70dGg==
react-native-toast-message@^1.3.4: react-native-toast-message@^1.4.2:
version "1.4.2" version "1.4.2"
resolved "https://registry.yarnpkg.com/react-native-toast-message/-/react-native-toast-message-1.4.2.tgz#bda453dd7259587f2c5b3a1684ee5461569fe191" resolved "https://registry.yarnpkg.com/react-native-toast-message/-/react-native-toast-message-1.4.2.tgz#bda453dd7259587f2c5b3a1684ee5461569fe191"
integrity sha512-Hp/APBQu/TCLlnMhwhqaosWiC/HgpVYXG2WGF2Zd2GF93nOcH516BUoDC0rvbncGx11IBUrUtt14RRm6LrcL6g== integrity sha512-Hp/APBQu/TCLlnMhwhqaosWiC/HgpVYXG2WGF2Zd2GF93nOcH516BUoDC0rvbncGx11IBUrUtt14RRm6LrcL6g==
@ -8234,10 +8234,10 @@ react-navigation@*, react-navigation@^4.4.3:
"@react-navigation/core" "^3.7.9" "@react-navigation/core" "^3.7.9"
"@react-navigation/native" "^3.8.3" "@react-navigation/native" "^3.8.3"
react-query@^3.3.2: react-query@^3.5.6:
version "3.5.5" version "3.5.6"
resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.5.5.tgz#50bae84066e1f61dc9a14ee7db8ea1a224535698" resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.5.6.tgz#ea52404002e91e6ce39d49bf4ae96bf62554cd23"
integrity sha512-WYZcHcAs5K5lPGT6CI8fz3lU62S8IfZhvB1K4aZH27wg9T6CWei+y7IRyZwti9X18LX134O4olgEuNth9LEX+w== integrity sha512-Fv184wu9FWg35PkgyZmEveveeRr+6+rqefVWf2vI3fhmWywjo2uBUA3GHwKMKCEI7Xb6T+6SyQt23pXhJQle0w==
dependencies: dependencies:
"@babel/runtime" "^7.5.5" "@babel/runtime" "^7.5.5"
match-sorter "^6.0.2" match-sorter "^6.0.2"
@ -9512,10 +9512,10 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
typescript@~4.0.0: typescript@~4.1.3:
version "4.0.5" version "4.1.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.5.tgz#ae9dddfd1069f1cb5beb3ef3b2170dd7c1332389" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7"
integrity sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ== integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==
ua-parser-js@^0.7.18, ua-parser-js@^0.7.19: ua-parser-js@^0.7.18, ua-parser-js@^0.7.19:
version "0.7.23" version "0.7.23"