From 8200375c9291beff157f392955d1f2a31c33070b Mon Sep 17 00:00:00 2001 From: Zhiyuan Zheng Date: Tue, 24 Nov 2020 00:18:47 +0100 Subject: [PATCH] Lots of updates --- src/Index.tsx | 17 ++- src/components/Menu/Button.tsx | 74 ++++++++++ src/components/Menu/Container.tsx | 20 ++- src/components/Menu/Item.tsx | 23 ++- src/components/PleaseLogin.tsx | 8 ++ src/components/Timelines.tsx | 135 +++++++++++------- .../Timelines/Timeline/Separator.tsx | 3 +- .../Timelines/Timeline/Shared/Emojis.tsx | 4 +- src/screens/Local.tsx | 2 +- src/screens/Me.tsx | 26 ++-- src/screens/Me/Root.tsx | 2 + src/screens/Me/Root/Login.tsx | 33 ++++- src/screens/Me/Root/Logout.tsx | 46 ++++++ src/screens/Me/Root/MyCollections.tsx | 3 +- src/screens/Me/Root/Settings.tsx | 3 +- src/screens/Notifications.tsx | 35 ++--- src/screens/Public.tsx | 2 +- src/screens/Shared/Search.tsx | 7 + src/screens/Shared/sharedScreens.tsx | 30 ++-- src/utils/getCurrentTab.ts | 9 ++ src/utils/slices/instancesSlice.ts | 41 +++--- src/utils/styles/constants.ts | 2 + src/utils/styles/themes.ts | 5 + 23 files changed, 378 insertions(+), 152 deletions(-) create mode 100644 src/components/Menu/Button.tsx create mode 100644 src/components/PleaseLogin.tsx create mode 100644 src/screens/Me/Root/Logout.tsx create mode 100644 src/screens/Shared/Search.tsx create mode 100644 src/utils/getCurrentTab.ts diff --git a/src/Index.tsx b/src/Index.tsx index a1a75b89..ee9eb5da 100644 --- a/src/Index.tsx +++ b/src/Index.tsx @@ -16,9 +16,18 @@ import ScreenMe from 'src/screens/Me' import { themes } from 'src/utils/styles/themes' import { useTheme } from 'src/utils/styles/ThemeManager' +import getCurrentTab from 'src/utils/getCurrentTab' enableScreens() -const Tab = createBottomTabNavigator() +const Tab = createBottomTabNavigator() + +export type RootStackParamList = { + 'Screen-Local': undefined + 'Screen-Public': { publicTab: boolean } + 'Screen-Post': undefined + 'Screen-Notifications': undefined + 'Screen-Me': undefined +} export const Index: React.FC = () => { const { mode, theme } = useTheme() @@ -65,11 +74,7 @@ export const Index: React.FC = () => { listeners={({ navigation, route }) => ({ tabPress: e => { e.preventDefault() - const { - length, - [length - 1]: last - } = navigation.dangerouslyGetState().history - navigation.navigate(last.key.split(new RegExp(/(.*)-/))[1], { + navigation.navigate(getCurrentTab(navigation), { screen: 'Screen-Shared-Compose' }) } diff --git a/src/components/Menu/Button.tsx b/src/components/Menu/Button.tsx new file mode 100644 index 00000000..98b873ca --- /dev/null +++ b/src/components/Menu/Button.tsx @@ -0,0 +1,74 @@ +import React from 'react' +import { + Alert, + AlertButton, + AlertOptions, + Pressable, + StyleSheet, + Text, + View +} from 'react-native' +import { useTheme } from 'src/utils/styles/ThemeManager' + +import constants from 'src/utils/styles/constants' + +export interface Props { + text: string + destructive?: boolean + alertOption?: { + title: string + message?: string | undefined + buttons?: AlertButton[] | undefined + options?: AlertOptions | undefined + } +} + +const Core: React.FC = ({ text, destructive = false }) => { + const { theme } = useTheme() + + return ( + + + {text} + + + ) +} + +const MenuButton: React.FC = ({ ...props }) => { + const { theme } = useTheme() + + return ( + + props.alertOption && + Alert.alert( + props.alertOption.title, + props.alertOption.message, + props.alertOption.buttons, + props.alertOption.options + ) + } + > + + + ) +} + +const styles = StyleSheet.create({ + base: { + height: 50, + borderBottomWidth: 1 + }, + core: { + flex: 1, + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'center', + paddingLeft: constants.GLOBAL_PAGE_PADDING, + paddingRight: constants.GLOBAL_PAGE_PADDING + } +}) + +export default MenuButton diff --git a/src/components/Menu/Container.tsx b/src/components/Menu/Container.tsx index 904b7029..4a87f0d9 100644 --- a/src/components/Menu/Container.tsx +++ b/src/components/Menu/Container.tsx @@ -1,8 +1,24 @@ import React from 'react' -import { View } from 'react-native' +import { StyleSheet, View } from 'react-native' +import { useTheme } from 'src/utils/styles/ThemeManager' + +import constants from 'src/utils/styles/constants' const MenuContainer: React.FC = ({ ...props }) => { - return {props.children} + const { theme } = useTheme() + + return ( + + {props.children} + + ) } +const styles = StyleSheet.create({ + base: { + borderTopWidth: 1, + marginBottom: constants.SPACING_M + } +}) + export default MenuContainer diff --git a/src/components/Menu/Item.tsx b/src/components/Menu/Item.tsx index 13e8e488..ba70c828 100644 --- a/src/components/Menu/Item.tsx +++ b/src/components/Menu/Item.tsx @@ -4,6 +4,8 @@ import { useNavigation } from '@react-navigation/native' import { Feather } from '@expo/vector-icons' import { useTheme } from 'src/utils/styles/ThemeManager' +import constants from 'src/utils/styles/constants' + export interface Props { icon?: string title: string @@ -16,8 +18,17 @@ const Core: React.FC = ({ icon, title, navigateTo }) => { return ( - {icon && } - {title} + {icon && ( + + )} + + {title} + {navigateTo && ( = ({ icon, title, navigateTo }) => { } const MenuItem: React.FC = ({ ...props }) => { + const { theme } = useTheme() const navigation = useNavigation() return props.navigateTo ? ( { navigation.navigate(props.navigateTo!, props.navigateToParams) }} @@ -52,15 +64,14 @@ const MenuItem: React.FC = ({ ...props }) => { const styles = StyleSheet.create({ base: { height: 50, - borderBottomColor: 'lightgray', borderBottomWidth: 1 }, core: { flex: 1, flexDirection: 'row', alignItems: 'center', - paddingLeft: 12, - paddingRight: 12 + paddingLeft: constants.GLOBAL_PAGE_PADDING, + paddingRight: constants.GLOBAL_PAGE_PADDING }, iconLeading: { marginRight: 8 diff --git a/src/components/PleaseLogin.tsx b/src/components/PleaseLogin.tsx new file mode 100644 index 00000000..a40986cc --- /dev/null +++ b/src/components/PleaseLogin.tsx @@ -0,0 +1,8 @@ +import React from 'react' +import { Text } from 'react-native' + +const PleaseLogin = () => { + return 请先登录 +} + +export default PleaseLogin diff --git a/src/components/Timelines.tsx b/src/components/Timelines.tsx index da0c7498..715dabec 100644 --- a/src/components/Timelines.tsx +++ b/src/components/Timelines.tsx @@ -7,9 +7,12 @@ import { Feather } from '@expo/vector-icons' import Timeline from './Timelines/Timeline' import sharedScreens from 'src/screens/Shared/sharedScreens' -import { InstancesState } from 'src/utils/slices/instancesSlice' -import { RootState } from 'src/store' +import { getRemoteUrl, InstancesState } from 'src/utils/slices/instancesSlice' +import { RootState, store } from 'src/store' import { useTheme } from 'src/utils/styles/ThemeManager' +import { useNavigation } from '@react-navigation/native' +import getCurrentTab from 'src/utils/getCurrentTab' +import PleaseLogin from './PleaseLogin' const Stack = createNativeStackNavigator() @@ -25,22 +28,24 @@ const Page = ({ {localRegistered || page === 'RemotePublic' ? ( ) : ( - 请先登录 + )} ) } export interface Props { - name: string + name: 'Screen-Local-Root' | 'Screen-Public-Root' content: { title: string; page: App.Pages }[] } const Timelines: React.FC = ({ name, content }) => { + const navigation = useNavigation() const { theme } = useTheme() const localRegistered = useSelector( (state: RootState) => state.instances.local.url ) + const publicDomain = getRemoteUrl(store.getState()) const [segment, setSegment] = useState(0) const [renderHeader, setRenderHeader] = useState(false) const [segmentManuallyTriggered, setSegmentManuallyTriggered] = useState( @@ -59,58 +64,80 @@ const Timelines: React.FC = ({ name, content }) => { - renderHeader ? ( - - ) : null, - headerCenter: () => - renderHeader ? ( - { - setSegmentManuallyTriggered(true) - setSegment(nativeEvent.selectedSegmentIndex) - horizontalPaging.current.scrollToIndex({ - index: nativeEvent.selectedSegmentIndex - }) - }} - style={{ width: 150, height: 30 }} - /> - ) : null + headerTitle: name === 'Screen-Public-Root' ? publicDomain : '', + ...(renderHeader && + localRegistered && { + headerCenter: () => ( + { + setSegmentManuallyTriggered(true) + setSegment(nativeEvent.selectedSegmentIndex) + horizontalPaging.current.scrollToIndex({ + index: nativeEvent.selectedSegmentIndex + }) + }} + style={{ width: 150, height: 30 }} + /> + ), + headerRight: () => ( + { + navigation.navigate(getCurrentTab(navigation), { + screen: 'Screen-Shared-Search' + }) + }} + /> + ) + }) }} > - {() => ( - page} - renderItem={({ item, index }) => ( - - )} - ref={horizontalPaging} - bounces={false} - getItemLayout={(data, index) => ({ - length: Dimensions.get('window').width, - offset: Dimensions.get('window').width * index, - index - })} - horizontal - onMomentumScrollEnd={() => setSegmentManuallyTriggered(false)} - onScroll={({ nativeEvent }) => - !segmentManuallyTriggered && - setSegment( - nativeEvent.contentOffset.x <= - Dimensions.get('window').width / 2 - ? 0 - : 1 - ) - } - pagingEnabled - showsHorizontalScrollIndicator={false} - /> - )} + {() => { + return ( + page} + renderItem={({ item, index }) => { + if (!localRegistered && index === 0) { + return null + } + return ( + + ) + }} + ref={horizontalPaging} + bounces={false} + getItemLayout={(data, index) => ({ + length: Dimensions.get('window').width, + offset: Dimensions.get('window').width * index, + index + })} + horizontal + onMomentumScrollEnd={() => setSegmentManuallyTriggered(false)} + onScroll={({ nativeEvent }) => + !segmentManuallyTriggered && + setSegment( + nativeEvent.contentOffset.x <= + Dimensions.get('window').width / 2 + ? 0 + : 1 + ) + } + pagingEnabled + showsHorizontalScrollIndicator={false} + /> + ) + }} {sharedScreens(Stack)} diff --git a/src/components/Timelines/Timeline/Separator.tsx b/src/components/Timelines/Timeline/Separator.tsx index b3c156b5..29697056 100644 --- a/src/components/Timelines/Timeline/Separator.tsx +++ b/src/components/Timelines/Timeline/Separator.tsx @@ -13,7 +13,8 @@ const TimelineSeparator = () => { const styles = StyleSheet.create({ base: { borderTopWidth: 1, - marginLeft: constants.SPACING_M + constants.AVATAR_S + constants.SPACING_S + marginLeft: constants.SPACING_M + constants.AVATAR_S + constants.SPACING_S, + marginRight: constants.SPACING_M } }) diff --git a/src/components/Timelines/Timeline/Shared/Emojis.tsx b/src/components/Timelines/Timeline/Shared/Emojis.tsx index adc9b037..a8969025 100644 --- a/src/components/Timelines/Timeline/Shared/Emojis.tsx +++ b/src/components/Timelines/Timeline/Shared/Emojis.tsx @@ -2,6 +2,8 @@ import React from 'react' import { Image, StyleSheet, Text } from 'react-native' import { useTheme } from 'src/utils/styles/ThemeManager' +import constants from 'src/utils/styles/constants' + const regexEmoji = new RegExp(/(:[a-z0-9_]+:)/) export interface Props { @@ -23,7 +25,7 @@ const Emojis: React.FC = ({ fontSize: size, lineHeight: size + 2, color: theme.primary, - ...(fontBold && { fontWeight: 'bold' }) + ...(fontBold && { fontWeight: constants.FONT_WEIGHT_BOLD }) }, image: { width: size, diff --git a/src/screens/Local.tsx b/src/screens/Local.tsx index 100abb86..daac16de 100644 --- a/src/screens/Local.tsx +++ b/src/screens/Local.tsx @@ -5,7 +5,7 @@ import Timelines from 'src/components/Timelines' const ScreenLocal: React.FC = () => { return ( { + const localRegistered = useSelector( + (state: RootState) => state.instances.local.url + ) + return ( - + <> - }} + options={ + localRegistered + ? { + headerTranslucent: true, + headerStyle: { backgroundColor: 'rgba(255, 255, 255, 0)' }, + headerCenter: () => <> + } + : { headerTitle: '我的长毛象' } + } /> { const localRegistered = useSelector( @@ -26,6 +27,7 @@ const ScreenMeRoot: React.FC = () => { )} + {localRegistered && } ) } diff --git a/src/screens/Me/Root/Login.tsx b/src/screens/Me/Root/Login.tsx index c438caf1..d54ca7c4 100644 --- a/src/screens/Me/Root/Login.tsx +++ b/src/screens/Me/Root/Login.tsx @@ -1,5 +1,5 @@ import React, { useCallback, useEffect, useState } from 'react' -import { Button, Text, TextInput, View } from 'react-native' +import { Button, StyleSheet, Text, TextInput, View } from 'react-native' import { useQuery } from 'react-query' import { debounce } from 'lodash' @@ -9,8 +9,12 @@ import * as AuthSession from 'expo-auth-session' import { useDispatch } from 'react-redux' import { updateLocal } from 'src/utils/slices/instancesSlice' import { useNavigation } from '@react-navigation/native' +import { useTheme } from 'src/utils/styles/ThemeManager' + +import constants from 'src/utils/styles/constants' const Login: React.FC = () => { + const { theme } = useTheme() const navigation = useNavigation() const dispatch = useDispatch() const [instance, setInstance] = useState('') @@ -109,23 +113,34 @@ const Login: React.FC = () => { } ) dispatch(updateLocal({ url: instance, token: accessToken })) - navigation.navigate('Local') + navigation.navigate('Screen-Local-Root') } })() }, [response]) return ( - + + isSuccess && data && data.uri && (await createApplication()) + } placeholder='输入服务器' - placeholderTextColor='#888888' + placeholderTextColor={theme.secondary} + returnKeyType='go' />