From 1493e20962a5743035606c0c7a6da98a656cd3a3 Mon Sep 17 00:00:00 2001 From: Zhiyuan Zheng Date: Sun, 29 Nov 2020 18:08:31 +0100 Subject: [PATCH] Theme done --- App.tsx | 35 +++--- src/Index.tsx | 116 ++++++++++-------- src/components/Timelines.tsx | 3 +- src/components/Timelines/Timeline/Default.tsx | 1 + .../Timeline/Shared/HeaderDefault.tsx | 14 +++ src/i18n/i18n.ts | 3 +- src/i18n/zh/_all.ts | 9 +- src/i18n/zh/common.ts | 19 +-- src/i18n/zh/screens/meBookmarks.ts | 4 + src/i18n/zh/screens/meConversations.ts | 4 + src/i18n/zh/screens/meFavourites.ts | 4 + src/i18n/zh/screens/meLists.ts | 4 + src/i18n/zh/screens/meListsList.ts | 4 + src/i18n/zh/screens/meRoot.ts | 24 ++++ src/i18n/zh/screens/meSettings.ts | 22 ++++ src/i18n/zh/settings.ts | 11 -- src/screens/Me.tsx | 12 +- src/screens/Me/Root.tsx | 4 +- .../{MyCollections.tsx => Collections.tsx} | 14 +-- src/screens/Me/Root/Logout.tsx | 12 +- src/screens/Me/Root/Settings.tsx | 4 +- src/screens/Me/Settings.tsx | 55 +++++++-- src/utils/slices/settingsSlice.ts | 13 +- src/utils/styles/ThemeManager.tsx | 39 +++--- 24 files changed, 280 insertions(+), 150 deletions(-) create mode 100644 src/i18n/zh/screens/meBookmarks.ts create mode 100644 src/i18n/zh/screens/meConversations.ts create mode 100644 src/i18n/zh/screens/meFavourites.ts create mode 100644 src/i18n/zh/screens/meLists.ts create mode 100644 src/i18n/zh/screens/meListsList.ts create mode 100644 src/i18n/zh/screens/meRoot.ts create mode 100644 src/i18n/zh/screens/meSettings.ts delete mode 100644 src/i18n/zh/settings.ts rename src/screens/Me/Root/{MyCollections.tsx => Collections.tsx} (71%) diff --git a/App.tsx b/App.tsx index 8ccbd27c..5117eb6a 100644 --- a/App.tsx +++ b/App.tsx @@ -28,22 +28,25 @@ setConsole({ const App: React.FC = () => { return ( - - - - - {bootstrapped => { - if (bootstrapped) { - require('src/i18n/i18n') - return - } else { - return <> - } - }} - - - - + + + + {bootstrapped => { + if (bootstrapped) { + console.log('Bootstrapped!') + require('src/i18n/i18n') + return ( + + + + ) + } else { + return <> + } + }} + + + ) } diff --git a/src/Index.tsx b/src/Index.tsx index 0a5f1a3f..9a1b6f22 100644 --- a/src/Index.tsx +++ b/src/Index.tsx @@ -4,6 +4,7 @@ import { NavigationContainer } from '@react-navigation/native' import { enableScreens } from 'react-native-screens' import React from 'react' +import { StatusBar } from 'react-native' import Toast from 'react-native-toast-message' import { Feather } from '@expo/vector-icons' @@ -30,65 +31,72 @@ export type RootStackParamList = { export const Index: React.FC = () => { const { mode, theme } = useTheme() + enum barStyle { + light = 'dark-content', + dark = 'light-content' + } return ( - - ({ - tabBarIcon: ({ focused, color, size }) => { - let name: string - switch (route.name) { - case 'Screen-Local': - name = 'home' - break - case 'Screen-Public': - name = 'globe' - break - case 'Screen-Post': - name = 'plus' - break - case 'Screen-Notifications': - name = 'bell' - break - case 'Screen-Me': - name = focused ? 'smile' : 'meh' - break - default: - name = 'alert-octagon' - break - } - return - } - })} - tabBarOptions={{ - activeTintColor: theme.primary, - inactiveTintColor: theme.secondary, - showLabel: false - }} - > - - - ({ - tabPress: e => { - e.preventDefault() - navigation.navigate(getCurrentTab(navigation), { - screen: 'Screen-Shared-Compose' - }) + <> + + + ({ + tabBarIcon: ({ focused, color, size }) => { + let name: string + switch (route.name) { + case 'Screen-Local': + name = 'home' + break + case 'Screen-Public': + name = 'globe' + break + case 'Screen-Post': + name = 'plus' + break + case 'Screen-Notifications': + name = 'bell' + break + case 'Screen-Me': + name = focused ? 'smile' : 'meh' + break + default: + name = 'alert-octagon' + break + } + return } })} + tabBarOptions={{ + activeTintColor: theme.primary, + inactiveTintColor: theme.secondary, + showLabel: false + }} > - {() => <>} - - - - + + + ({ + tabPress: e => { + e.preventDefault() + navigation.navigate(getCurrentTab(navigation), { + screen: 'Screen-Shared-Compose' + }) + } + })} + > + {() => <>} + + + + - Toast.setRef(ref)} config={toastConfig} /> - + Toast.setRef(ref)} config={toastConfig} /> + + ) } diff --git a/src/components/Timelines.tsx b/src/components/Timelines.tsx index c6a84963..70f71a2d 100644 --- a/src/components/Timelines.tsx +++ b/src/components/Timelines.tsx @@ -44,7 +44,7 @@ export interface Props { const Timelines: React.FC = ({ name, content }) => { const navigation = useNavigation() - const { theme } = useTheme() + const { mode, theme } = useTheme() const localRegistered = useSelector(getLocalUrl) const publicDomain = useSelector(getRemoteUrl) const [segment, setSegment] = useState(0) @@ -107,6 +107,7 @@ const Timelines: React.FC = ({ name, content }) => { headerCenter: () => ( = ({ item, queryKey }) => { emojis={actualStatus.account.emojis} account={actualStatus.account.acct} created_at={item.created_at} + visibility={item.visibility} application={item.application} /> {/* Can pass toot info to next page to speed up performance */} diff --git a/src/components/Timelines/Timeline/Shared/HeaderDefault.tsx b/src/components/Timelines/Timeline/Shared/HeaderDefault.tsx index 4f414491..ca0dcdee 100644 --- a/src/components/Timelines/Timeline/Shared/HeaderDefault.tsx +++ b/src/components/Timelines/Timeline/Shared/HeaderDefault.tsx @@ -98,6 +98,7 @@ export interface Props { emojis?: Mastodon.Emoji[] account: string created_at: string + visibility: Mastodon.Status['visibility'] application?: Mastodon.Application } @@ -109,6 +110,7 @@ const HeaderDefault: React.FC = ({ emojis, account, created_at, + visibility, application }) => { const { theme } = useTheme() @@ -197,6 +199,14 @@ const HeaderDefault: React.FC = ({ {since} + {visibility === 'private' && ( + + )} {application && application.name !== 'Web' && ( { name='Screen-Me-Conversations' component={ScreenMeConversations} options={{ - headerTitle: t('headers.me.conversations') + headerTitle: t('meConversations:heading') }} /> ({ - headerTitle: t('headers.me.lists.list', { list: route.params.title }) + headerTitle: t('meListsList:heading', { list: route.params.title }) })} /> diff --git a/src/screens/Me/Root.tsx b/src/screens/Me/Root.tsx index acee40e6..bafd6340 100644 --- a/src/screens/Me/Root.tsx +++ b/src/screens/Me/Root.tsx @@ -6,7 +6,7 @@ import { getLocalUrl } from 'src/utils/slices/instancesSlice' import Login from './Root/Login' import MyInfo from './Root/MyInfo' -import MyCollections from './Root/MyCollections' +import Collections from './Root/Collections' import Settings from './Root/Settings' import Logout from './Root/Logout' @@ -16,7 +16,7 @@ const ScreenMeRoot: React.FC = () => { return ( {localRegistered ? : } - {localRegistered && } + {localRegistered && } {localRegistered && } diff --git a/src/screens/Me/Root/MyCollections.tsx b/src/screens/Me/Root/Collections.tsx similarity index 71% rename from src/screens/Me/Root/MyCollections.tsx rename to src/screens/Me/Root/Collections.tsx index 59c4cdf5..506a0ad1 100644 --- a/src/screens/Me/Root/MyCollections.tsx +++ b/src/screens/Me/Root/Collections.tsx @@ -4,34 +4,34 @@ import { useTranslation } from 'react-i18next' import { MenuContainer, MenuItem } from 'src/components/Menu' -const MyInfo: React.FC = () => { - const { t } = useTranslation() +const Collections: React.FC = () => { + const { t } = useTranslation('meRoot') const navigation = useNavigation() return ( navigation.navigate('Screen-Me-Conversations')} /> navigation.navigate('Screen-Me-Bookmarks')} /> navigation.navigate('Screen-Me-Favourites')} /> navigation.navigate('Screen-Me-Lists')} /> ) } -export default MyInfo +export default Collections diff --git a/src/screens/Me/Root/Logout.tsx b/src/screens/Me/Root/Logout.tsx index c247a34b..70b63ace 100644 --- a/src/screens/Me/Root/Logout.tsx +++ b/src/screens/Me/Root/Logout.tsx @@ -5,17 +5,19 @@ import { updateLocal } from 'src/utils/slices/instancesSlice' import MenuButton from 'src/components/Menu/Button' import { MenuContainer } from 'src/components/Menu' import { useNavigation } from '@react-navigation/native' +import { useTranslation } from 'react-i18next' const Logout: React.FC = () => { + const { t } = useTranslation('meRoot') const dispatch = useDispatch() const navigation = useNavigation() const alertOption = { - title: '确认退出登录?', - message: '退出登录后,需要重新认证账号', + title: t('content.logout.alert.title'), + message: t('content.logout.alert.message'), buttons: [ { - text: '退出登录', + text: t('content.logout.alert.buttons.logout'), style: 'destructive' as const, onPress: () => { dispatch(updateLocal({})) @@ -26,7 +28,7 @@ const Logout: React.FC = () => { } }, { - text: '取消', + text: t('content.logout.alert.buttons.cancel'), style: 'cancel' as const } ] @@ -35,7 +37,7 @@ const Logout: React.FC = () => { return ( diff --git a/src/screens/Me/Root/Settings.tsx b/src/screens/Me/Root/Settings.tsx index 37cc1f79..38d8232c 100644 --- a/src/screens/Me/Root/Settings.tsx +++ b/src/screens/Me/Root/Settings.tsx @@ -5,14 +5,14 @@ import { useTranslation } from 'react-i18next' import { MenuContainer, MenuItem } from 'src/components/Menu' const Settings: React.FC = () => { - const { t } = useTranslation() + const { t } = useTranslation('meRoot') const navigation = useNavigation() return ( navigation.navigate('Screen-Me-Settings')} /> diff --git a/src/screens/Me/Settings.tsx b/src/screens/Me/Settings.tsx index 95c8fed4..f84df789 100644 --- a/src/screens/Me/Settings.tsx +++ b/src/screens/Me/Settings.tsx @@ -6,28 +6,32 @@ import { useDispatch, useSelector } from 'react-redux' import { MenuContainer, MenuItem } from 'src/components/Menu' import { changeLanguage, - getSettingsLanguage + changeTheme, + getSettingsLanguage, + getSettingsTheme } from 'src/utils/slices/settingsSlice' +import { useTheme } from 'src/utils/styles/ThemeManager' const ScreenMeSettings: React.FC = () => { - const { t, i18n } = useTranslation('settings') - const language = useSelector(getSettingsLanguage) + const { t, i18n } = useTranslation('meSettings') + const { setTheme } = useTheme() + const settingsLanguage = useSelector(getSettingsLanguage) + const settingsTheme = useSelector(getSettingsTheme) const dispatch = useDispatch() - console.log(i18n.language) return ( ActionSheetIOS.showActionSheetWithOptions( { options: [ - t('settings:content.language.options.zh'), - t('settings:content.language.options.en'), - '取消' + t('content.language.options.zh'), + t('content.language.options.en'), + t('content.language.options.cancel') ], cancelButtonIndex: 2 }, @@ -46,6 +50,39 @@ const ScreenMeSettings: React.FC = () => { ) } /> + + ActionSheetIOS.showActionSheetWithOptions( + { + options: [ + t('content.theme.options.auto'), + t('content.theme.options.light'), + t('content.theme.options.dark'), + t('content.theme.options.cancel') + ], + cancelButtonIndex: 3 + }, + buttonIndex => { + switch (buttonIndex) { + case 0: + dispatch(changeTheme('auto')) + break + case 1: + dispatch(changeTheme('light')) + setTheme('light') + break + case 2: + dispatch(changeTheme('dark')) + setTheme('dark') + break + } + } + ) + } + /> ) } diff --git a/src/utils/slices/settingsSlice.ts b/src/utils/slices/settingsSlice.ts index 047fddc1..ff821578 100644 --- a/src/utils/slices/settingsSlice.ts +++ b/src/utils/slices/settingsSlice.ts @@ -5,10 +5,12 @@ import { RootState } from 'src/store' export type SettingsState = { language: 'zh' | 'en' | undefined + theme: 'light' | 'dark' | 'auto' } const initialState = { - language: undefined + language: undefined, + theme: 'auto' } // export const updateLocal = createAsyncThunk( @@ -62,6 +64,12 @@ const settingsSlice = createSlice({ action: PayloadAction> ) => { state.language = action.payload + }, + changeTheme: ( + state, + action: PayloadAction> + ) => { + state.theme = action.payload } } // extraReducers: builder => { @@ -72,6 +80,7 @@ const settingsSlice = createSlice({ }) export const getSettingsLanguage = (state: RootState) => state.settings.language +export const getSettingsTheme = (state: RootState) => state.settings.theme -export const { changeLanguage } = settingsSlice.actions +export const { changeLanguage, changeTheme } = settingsSlice.actions export default settingsSlice.reducer diff --git a/src/utils/styles/ThemeManager.tsx b/src/utils/styles/ThemeManager.tsx index b1d67293..13727a57 100644 --- a/src/utils/styles/ThemeManager.tsx +++ b/src/utils/styles/ThemeManager.tsx @@ -1,39 +1,44 @@ import React, { createContext, useContext, useEffect, useState } from 'react' -import { Appearance, useColorScheme } from 'react-native-appearance' +import { Appearance } from 'react-native-appearance' +import { useSelector } from 'react-redux' import { ColorDefinitions, getTheme } from 'src/utils/styles/themes' +import { getSettingsTheme } from '../slices/settingsSlice' -const osTheme = Appearance.getColorScheme() as 'light' | 'dark' - -export const ManageThemeContext: React.Context<{ +type ContextType = { mode: 'light' | 'dark' theme: { [key in ColorDefinitions]: string } - toggle: () => void -}> = createContext({ - mode: osTheme, - theme: getTheme(osTheme), - toggle: () => {} + setTheme: (theme: 'light' | 'dark') => void +} + +export const ManageThemeContext = createContext({ + mode: 'light', + theme: getTheme('light'), + setTheme: () => {} }) export const useTheme = () => useContext(ManageThemeContext) const ThemeManager: React.FC = ({ children }) => { - const [mode, setMode] = useState(osTheme) - const systemTheme = useColorScheme() + const userTheme = useSelector(getSettingsTheme) + const currentMode = + userTheme === 'auto' + ? (Appearance.getColorScheme() as 'light' | 'dark') + : userTheme - const toggleTheme = () => { - mode === 'light' ? setMode('dark') : setMode('light') - } + const [mode, setMode] = useState(currentMode) + + const setTheme = (theme: 'light' | 'dark') => setMode(theme) useEffect(() => { - setMode(systemTheme === 'no-preference' ? 'light' : systemTheme) - }, [systemTheme]) + setMode(currentMode) + }, [currentMode]) return ( {children}