From dceaf8d25c7ac3c8871c1aa3935678fdf9cfda51 Mon Sep 17 00:00:00 2001 From: Zhiyuan Zheng Date: Sun, 3 Jan 2021 02:00:26 +0100 Subject: [PATCH] Use svg icons instead of expo ones Possibility to control `strokeWidth` --- App.tsx | 12 ++- package.json | 2 +- src/@types/app.d.ts | 2 +- src/@types/untyped.d.ts | 3 +- src/Index.tsx | 20 ++-- src/components/Button.tsx | 18 ++-- src/components/Header/Left.tsx | 10 +- src/components/Header/Right.tsx | 16 +-- src/components/Icon.tsx | 45 ++++++++ src/components/Menu/Row.tsx | 8 +- src/components/Parse/HTML.tsx | 53 +++++---- src/components/Timelines.tsx | 2 +- src/components/Timelines/Timeline.tsx | 12 +-- src/components/Timelines/Timeline/Default.tsx | 5 +- src/components/Timelines/Timeline/Empty.tsx | 10 +- .../Timelines/Timeline/Shared/Actioned.tsx | 25 ++--- .../Timelines/Timeline/Shared/Actions.tsx | 22 ++-- .../Timelines/Timeline/Shared/Attachment.tsx | 2 +- .../Timeline/Shared/Attachment/Audio.tsx | 2 +- .../Timeline/Shared/Attachment/Video.tsx | 2 +- .../Timelines/Timeline/Shared/End.tsx | 10 +- .../Timeline/Shared/HeaderConversation.tsx | 8 +- .../Timeline/Shared/HeaderDefault.tsx | 15 ++- .../Shared/HeaderDefault/ActionsAccount.tsx | 6 +- .../Shared/HeaderDefault/ActionsDomain.tsx | 2 +- .../Shared/HeaderDefault/ActionsStatus.tsx | 8 +- .../Timeline/Shared/HeaderNotification.tsx | 22 ++-- .../Shared/HeaderShared/Visibility.tsx | 6 +- .../Timelines/Timeline/Shared/Poll.tsx | 14 +-- src/components/toast.tsx | 21 ++-- src/i18n/zh/components/timeline.ts | 12 +-- src/screens/Me/Lists.tsx | 2 +- src/screens/Me/Root.tsx | 39 +++---- src/screens/Me/Root/Collections.tsx | 20 ++-- src/screens/Me/Root/Login.tsx | 6 +- src/screens/Me/Root/MyInfo.tsx | 16 +-- src/screens/Me/Root/Settings.tsx | 4 +- src/screens/Me/Settings.tsx | 10 +- src/screens/Shared/Account.tsx | 102 ++++-------------- src/screens/Shared/Account/Header.tsx | 19 ++-- src/screens/Shared/Account/Information.tsx | 12 ++- .../Shared/Account/Information/Account.tsx | 22 ++-- .../Shared/Account/Information/Actions.tsx | 2 +- .../Shared/Account/Information/Created.tsx | 10 +- .../Shared/Account/Information/Fields.tsx | 6 +- src/screens/Shared/Account/Nav.tsx | 16 +-- .../Shared/Account/SegmentedControl.tsx | 19 ++-- src/screens/Shared/Account/Toots.tsx | 43 +++----- .../Shared/Account/utils/createContext.ts | 10 ++ .../Shared/Account/utils/initialState.ts | 9 ++ src/screens/Shared/Account/utils/reducer.ts | 19 ++++ src/screens/Shared/Account/utils/types.d.ts | 22 ++++ src/screens/Shared/Announcements.tsx | 4 +- src/screens/Shared/Compose/Actions.tsx | 58 +++++----- src/screens/Shared/Compose/Attachments.tsx | 12 +-- src/screens/Shared/Compose/Poll.tsx | 14 +-- src/screens/Shared/ImagesViewer.tsx | 4 +- src/screens/Shared/Search.tsx | 6 +- src/screens/Shared/Toot.tsx | 2 +- src/utils/fetches/timelineFetch.ts | 10 +- tsconfig.json | 4 +- yarn.lock | 5 + 62 files changed, 495 insertions(+), 427 deletions(-) create mode 100644 src/components/Icon.tsx create mode 100644 src/screens/Shared/Account/utils/createContext.ts create mode 100644 src/screens/Shared/Account/utils/initialState.ts create mode 100644 src/screens/Shared/Account/utils/reducer.ts create mode 100644 src/screens/Shared/Account/utils/types.d.ts diff --git a/App.tsx b/App.tsx index 2e042abb..367edb13 100644 --- a/App.tsx +++ b/App.tsx @@ -57,7 +57,7 @@ enableScreens() const App: React.FC = () => { startingLog('log', 'rendering App') const [appLoaded, setAppLoaded] = useState(false) - const [localCorrupt, setLocalCorrupt] = useState(false) + const [localCorrupt, setLocalCorrupt] = useState() useEffect(() => { const onlineState = onlineManager.setEventListener(setOnline => { @@ -118,16 +118,20 @@ const App: React.FC = () => { startingLog('log', 'local credential check passed') if (res.body.id !== store.getState().instances.local.account.id) { store.dispatch(resetLocal()) - setLocalCorrupt(true) + setLocalCorrupt('') } setAppLoaded(true) }) .catch(error => { startingLog('error', 'local credential check failed') - if (error.status && typeof error.status === 'number') { + if ( + error.status && + typeof error.status === 'number' && + error.status === 401 + ) { store.dispatch(resetLocal()) - setLocalCorrupt(true) } + setLocalCorrupt(error.data.error) setAppLoaded(true) }) } else { diff --git a/package.json b/package.json index acb70572..cf9bfa4c 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,6 @@ "test": "jest" }, "dependencies": { - "@expo/vector-icons": "^12.0.0", "@react-native-community/masked-view": "0.1.10", "@react-native-community/netinfo": "^5.9.9", "@react-native-community/segmented-control": "2.2.1", @@ -50,6 +49,7 @@ "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", + "react-native-feather": "^1.0.2", "react-native-gesture-handler": "~1.8.0", "react-native-htmlview": "^0.16.0", "react-native-image-zoom-viewer": "^3.0.1", diff --git a/src/@types/app.d.ts b/src/@types/app.d.ts index 783ac9af..212f28b9 100644 --- a/src/@types/app.d.ts +++ b/src/@types/app.d.ts @@ -66,7 +66,7 @@ declare namespace QueryKey { { hashtag?: Mastodon.Tag['name'] list?: Mastodon.List['id'] - toot?: Mastodon.Status + toot?: Mastodon.Status['id'] account?: Mastodon.Account['id'] } ] diff --git a/src/@types/untyped.d.ts b/src/@types/untyped.d.ts index 0fa69d0c..fae6f608 100644 --- a/src/@types/untyped.d.ts +++ b/src/@types/untyped.d.ts @@ -1,3 +1,4 @@ declare module 'gl-react-blurhash' -declare module 'react-native-toast-message' +declare module 'react-native-feather' declare module 'react-native-htmlview' +declare module 'react-native-toast-message' diff --git a/src/Index.tsx b/src/Index.tsx index a2f5bf8c..69d58321 100644 --- a/src/Index.tsx +++ b/src/Index.tsx @@ -1,5 +1,5 @@ import client from '@api/client' -import { Feather } from '@expo/vector-icons' +import Icon from '@components/Icon' import { createBottomTabNavigator } from '@react-navigation/bottom-tabs' import { NavigationContainer, @@ -37,7 +37,7 @@ export type RootStackParamList = { } export interface Props { - localCorrupt: boolean + localCorrupt?: string } const Index: React.FC = ({ localCorrupt }) => { @@ -71,7 +71,7 @@ const Index: React.FC = ({ localCorrupt }) => { ? toast({ type: 'error', message: '登录已过期', - description: '请重新登录', + description: localCorrupt.length ? localCorrupt : undefined, autoHide: false }) : undefined @@ -171,27 +171,27 @@ const Index: React.FC = ({ localCorrupt }) => { let updateColor: string = color switch (route.name) { case 'Screen-Local': - name = 'home' + name = 'Home' break case 'Screen-Public': - name = 'globe' + name = 'Globe' !focused && (updateColor = theme.secondary) break case 'Screen-Post': - name = 'plus' + name = 'Plus' break case 'Screen-Notifications': - name = 'bell' + name = 'Bell' break case 'Screen-Me': - name = focused ? 'meh' : 'smile' + name = focused ? 'Meh' : 'Smile' !focused && (updateColor = theme.secondary) break default: - name = 'alert-octagon' + name = 'AlertOctagon' break } - return + return } }), [] diff --git a/src/components/Button.tsx b/src/components/Button.tsx index e53dfb01..0786cceb 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -1,4 +1,7 @@ -import { Feather } from '@expo/vector-icons' +import Icon from '@components/Icon' +import { StyleConstants } from '@utils/styles/constants' +import layoutAnimation from '@utils/styles/layoutAnimation' +import { useTheme } from '@utils/styles/ThemeManager' import React, { useEffect, useMemo } from 'react' import { Pressable, @@ -9,9 +12,6 @@ import { ViewStyle } from 'react-native' import { Chase } from 'react-native-animated-spinkit' -import { StyleConstants } from '@utils/styles/constants' -import { useTheme } from '@utils/styles/ThemeManager' -import layoutAnimation from '@root/utils/styles/layoutAnimation' export interface Props { style?: StyleProp @@ -23,6 +23,7 @@ export interface Props { destructive?: boolean disabled?: boolean + strokeWidth?: number size?: 'S' | 'M' | 'L' spacing?: 'XS' | 'S' | 'M' | 'L' round?: boolean @@ -38,6 +39,7 @@ const Button: React.FC = ({ loading = false, destructive = false, disabled = false, + strokeWidth, size = 'M', spacing = 'S', round = false, @@ -78,12 +80,12 @@ const Button: React.FC = ({ case 'icon': return ( <> - {loading && loadingSpinkit} diff --git a/src/components/Header/Left.tsx b/src/components/Header/Left.tsx index c22d9441..40c20289 100644 --- a/src/components/Header/Left.tsx +++ b/src/components/Header/Left.tsx @@ -1,8 +1,8 @@ -import React, { useMemo } from 'react' -import { Pressable, StyleSheet, Text } from 'react-native' -import { Feather } from '@expo/vector-icons' +import Icon from '@components/Icon' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' +import React, { useMemo } from 'react' +import { Pressable, StyleSheet, Text } from 'react-native' export interface Props { type?: 'icon' | 'text' @@ -18,9 +18,9 @@ const HeaderLeft: React.FC = ({ type = 'icon', content, onPress }) => { switch (type) { case 'icon': return ( - ) diff --git a/src/components/Header/Right.tsx b/src/components/Header/Right.tsx index c9209227..ca909942 100644 --- a/src/components/Header/Right.tsx +++ b/src/components/Header/Right.tsx @@ -1,13 +1,13 @@ +import Icon from '@components/Icon' +import { StyleConstants } from '@utils/styles/constants' +import { useTheme } from '@utils/styles/ThemeManager' import React, { useMemo } from 'react' import { Pressable, StyleSheet, Text, View } from 'react-native' import { Chase } from 'react-native-animated-spinkit' -import { Feather } from '@expo/vector-icons' -import { StyleConstants } from '@utils/styles/constants' -import { useTheme } from '@utils/styles/ThemeManager' export interface Props { type?: 'icon' | 'text' - content?: string + content: string loading?: boolean disabled?: boolean @@ -41,11 +41,11 @@ const HeaderRight: React.FC = ({ case 'icon': return ( <> - {loading && loadingSpinkit} diff --git a/src/components/Icon.tsx b/src/components/Icon.tsx new file mode 100644 index 00000000..4e3d8204 --- /dev/null +++ b/src/components/Icon.tsx @@ -0,0 +1,45 @@ +import React, { createElement } from 'react' +import { StyleProp, View, ViewStyle } from 'react-native' +import * as FeatherIcon from 'react-native-feather' + +export interface Props { + name: string + size: number + color: string + strokeWidth?: number + inline?: boolean // When used in line of text, need to drag it down + style?: StyleProp +} + +const Icon: React.FC = ({ + name, + size, + color, + strokeWidth = 2, + inline = false, + style +}) => { + return ( + + {createElement(FeatherIcon[name], { + width: size, + height: size, + color, + strokeWidth + })} + + ) +} + +export default Icon diff --git a/src/components/Menu/Row.tsx b/src/components/Menu/Row.tsx index 30e0f4e3..118a911c 100644 --- a/src/components/Menu/Row.tsx +++ b/src/components/Menu/Row.tsx @@ -1,4 +1,4 @@ -import { Feather } from '@expo/vector-icons' +import Icon from '@components/Icon' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' import { ColorDefinitions } from '@utils/styles/themes' @@ -18,7 +18,7 @@ export interface Props { switchDisabled?: boolean switchOnValueChange?: () => void - iconBack?: 'chevron-right' | 'check' + iconBack?: 'ChevronRight' | 'Check' iconBackColor?: ColorDefinitions loading?: boolean @@ -63,7 +63,7 @@ const MenuRow: React.FC = ({ {iconFront && ( - = ({ ) : null} {iconBack ? ( <> - {!shouldBeTag ? ( - ) : null} {content || (showFullLink ? href : domain[1])} @@ -166,37 +167,45 @@ const ParseHTML: React.FC = ({ const [heightOriginal, setHeightOriginal] = useState() const [heightTruncated, setHeightTruncated] = useState() - const [allowExpand, setAllowExpand] = useState( - numberOfLines === 0 ? true : undefined - ) + const [allowExpand, setAllowExpand] = useState(false) const [showAllText, setShowAllText] = useState(false) const calNumberOfLines = useMemo(() => { - if (heightOriginal) { - if (!heightTruncated) { - return numberOfLines - } else { - if (allowExpand && !showAllText) { + if (numberOfLines === 0) { + // For spoilers without calculation + return showAllText ? undefined : 1 + } else { + if (heightOriginal) { + if (!heightTruncated) { return numberOfLines } else { - return undefined + if (allowExpand && !showAllText) { + return numberOfLines + } else { + return undefined + } } + } else { + return undefined } - } else { - return undefined } }, [heightOriginal, heightTruncated, allowExpand, showAllText]) const onLayout = useCallback( ({ nativeEvent }) => { - if (!heightOriginal) { - setHeightOriginal(nativeEvent.layout.height) + if (numberOfLines === 0) { + // For spoilers without calculation + setAllowExpand(true) } else { - if (!heightTruncated) { - setHeightTruncated(nativeEvent.layout.height) + if (!heightOriginal) { + setHeightOriginal(nativeEvent.layout.height) } else { - if (heightOriginal > heightTruncated) { - setAllowExpand(true) + if (!heightTruncated) { + setHeightTruncated(nativeEvent.layout.height) + } else { + if (heightOriginal > heightTruncated) { + setAllowExpand(true) + } } } } @@ -214,7 +223,7 @@ const ParseHTML: React.FC = ({ }} children={children} numberOfLines={calNumberOfLines} - onLayout={allowExpand === undefined ? onLayout : undefined} + onLayout={onLayout} /> {allowExpand ? ( = ({ name, content }) => { ), headerRight: () => ( - + ) }) }} diff --git a/src/components/Timelines/Timeline.tsx b/src/components/Timelines/Timeline.tsx index 0968fc99..b4688a6f 100644 --- a/src/components/Timelines/Timeline.tsx +++ b/src/components/Timelines/Timeline.tsx @@ -24,10 +24,10 @@ export type TimelineData = export interface Props { page: App.Pages - hashtag?: string - list?: string - toot?: Mastodon.Status - account?: string + hashtag?: Mastodon.Tag['name'] + list?: Mastodon.List['id'] + toot?: Mastodon.Status['id'] + account?: Mastodon.Account['id'] disableRefresh?: boolean disableInfinity?: boolean } @@ -134,7 +134,7 @@ const Timeline: React.FC = ({ flattenPinnedLength[0] && { pinnedLength: flattenPinnedLength[0] })} - {...(toot && toot.id === item.id && { highlighted: true })} + {...(toot === item.id && { highlighted: true })} /> ) } @@ -144,7 +144,7 @@ const Timeline: React.FC = ({ const ItemSeparatorComponent = useCallback( ({ leadingItem }) => ( ), [] diff --git a/src/components/Timelines/Timeline/Default.tsx b/src/components/Timelines/Timeline/Default.tsx index 3ae166f6..56acc786 100644 --- a/src/components/Timelines/Timeline/Default.tsx +++ b/src/components/Timelines/Timeline/Default.tsx @@ -44,6 +44,7 @@ const TimelineDefault: React.FC = ({ }), [] ) + return ( {item.reblog ? ( @@ -57,11 +58,11 @@ const TimelineDefault: React.FC = ({ {...(!isRemotePublic && { queryKey })} account={actualStatus.account} /> - + /> */} = ({ status, refetch }) => { case 'error': return ( <> - @@ -44,8 +44,8 @@ const TimelineEmpty: React.FC = ({ status, refetch }) => { case 'success': return ( <> - diff --git a/src/components/Timelines/Timeline/Shared/Actioned.tsx b/src/components/Timelines/Timeline/Shared/Actioned.tsx index c381c8d8..ebf8c3bb 100644 --- a/src/components/Timelines/Timeline/Shared/Actioned.tsx +++ b/src/components/Timelines/Timeline/Shared/Actioned.tsx @@ -1,5 +1,5 @@ +import Icon from '@components/Icon' import { ParseEmojis } from '@components/Parse' -import { Feather } from '@expo/vector-icons' import { useNavigation } from '@react-navigation/native' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' @@ -37,8 +37,8 @@ const TimelineActioned: React.FC = ({ case 'pinned': return ( <> - = ({ case 'favourite': return ( <> - = ({ case 'follow': return ( <> - = ({ case 'poll': return ( <> - = ({ case 'reblog': return ( <> - = ({ const styles = StyleSheet.create({ actioned: { flexDirection: 'row', + alignItems: 'center', marginBottom: StyleConstants.Spacing.S, paddingLeft: StyleConstants.Avatar.M - StyleConstants.Font.Size.S, paddingRight: StyleConstants.Spacing.Global.PagePadding }, icon: { - paddingRight: StyleConstants.Spacing.S + marginRight: StyleConstants.Spacing.S } }) diff --git a/src/components/Timelines/Timeline/Shared/Actions.tsx b/src/components/Timelines/Timeline/Shared/Actions.tsx index ad537ee5..88b89883 100644 --- a/src/components/Timelines/Timeline/Shared/Actions.tsx +++ b/src/components/Timelines/Timeline/Shared/Actions.tsx @@ -1,8 +1,8 @@ import client from '@api/client' import haptics from '@components/haptics' +import Icon from '@components/Icon' import { TimelineData } from '@components/Timelines/Timeline' import { toast } from '@components/toast' -import { Feather } from '@expo/vector-icons' import { useNavigation } from '@react-navigation/native' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' @@ -171,8 +171,8 @@ const TimelineActions: React.FC = ({ queryKey, status, reblog }) => { const childrenReply = useMemo( () => ( <> - @@ -193,8 +193,8 @@ const TimelineActions: React.FC = ({ queryKey, status, reblog }) => { ) const childrenReblog = useMemo( () => ( - = ({ queryKey, status, reblog }) => { ) const childrenFavourite = useMemo( () => ( - @@ -217,8 +217,8 @@ const TimelineActions: React.FC = ({ queryKey, status, reblog }) => { ) const childrenBookmark = useMemo( () => ( - @@ -227,8 +227,8 @@ const TimelineActions: React.FC = ({ queryKey, status, reblog }) => { ) const childrenShare = useMemo( () => ( - diff --git a/src/components/Timelines/Timeline/Shared/Attachment.tsx b/src/components/Timelines/Timeline/Shared/Attachment.tsx index 3ac63326..b2589bc3 100644 --- a/src/components/Timelines/Timeline/Shared/Attachment.tsx +++ b/src/components/Timelines/Timeline/Shared/Attachment.tsx @@ -117,7 +117,7 @@ const TimelineAttachment: React.FC = ({ status }) => { ) : (