diff --git a/App.tsx b/App.tsx index 8d2f48b4..f3a6e92c 100644 --- a/App.tsx +++ b/App.tsx @@ -1,3 +1,4 @@ +import 'react-native-gesture-handler' import NetInfo from '@react-native-community/netinfo' import client from '@root/api/client' import Index from '@root/Index' @@ -5,9 +6,9 @@ import { persistor, store } from '@root/store' import { resetLocal } from '@root/utils/slices/instancesSlice' import ThemeManager from '@utils/styles/ThemeManager' import chalk from 'chalk' +import * as Analytics from 'expo-firebase-analytics' import * as SplashScreen from 'expo-splash-screen' import React, { useCallback, useEffect, useState } from 'react' -import { Platform, Text } from 'react-native' import { enableScreens } from 'react-native-screens' import { onlineManager, QueryClient, QueryClientProvider } from 'react-query' import { Provider } from 'react-redux' @@ -30,6 +31,8 @@ const startingLog = (type: 'log' | 'warn' | 'error', message: string) => { } if (__DEV__) { + Analytics.setDebugModeEnabled(true) + startingLog('log', 'initializing wdyr') const whyDidYouRender = require('@welldone-software/why-did-you-render') whyDidYouRender(React, { diff --git a/app.config.ts b/app.config.ts index 537d28cb..08d53232 100644 --- a/app.config.ts +++ b/app.config.ts @@ -5,7 +5,7 @@ export default (): ExpoConfig => ({ description: 'This is a description', slug: 'mastodon-app', privacy: 'hidden', - version: '1.0.0', + version: '0.1.0', platforms: ['ios'], orientation: 'portrait', userInterfaceStyle: 'automatic', @@ -33,6 +33,18 @@ export default (): ExpoConfig => ({ // } // }, 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: { config: { firebase: { diff --git a/package.json b/package.json index e39820d5..e1c291a6 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "@react-navigation/bottom-tabs": "^5.11.2", "@react-navigation/native": "^5.8.10", "@reduxjs/toolkit": "^1.5.0", - "axios": "^0.21.0", + "axios": "^0.21.1", "buffer": "^6.0.3", "expo": "^40.0.0", "expo-auth-session": "~3.0.0", @@ -45,7 +45,7 @@ "pretty-bytes": "^5.5.0", "react": "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-animated-spinkit": "^1.4.2", "react-native-expo-image-cache": "^4.1.0", @@ -58,9 +58,9 @@ "react-native-shimmer-placeholder": "^2.0.6", "react-native-svg": "12.1.0", "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-query": "^3.3.2", + "react-query": "^3.5.6", "react-redux": "^7.2.2", "redux-persist": "^6.0.0", "redux-persist-expo-securestore": "^2.0.0", @@ -87,13 +87,13 @@ "@types/react-navigation": "^3.4.0", "@types/react-redux": "^7.1.12", "@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", "chalk": "^4.1.0", "jest": "^26.6.3", "jest-expo": "^40.0.1", "react-test-renderer": "^16.13.1", - "typescript": "~4.0.0" + "typescript": "~4.1.3" }, "jest": { "preset": "jest-expo", diff --git a/src/Index.tsx b/src/Index.tsx index c1f4d784..9c930f02 100644 --- a/src/Index.tsx +++ b/src/Index.tsx @@ -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 { NavigationContainer, NavigationContainerRef } 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 ScreenPublic from '@screens/Public' import ScreenNotifications from '@screens/Notifications' import ScreenMe from '@screens/Me' - -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 { timelineFetch } from '@utils/fetches/timelineFetch' import { getLocalNotification, getLocalUrl, updateLocalAccountPreferences, updateNotification } 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 client from './api/client' -import { timelineFetch } from './utils/fetches/timelineFetch' -import { useNetInfo } from '@react-native-community/netinfo' const Tab = createBottomTabNavigator() @@ -50,25 +43,27 @@ export interface Props { const Index: React.FC = ({ localCorrupt }) => { const dispatch = useDispatch() const localInstance = useSelector(getLocalUrl) - const { i18n } = useTranslation() const { mode, theme } = useTheme() enum barStyle { light = 'dark-content', dark = 'light-content' } - const isConnected = useNetInfo().isConnected - const [firstRender, setFirstRender] = useState(false) - useEffect(() => { - if (firstRender) { - // bug in netInfo on first render as false - if (isConnected !== false) { - toast({ type: 'error', content: '手机🈚️网络', autoHide: false }) - } - } else { - setFirstRender(true) - } - }, [isConnected, firstRender]) + const routeNameRef = useRef() + const navigationRef = useRef(null) + + // const isConnected = useNetInfo().isConnected + // const [firstRender, setFirstRender] = useState(false) + // useEffect(() => { + // if (firstRender) { + // // bug in netInfo on first render as false + // if (isConnected !== false) { + // toast({ type: 'error', content: '手机🈚️网络', autoHide: false }) + // } + // } else { + // setFirstRender(true) + // } + // }, [isConnected, firstRender]) // On launch display login credentials corrupt information useEffect(() => { @@ -84,8 +79,8 @@ const Index: React.FC = ({ localCorrupt }) => { }, [localCorrupt]) // On launch check if there is any unread announcements - const navigationRef = useRef(null) useEffect(() => { + console.log('Checking announcements') localInstance && client({ method: 'get', @@ -99,7 +94,7 @@ const Index: React.FC = ({ localCorrupt }) => { }) } }) - .catch(() => null) + .catch(() => {}) }, []) // On launch check if there is any unread noficiations @@ -145,104 +140,149 @@ const Index: React.FC = ({ 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 + } + }), + [] + ) + 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 ( <> { - Analytics.setCurrentScreen(state?.routes[state.index].name) - }} + // key={i18n.language} + onReady={navigationContainerOnReady} + onStateChange={navigationContainerOnStateChange} > ({ - tabBarIcon: ({ focused, color, size }) => { - 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 - } - })} - tabBarOptions={{ - activeTintColor: theme.primary, - inactiveTintColor: localInstance ? theme.secondary : theme.disabled, - showLabel: false - }} + screenOptions={tabNavigatorScreenOptions} + tabBarOptions={tabNavigatorTabBarOptions} > ({ - tabPress: e => { - if (!localInstance) { - e.preventDefault() - } - } - })} + listeners={tabScreenLocalListeners} /> ({ - tabPress: e => { - e.preventDefault() - if (localInstance) { - navigation.navigate(getCurrentTab(navigation), { - screen: 'Screen-Shared-Compose' - }) - } - } - })} - > - {() => null} - + component={tabScreenComposeComponent} + listeners={tabScreenComposeListeners} + /> ({ - tabPress: e => { - if (!localInstance) { - e.preventDefault() - } - } - })} + listeners={tabScreenNotificationsListeners} + options={tabScreenNotificationsOptions} /> - Toast.setRef(ref)} config={toastConfig} /> + ) diff --git a/src/components/Menu/Row.tsx b/src/components/Menu/Row.tsx index 403633c6..2ea2fd3b 100644 --- a/src/components/Menu/Row.tsx +++ b/src/components/Menu/Row.tsx @@ -3,7 +3,7 @@ import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' import { ColorDefinitions } from '@utils/styles/themes' 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' export interface Props { @@ -11,8 +11,13 @@ export interface Props { iconFrontColor?: ColorDefinitions title: string + description?: string content?: string + switchValue?: boolean + switchDisabled?: boolean + switchOnValueChange?: () => void + iconBack?: 'chevron-right' | 'check' iconBackColor?: ColorDefinitions @@ -24,7 +29,11 @@ const MenuRow: React.FC = ({ iconFront, iconFrontColor = 'primary', title, + description, content, + switchValue, + switchDisabled, + switchOnValueChange, iconBack, iconBackColor = 'secondary', loading = false, @@ -61,45 +70,59 @@ const MenuRow: React.FC = ({ style={styles.iconFront} /> )} - - {title} - - - {(content || iconBack) && ( - - {content && content.length ? ( - <> - - {content} - - {loading && !iconBack && loadingSpinkit} - + + + {title} + + {description ? ( + + {description} + ) : null} - {iconBack && ( - <> - - {loading && loadingSpinkit} - - )} - )} + + + + {content && content.length ? ( + <> + + {content} + + {loading && !iconBack && loadingSpinkit} + + ) : null} + {switchValue !== undefined ? ( + + ) : null} + {iconBack ? ( + <> + + {loading && loadingSpinkit} + + ) : null} + ) @@ -131,10 +154,16 @@ const styles = StyleSheet.create({ iconFront: { marginRight: 8 }, - text: { - flex: 1, + main: { + flex: 1 + }, + title: { ...StyleConstants.FontStyle.M }, + description: { + ...StyleConstants.FontStyle.S, + marginTop: StyleConstants.Spacing.XS + }, content: { ...StyleConstants.FontStyle.M }, diff --git a/src/components/ParseContent.tsx b/src/components/ParseContent.tsx index df74d7b0..e555acaa 100644 --- a/src/components/ParseContent.tsx +++ b/src/components/ParseContent.tsx @@ -76,6 +76,7 @@ const renderNode = ({ } } else { const domain = href.split(new RegExp(/:\/\/(.[^\/]+)/)) + // Need example here const content = node.children && node.children[0].data const shouldBeTag = tags && tags.filter(tag => `#${tag.name}` === content).length > 0 diff --git a/src/components/Timelines.tsx b/src/components/Timelines.tsx index b21d172b..0948f48b 100644 --- a/src/components/Timelines.tsx +++ b/src/components/Timelines.tsx @@ -9,7 +9,6 @@ import sharedScreens from '@screens/Shared/sharedScreens' import { getLocalUrl, getRemoteUrl } from '@utils/slices/instancesSlice' import { useTheme } from '@utils/styles/ThemeManager' import { useNavigation } from '@react-navigation/native' -import getCurrentTab from '@utils/getCurrentTab' import { HeaderRight } from './Header' import { TabView } from 'react-native-tab-view' @@ -28,9 +27,7 @@ const Timelines: React.FC = ({ name, content }) => { const [segment, setSegment] = useState(0) const onPressSearch = useCallback(() => { - navigation.navigate(getCurrentTab(navigation), { - screen: 'Screen-Shared-Search' - }) + navigation.navigate('Screen-Shared-Search') }, []) const routes = content diff --git a/src/components/Timelines/Timeline/Shared/Actions.tsx b/src/components/Timelines/Timeline/Shared/Actions.tsx index ff7446e2..451243c6 100644 --- a/src/components/Timelines/Timeline/Shared/Actions.tsx +++ b/src/components/Timelines/Timeline/Shared/Actions.tsx @@ -8,7 +8,6 @@ import { useTheme } from '@utils/styles/ThemeManager' import { toast } from '@components/toast' import { StyleConstants } from '@utils/styles/constants' import { useNavigation } from '@react-navigation/native' -import getCurrentTab from '@utils/getCurrentTab' import { findIndex } from 'lodash' import { TimelineData } from '../../Timeline' @@ -124,13 +123,10 @@ const TimelineActions: React.FC = ({ queryKey, status, reblog }) => { const onPressReply = useCallback( () => - navigation.navigate(getCurrentTab(navigation), { - screen: 'Screen-Shared-Compose', - params: { - type: 'reply', - incomingStatus: status, - visibilityLock: status.visibility === 'direct' - } + navigation.navigate('Screen-Shared-Compose', { + type: 'reply', + incomingStatus: status, + visibilityLock: status.visibility === 'direct' }), [] ) diff --git a/src/components/Timelines/Timeline/Shared/HeaderDefault/ActionsStatus.tsx b/src/components/Timelines/Timeline/Shared/HeaderDefault/ActionsStatus.tsx index fc173ee0..35fa75cd 100644 --- a/src/components/Timelines/Timeline/Shared/HeaderDefault/ActionsStatus.tsx +++ b/src/components/Timelines/Timeline/Shared/HeaderDefault/ActionsStatus.tsx @@ -5,7 +5,6 @@ import { useMutation, useQueryClient } from 'react-query' import client from '@api/client' import { MenuContainer, MenuHeader, MenuRow } from '@components/Menu' import { toast } from '@components/toast' -import getCurrentTab from '@utils/getCurrentTab' import { TimelineData } from '@root/components/Timelines/Timeline' import { findIndex } from 'lodash' @@ -155,9 +154,9 @@ const HeaderDefaultActionsStatus: React.FC = ({ .then(res => { queryClient.invalidateQueries(queryKey) setBottomSheetVisible(false) - navigation.navigate(getCurrentTab(navigation), { - screen: 'Screen-Shared-Compose', - params: { type: 'edit', incomingStatus: res.body } + navigation.navigate('Screen-Shared-Compose', { + type: 'edit', + incomingStatus: res.body }) }) .catch(() => { diff --git a/src/components/toast.tsx b/src/components/toast.tsx index 21fd78c1..d3ddb104 100644 --- a/src/components/toast.tsx +++ b/src/components/toast.tsx @@ -63,7 +63,7 @@ const ToastBase = ({ config }: { config: Config }) => { @@ -97,15 +97,14 @@ const toastConfig = { const styles = StyleSheet.create({ base: { width: '100%', - shadowOpacity: 1, - shadowRadius: 6 + borderBottomWidth: 1 }, container: { flex: 1, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', - padding: StyleConstants.Spacing.M + padding: StyleConstants.Spacing.L }, texts: { marginLeft: StyleConstants.Spacing.S diff --git a/src/i18n/zh/screens/meSettings.ts b/src/i18n/zh/screens/meSettings.ts index 61cf5514..36cf1647 100644 --- a/src/i18n/zh/screens/meSettings.ts +++ b/src/i18n/zh/screens/meSettings.ts @@ -29,6 +29,10 @@ export default { cache: { heading: '清空缓存' }, + analytics: { + heading: '帮助我们改进', + description: '允许我们收集不与用户相关联的使用信息' + }, copyrights: { heading: '版权信息' }, diff --git a/src/screens/Me/Settings.tsx b/src/screens/Me/Settings.tsx index daaa3ff4..1d60cbeb 100644 --- a/src/screens/Me/Settings.tsx +++ b/src/screens/Me/Settings.tsx @@ -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 { + changeAnalytics, changeBrowser, changeLanguage, changeTheme, + getSettingsAnalytics, getSettingsBrowser, getSettingsLanguage, getSettingsTheme } from '@utils/slices/settingsSlice' import { StyleConstants } from '@utils/styles/constants' 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 { t, i18n } = useTranslation('meSettings') @@ -22,6 +24,7 @@ const ScreenMeSettings: React.FC = () => { const settingsLanguage = useSelector(getSettingsLanguage) const settingsTheme = useSelector(getSettingsTheme) const settingsBrowser = useSelector(getSettingsBrowser) + const settingsAnalytics = useSelector(getSettingsAnalytics) const dispatch = useDispatch() const [cacheSize, setCacheSize] = useState() @@ -132,6 +135,14 @@ const ScreenMeSettings: React.FC = () => { setCacheSize(0) }} /> + + dispatch(changeAnalytics(!settingsAnalytics)) + } + /> = ({ account }) => { content='mail' round onPress={() => - navigation.navigate(getCurrentTab(navigation), { - screen: 'Screen-Shared-Compose', - params: { - type: 'conversation', - incomingStatus: { account } - } + navigation.navigate('Screen-Shared-Compose', { + type: 'conversation', + incomingStatus: { account } }) } style={styles.actionConversation} diff --git a/src/screens/Shared/Account/Nav.tsx b/src/screens/Shared/Account/Nav.tsx index 1a25dfc8..869412e6 100644 --- a/src/screens/Shared/Account/Nav.tsx +++ b/src/screens/Shared/Account/Nav.tsx @@ -63,14 +63,14 @@ const AccountNav: React.FC = ({ accountState, scrollY, account }) => { ) : ( diff --git a/src/screens/Shared/Compose.tsx b/src/screens/Shared/Compose.tsx index cb9ab4db..af561ad7 100644 --- a/src/screens/Shared/Compose.tsx +++ b/src/screens/Shared/Compose.tsx @@ -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, { createContext, createRef, @@ -10,7 +19,6 @@ import React, { useState } from 'react' import { - ActivityIndicator, Alert, Keyboard, KeyboardAvoidingView, @@ -20,19 +28,7 @@ import { } from 'react-native' import { SafeAreaView } from 'react-native-safe-area-context' 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 Toast from 'react-native-toast-message' -import { toastConfig } from '@root/components/toast' const Stack = createNativeStackNavigator() @@ -583,6 +579,15 @@ const Compose: React.FC = ({ route: { params }, navigation }) => { [isSubmitting, rawCount, totalTextCount] ) + const screenComponent = useCallback( + () => ( + + + + ), + [] + ) + return ( = ({ route: { params }, navigation }) => { > - {() => ( - - - - )} - + component={screenComponent} + /> diff --git a/src/utils/getCurrentTab.ts b/src/utils/getCurrentTab.ts deleted file mode 100644 index c7692d5b..00000000 --- a/src/utils/getCurrentTab.ts +++ /dev/null @@ -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 diff --git a/src/utils/slices/settingsSlice.ts b/src/utils/slices/settingsSlice.ts index a641cf16..ca719adc 100644 --- a/src/utils/slices/settingsSlice.ts +++ b/src/utils/slices/settingsSlice.ts @@ -1,61 +1,28 @@ import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit' - import { RootState } from '@root/store' -// import client from 'src/api/client' +import * as Analytics from 'expo-firebase-analytics' export type SettingsState = { language: 'zh' | 'en' | undefined theme: 'light' | 'dark' | 'auto' browser: 'internal' | 'external' + analytics: boolean } const initialState = { language: undefined, theme: 'auto', - browser: 'internal' + browser: 'internal', + analytics: false } -// export const updateLocal = createAsyncThunk( -// 'instances/updateLocal', -// async ({ -// url, -// token -// }: { -// 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 -// } -// } -// } -// ) +export const changeAnalytics = createAsyncThunk( + 'settings/changeAnalytics', + async (newValue: SettingsState['analytics']) => { + await Analytics.setAnalyticsCollectionEnabled(newValue) + return newValue + } +) const settingsSlice = createSlice({ name: 'settings', @@ -79,17 +46,19 @@ const settingsSlice = createSlice({ ) => { 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 getSettingsTheme = (state: RootState) => state.settings.theme export const getSettingsBrowser = (state: RootState) => state.settings.browser +export const getSettingsAnalytics = (state: RootState) => + state.settings.analytics export const { changeLanguage, diff --git a/yarn.lock b/yarn.lock index 90029ee3..204f4549 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2262,7 +2262,7 @@ invariant "^2.2.4" 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" 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== @@ -2609,7 +2609,7 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== -axios@^0.21.0: +axios@^0.21.1: version "0.21.1" resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA== @@ -8078,10 +8078,10 @@ react-dom@16.13.1: prop-types "^15.6.2" scheduler "^0.19.1" -react-i18next@^11.8.4: - version "11.8.4" - resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.8.4.tgz#5407d2edcaa704c38e4034e7ac06413914ed6e6d" - integrity sha512-QlPJfX+Roi+jEQ6frBSsLHHH+VWbUoCl6wZDT8XHMd6PsSgepjgD2sZf/h7F46JnHeuy0U+SxY3TtrJF+aDIyg== +react-i18next@^11.8.5: + version "11.8.5" + resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.8.5.tgz#a093335822e36252cda6efc0f55facef6253643f" + integrity sha512-2jY/8NkhNv2KWBnZuhHxTn13aMxAbvhiDUNskm+1xVVnrPId78l8fA7fCyVeO3XU1kptM0t4MtvxV1Nu08cjLw== dependencies: "@babel/runtime" "^7.3.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" 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" resolved "https://registry.yarnpkg.com/react-native-toast-message/-/react-native-toast-message-1.4.2.tgz#bda453dd7259587f2c5b3a1684ee5461569fe191" 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/native" "^3.8.3" -react-query@^3.3.2: - version "3.5.5" - resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.5.5.tgz#50bae84066e1f61dc9a14ee7db8ea1a224535698" - integrity sha512-WYZcHcAs5K5lPGT6CI8fz3lU62S8IfZhvB1K4aZH27wg9T6CWei+y7IRyZwti9X18LX134O4olgEuNth9LEX+w== +react-query@^3.5.6: + version "3.5.6" + resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.5.6.tgz#ea52404002e91e6ce39d49bf4ae96bf62554cd23" + integrity sha512-Fv184wu9FWg35PkgyZmEveveeRr+6+rqefVWf2vI3fhmWywjo2uBUA3GHwKMKCEI7Xb6T+6SyQt23pXhJQle0w== dependencies: "@babel/runtime" "^7.5.5" 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" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@~4.0.0: - version "4.0.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.5.tgz#ae9dddfd1069f1cb5beb3ef3b2170dd7c1332389" - integrity sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ== +typescript@~4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7" + integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg== ua-parser-js@^0.7.18, ua-parser-js@^0.7.19: version "0.7.23"