From 9bfee024849aad635f698fc45215de1e326cf2c9 Mon Sep 17 00:00:00 2001 From: Zhiyuan Zheng Date: Tue, 1 Dec 2020 00:44:28 +0100 Subject: [PATCH] A lot of updates --- src/Index.tsx | 2 +- src/components/BottomSheet.tsx | 9 +- src/components/BottomSheet/Row.tsx | 7 +- src/components/Header/Left.tsx | 4 +- src/components/Header/Right.tsx | 4 +- src/components/ParseContent.tsx | 27 ++- src/components/Timelines/Timeline.tsx | 6 +- src/components/Timelines/Timeline/Default.tsx | 3 +- .../Timeline/Shared/ActionsStatus.tsx | 175 ++++++++---------- .../Timelines/Timeline/Shared/Card.tsx | 48 ++++- .../Timelines/Timeline/Shared/Emojis.tsx | 32 ++-- .../Timeline/Shared/HeaderDefault.tsx | 29 +-- src/i18n/zh/screens/meSettings.ts | 6 +- src/screens/Me/Settings.tsx | 148 ++++++++------- src/screens/Shared/Account/Information.tsx | 173 ++++++++++++----- src/screens/Shared/Webview.tsx | 57 +++++- src/utils/styles/ThemeManager.tsx | 7 +- src/utils/styles/constants.ts | 5 +- 18 files changed, 463 insertions(+), 279 deletions(-) diff --git a/src/Index.tsx b/src/Index.tsx index 15d9deea..50c0be08 100644 --- a/src/Index.tsx +++ b/src/Index.tsx @@ -60,7 +60,7 @@ export const Index: React.FC = () => { name = 'bell' break case 'Screen-Me': - name = focused ? 'smile' : 'meh' + name = focused ? 'meh' : 'smile' break default: name = 'alert-octagon' diff --git a/src/components/BottomSheet.tsx b/src/components/BottomSheet.tsx index a385fdaa..5a71c234 100644 --- a/src/components/BottomSheet.tsx +++ b/src/components/BottomSheet.tsx @@ -77,7 +77,7 @@ const BottomSheet: React.FC = ({ children, visible, handleDismiss }) => { { top, backgroundColor: theme.background, - paddingBottom: insets.bottom + paddingBottom: insets.bottom || StyleConstants.Spacing.L } ]} > @@ -108,15 +108,16 @@ const styles = StyleSheet.create({ }, handle: { alignSelf: 'center', - width: StyleConstants.Spacing.Global.PagePadding * 8, - height: StyleConstants.Spacing.Global.PagePadding / 2, + width: StyleConstants.Spacing.S * 8, + height: StyleConstants.Spacing.S / 2, borderRadius: 100, top: -StyleConstants.Spacing.M * 2 }, cancel: { padding: StyleConstants.Spacing.S, borderWidth: 1, - borderRadius: 100 + borderRadius: 100, + // marginBottom: StyleConstants.Spacing.L }, text: { fontSize: StyleConstants.Font.Size.L, diff --git a/src/components/BottomSheet/Row.tsx b/src/components/BottomSheet/Row.tsx index c4c771df..26b55d77 100644 --- a/src/components/BottomSheet/Row.tsx +++ b/src/components/BottomSheet/Row.tsx @@ -6,16 +6,16 @@ import { useTheme } from 'src/utils/styles/ThemeManager' import { StyleConstants } from 'src/utils/styles/constants' export interface Props { - onPressFunction: () => void + onPress: () => void icon: string text: string } -const BottomSheetRow: React.FC = ({ onPressFunction, icon, text }) => { +const BottomSheetRow: React.FC = ({ onPress, icon, text }) => { const { theme } = useTheme() return ( - onPressFunction()} style={styles.pressable}> + = ({ onPressFunction, icon, text }) => { const styles = StyleSheet.create({ pressable: { + width: '100%', flexDirection: 'row', marginBottom: StyleConstants.Spacing.L }, diff --git a/src/components/Header/Left.tsx b/src/components/Header/Left.tsx index b8bab0e9..1f0eecac 100644 --- a/src/components/Header/Left.tsx +++ b/src/components/Header/Left.tsx @@ -17,11 +17,11 @@ const HeaderLeft: React.FC = ({ onPress, text, icon }) => { return ( {text ? ( - {text} + {text} ) : ( )} diff --git a/src/components/Header/Right.tsx b/src/components/Header/Right.tsx index 12ddd04d..fab8b5e9 100644 --- a/src/components/Header/Right.tsx +++ b/src/components/Header/Right.tsx @@ -28,11 +28,11 @@ const HeaderRight: React.FC = ({ return ( - {text && {text}} + {text && {text}} {icon && ( )} diff --git a/src/components/ParseContent.tsx b/src/components/ParseContent.tsx index ff37e394..ad1dcba1 100644 --- a/src/components/ParseContent.tsx +++ b/src/components/ParseContent.tsx @@ -1,10 +1,12 @@ import React, { useCallback } from 'react' -import { Text } from 'react-native' -import HTMLView, { HTMLViewNode } from 'react-native-htmlview' +import { StyleSheet, Text, View } from 'react-native' +import HTMLView from 'react-native-htmlview' import { useNavigation } from '@react-navigation/native' import Emojis from 'src/components/Timelines/Timeline/Shared/Emojis' import { useTheme } from 'src/utils/styles/ThemeManager' +import { Feather } from '@expo/vector-icons' +import { StyleConstants } from 'src/utils/styles/constants' // Prevent going to the same hashtag multiple times const renderNode = ({ @@ -75,6 +77,11 @@ const renderNode = ({ }) }} > + {' '} {showFullLink ? href : domain[1]} ) @@ -88,7 +95,7 @@ export interface Props { emojis?: Mastodon.Emoji[] mentions?: Mastodon.Mention[] showFullLink?: boolean - linesTruncated?: number + numberOfLines?: number } const ParseContent: React.FC = ({ @@ -97,7 +104,7 @@ const ParseContent: React.FC = ({ emojis, mentions, showFullLink = false, - linesTruncated = 10 + numberOfLines = 10 }) => { const navigation = useNavigation() const { theme } = useTheme() @@ -117,7 +124,11 @@ const ParseContent: React.FC = ({ [] ) const rootComponent = useCallback(({ children }) => { - return {children} + return ( + + {children} + + ) }, []) return ( @@ -130,4 +141,10 @@ const ParseContent: React.FC = ({ ) } +const styles = StyleSheet.create({ + root: { + lineHeight: StyleConstants.Font.LineHeight.M + } +}) + export default ParseContent diff --git a/src/components/Timelines/Timeline.tsx b/src/components/Timelines/Timeline.tsx index 285cf4ad..42619123 100644 --- a/src/components/Timelines/Timeline.tsx +++ b/src/components/Timelines/Timeline.tsx @@ -80,7 +80,7 @@ const Timeline: React.FC = ({ }, { previous: true } ), - [disableRefresh] + [disableRefresh, flattenData] ) const flOnEndReach = useCallback( () => @@ -89,7 +89,7 @@ const Timeline: React.FC = ({ direction: 'next', id: flattenData[flattenData.length - 1].id }), - [disableRefresh] + [disableRefresh, flattenData] ) let content @@ -110,7 +110,7 @@ const Timeline: React.FC = ({ scrollEnabled={scrollEnabled} // For timeline in Account view ItemSeparatorComponent={flItemSeparatorComponent} refreshing={!disableRefresh && isLoading} - onEndReachedThreshold={!disableRefresh ? 0.5 : null} + onEndReachedThreshold={!disableRefresh ? 1 : null} // require getItemLayout // {...(flattenPointer[0] && { initialScrollIndex: flattenPointer[0] })} /> diff --git a/src/components/Timelines/Timeline/Default.tsx b/src/components/Timelines/Timeline/Default.tsx index 10d3eeaf..59df9a9d 100644 --- a/src/components/Timelines/Timeline/Default.tsx +++ b/src/components/Timelines/Timeline/Default.tsx @@ -106,7 +106,8 @@ const styles = StyleSheet.create({ statusView: { flex: 1, flexDirection: 'column', - padding: StyleConstants.Spacing.Global.PagePadding + padding: StyleConstants.Spacing.Global.PagePadding, + paddingBottom: StyleConstants.Spacing.M }, status: { flex: 1, diff --git a/src/components/Timelines/Timeline/Shared/ActionsStatus.tsx b/src/components/Timelines/Timeline/Shared/ActionsStatus.tsx index 64666fbb..999086f1 100644 --- a/src/components/Timelines/Timeline/Shared/ActionsStatus.tsx +++ b/src/components/Timelines/Timeline/Shared/ActionsStatus.tsx @@ -1,13 +1,5 @@ import React, { useCallback, useMemo, useState } from 'react' -import { - ActionSheetIOS, - Clipboard, - Modal, - Pressable, - StyleSheet, - Text, - View -} from 'react-native' +import { ActionSheetIOS, Pressable, StyleSheet, Text, View } from 'react-native' import { useMutation, useQueryCache } from 'react-query' import { Feather } from '@expo/vector-icons' @@ -17,6 +9,8 @@ import { useTheme } from 'src/utils/styles/ThemeManager' import { toast } from 'src/components/toast' import { useSelector } from 'react-redux' import { StyleConstants } from 'src/utils/styles/constants' +import BottomSheet from 'src/components/BottomSheet' +import BottomSheetRow from 'src/components/BottomSheet/Row' const fireMutation = async ({ id, @@ -275,96 +269,85 @@ const ActionsStatus: React.FC = ({ queryKey, status }) => { /> - setBottomSheetVisible(false)} > - setBottomSheetVisible(false)} - > - - - ActionSheetIOS.showShareActionSheetWithOptions( - { - url: status.uri, - excludedActivityTypes: [ - 'com.apple.UIKit.activity.Mail', - 'com.apple.UIKit.activity.Print', - 'com.apple.UIKit.activity.SaveToCameraRoll', - 'com.apple.UIKit.activity.OpenInIBooks' - ] - }, - () => {}, - () => { - setBottomSheetVisible(false) - toast({ type: 'success', content: '分享成功' }) - } - ) + { + ActionSheetIOS.showShareActionSheetWithOptions( + { + url: status.uri, + excludedActivityTypes: [ + 'com.apple.UIKit.activity.Mail', + 'com.apple.UIKit.activity.Print', + 'com.apple.UIKit.activity.SaveToCameraRoll', + 'com.apple.UIKit.activity.OpenInIBooks' + ] + }, + () => {}, + () => { + setBottomSheetVisible(false) + toast({ type: 'success', content: '分享成功' }) } - > - 分享 - - { - Clipboard.setString(status.uri) - setBottomSheetVisible(false) - toast({ type: 'success', content: '链接复制成功' }) - }} - > - 复制链接 - - {status.account.id === localAccountId && ( - { - setBottomSheetVisible(false) - mutateAction({ - id: status.id, - type: 'delete', - stateKey: 'id' - }) - }} - > - 删除 - - )} - (删除并重发) - { - setBottomSheetVisible(false) - mutateAction({ - id: status.id, - type: 'mute', - stateKey: 'muted', - prevState: status.muted - }) - }} - > - {status.muted ? '取消静音' : '静音'} - - {/* Also note that reblogs cannot be pinned. */} - {status.account.id === localAccountId && ( - { - setBottomSheetVisible(false) - mutateAction({ - id: status.id, - type: 'pin', - stateKey: 'pinned', - prevState: status.pinned - }) - }} - > - {status.pinned ? '取消置顶' : '置顶'} - - )} - 静音用户,屏蔽用户,屏蔽域名,举报用户 - - - + ) + }} + icon='share' + text={'分享嘟嘟'} + /> + {status.account.id === localAccountId && ( + { + setBottomSheetVisible(false) + mutateAction({ + id: status.id, + type: 'delete', + stateKey: 'id' + }) + }} + icon='trash' + text='删除嘟嘟' + /> + )} + {status.account.id === localAccountId && ( + { + console.warn('功能未开发') + }} + icon='trash' + text='删除并重发' + /> + )} + { + setBottomSheetVisible(false) + mutateAction({ + id: status.id, + type: 'mute', + stateKey: 'muted', + prevState: status.muted + }) + }} + icon='volume-x' + text={status.muted ? '取消静音' : '静音'} + /> + {/* Also note that reblogs cannot be pinned. */} + {status.account.id === localAccountId && ( + { + setBottomSheetVisible(false) + mutateAction({ + id: status.id, + type: 'pin', + stateKey: 'pinned', + prevState: status.pinned + }) + }} + icon='anchor' + text={status.pinned ? '取消置顶' : '置顶'} + /> + )} + ) } diff --git a/src/components/Timelines/Timeline/Shared/Card.tsx b/src/components/Timelines/Timeline/Shared/Card.tsx index a3c2d59c..29df1b82 100644 --- a/src/components/Timelines/Timeline/Shared/Card.tsx +++ b/src/components/Timelines/Timeline/Shared/Card.tsx @@ -1,12 +1,15 @@ import React, { useCallback } from 'react' import { Image, Pressable, StyleSheet, Text, View } from 'react-native' import { useNavigation } from '@react-navigation/native' +import { StyleConstants } from 'src/utils/styles/constants' +import { useTheme } from 'src/utils/styles/ThemeManager' export interface Props { card: Mastodon.Card } const Card: React.FC = ({ card }) => { + const { theme } = useTheme() const navigation = useNavigation() const onPress = useCallback(() => { navigation.navigate('Screen-Shared-Webview', { @@ -15,20 +18,35 @@ const Card: React.FC = ({ card }) => { }, []) return ( - + {card.image && ( )} - {card.title} + + {card.title} + {card.description ? ( - {card.description} + + {card.description} + ) : ( <> )} - {card.url} + + {card.url} + ) @@ -38,18 +56,30 @@ const styles = StyleSheet.create({ card: { flex: 1, flexDirection: 'row', - height: 70, - marginTop: 12 + height: StyleConstants.Avatar.L, + marginTop: StyleConstants.Spacing.M, + borderWidth: 0.5, + borderRadius: 6 }, left: { - width: 70 + width: StyleConstants.Avatar.L }, image: { width: '100%', - height: '100%' + height: '100%', + borderTopLeftRadius: 6, + borderBottomLeftRadius: 6 }, right: { - flex: 1 + flex: 1, + padding: StyleConstants.Spacing.S + }, + rightTitle: { + marginBottom: StyleConstants.Spacing.XS, + fontWeight: StyleConstants.Font.Weight.Bold + }, + rightDescription: { + marginBottom: StyleConstants.Spacing.XS } }) diff --git a/src/components/Timelines/Timeline/Shared/Emojis.tsx b/src/components/Timelines/Timeline/Shared/Emojis.tsx index 954a0184..4cae043c 100644 --- a/src/components/Timelines/Timeline/Shared/Emojis.tsx +++ b/src/components/Timelines/Timeline/Shared/Emojis.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { Image, StyleSheet, Text } from 'react-native' +import { Image, StyleSheet, Text, View } from 'react-native' import { useTheme } from 'src/utils/styles/ThemeManager' import { StyleConstants } from 'src/utils/styles/constants' @@ -22,19 +22,20 @@ const Emojis: React.FC = ({ const styles = StyleSheet.create({ text: { fontSize: size, - lineHeight: size + 2, color: theme.primary, ...(fontBold && { fontWeight: StyleConstants.Font.Weight.Bold }) }, image: { width: size, - height: size + height: size, + paddingTop: 1, + marginBottom: -1 } }) const hasEmojis = content.match(regexEmoji) - return hasEmojis ? ( - <> + return ( + {content.split(regexEmoji).map((str, i) => { if (str.match(regexEmoji)) { const emojiShortcode = str.split(regexEmoji)[1] @@ -46,23 +47,26 @@ const Emojis: React.FC = ({ {emojiShortcode} ) : ( - + + + ) } else { - return ( + return str ? ( {str} + ) : ( + undefined ) } })} - - ) : ( - {content} + ) } diff --git a/src/components/Timelines/Timeline/Shared/HeaderDefault.tsx b/src/components/Timelines/Timeline/Shared/HeaderDefault.tsx index 10c089fd..cb657423 100644 --- a/src/components/Timelines/Timeline/Shared/HeaderDefault.tsx +++ b/src/components/Timelines/Timeline/Shared/HeaderDefault.tsx @@ -166,7 +166,7 @@ const HeaderDefault: React.FC = ({ - {emojis ? ( + {emojis?.length ? ( = ({ fontBold={true} /> ) : ( - + {name} )} @@ -193,6 +196,7 @@ const HeaderDefault: React.FC = ({ /> )} + @@ -224,7 +228,7 @@ const HeaderDefault: React.FC = ({ > {accountId !== localAccountId && ( { + onPress={() => { setModalVisible(false) mutateAction({ id: accountId, @@ -238,7 +242,7 @@ const HeaderDefault: React.FC = ({ )} {accountId !== localAccountId && ( { + onPress={() => { setModalVisible(false) mutateAction({ id: accountId, @@ -252,7 +256,7 @@ const HeaderDefault: React.FC = ({ )} {domain !== localDomain && ( { + onPress={() => { setModalVisible(false) mutateAction({ id: domain, @@ -265,7 +269,7 @@ const HeaderDefault: React.FC = ({ )} {accountId !== localAccountId && ( { + onPress={() => { setModalVisible(false) mutateAction({ id: accountId, @@ -288,17 +292,20 @@ const styles = StyleSheet.create({ justifyContent: 'space-between' }, name: { - flexBasis: '80%', + flexBasis: '90%', flexDirection: 'row' }, + nameWithoutEmoji: { + fontSize: StyleConstants.Font.Size.M, + fontWeight: StyleConstants.Font.Weight.Bold + }, action: { - flexBasis: '20%', - alignItems: 'center' + alignItems: 'flex-end' }, account: { flexShrink: 1, - marginLeft: StyleConstants.Spacing.XS, - lineHeight: StyleConstants.Font.Size.M + 2 + marginLeft: StyleConstants.Spacing.XS + // lineHeight: StyleConstants.Font.LineHeight.M }, meta: { flexDirection: 'row', diff --git a/src/i18n/zh/screens/meSettings.ts b/src/i18n/zh/screens/meSettings.ts index 9abf7d86..182b6384 100644 --- a/src/i18n/zh/screens/meSettings.ts +++ b/src/i18n/zh/screens/meSettings.ts @@ -17,6 +17,10 @@ export default { dark: '深色模式', cancel: '$t(common:buttons.cancel)' } - } + }, + copyrights: { + heading: '版权信息' + }, + version: '版本 v{{version}}' } } diff --git a/src/screens/Me/Settings.tsx b/src/screens/Me/Settings.tsx index f84df789..457e3175 100644 --- a/src/screens/Me/Settings.tsx +++ b/src/screens/Me/Settings.tsx @@ -1,6 +1,6 @@ import React from 'react' import { useTranslation } from 'react-i18next' -import { ActionSheetIOS } from 'react-native' +import { ActionSheetIOS, StyleSheet, Text } from 'react-native' import { useDispatch, useSelector } from 'react-redux' import { MenuContainer, MenuItem } from 'src/components/Menu' @@ -10,81 +10,101 @@ import { getSettingsLanguage, getSettingsTheme } from 'src/utils/slices/settingsSlice' +import { StyleConstants } from 'src/utils/styles/constants' import { useTheme } from 'src/utils/styles/ThemeManager' const ScreenMeSettings: React.FC = () => { const { t, i18n } = useTranslation('meSettings') - const { setTheme } = useTheme() + const { setTheme, theme } = useTheme() const settingsLanguage = useSelector(getSettingsLanguage) const settingsTheme = useSelector(getSettingsTheme) const dispatch = useDispatch() return ( - - - ActionSheetIOS.showActionSheetWithOptions( - { - options: [ - t('content.language.options.zh'), - t('content.language.options.en'), - t('content.language.options.cancel') - ], - cancelButtonIndex: 2 - }, - buttonIndex => { - switch (buttonIndex) { - case 0: - dispatch(changeLanguage('zh')) - i18n.changeLanguage('zh') - break - case 1: - dispatch(changeLanguage('en')) - i18n.changeLanguage('en') - break + <> + + + ActionSheetIOS.showActionSheetWithOptions( + { + options: [ + t('content.language.options.zh'), + t('content.language.options.en'), + t('content.language.options.cancel') + ], + cancelButtonIndex: 2 + }, + buttonIndex => { + switch (buttonIndex) { + case 0: + dispatch(changeLanguage('zh')) + i18n.changeLanguage('zh') + break + case 1: + dispatch(changeLanguage('en')) + i18n.changeLanguage('en') + break + } } - } - ) - } - /> - - 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 + ) + } + /> + + 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 + } } - } - ) - } - /> - + ) + } + /> + + + + + {t('content.version', { version: '1.0.0' })} + + + ) } +const styles = StyleSheet.create({ + version: { + textAlign: 'center', + fontSize: StyleConstants.Font.Size.S, + marginTop: StyleConstants.Spacing.M + } +}) + export default ScreenMeSettings diff --git a/src/screens/Shared/Account/Information.tsx b/src/screens/Shared/Account/Information.tsx index c9ad8602..93aaecb0 100644 --- a/src/screens/Shared/Account/Information.tsx +++ b/src/screens/Shared/Account/Information.tsx @@ -7,6 +7,7 @@ import ParseContent from 'src/components/ParseContent' import { useTheme } from 'src/utils/styles/ThemeManager' import { StyleConstants } from 'src/utils/styles/constants' import { useTranslation } from 'react-i18next' +import Emojis from 'src/components/Timelines/Timeline/Shared/Emojis' export interface Props { account: Mastodon.Account | undefined @@ -17,7 +18,6 @@ const AccountInformation: React.FC = ({ account }) => { const { theme } = useTheme() const [avatarLoaded, setAvatarLoaded] = useState(false) - // add emoji support return ( {/* Moved or not: {account.moved} */} @@ -29,27 +29,69 @@ const AccountInformation: React.FC = ({ account }) => { /> - - {account?.display_name || account?.username} - {account?.bot && ( - + + {account?.emojis ? ( + + ) : ( + + {account?.display_name || account?.username} + )} - + - - @{account?.acct} - {account?.locked && } - + + + @{account?.acct} + + {account?.locked && ( + + )} + {account?.bot && ( + + )} + - {account?.fields && ( - + {account?.fields && account.fields.length > 0 && ( + {account.fields.map((field, index) => ( - - + = ({ account }) => { size={StyleConstants.Font.Size.M} emojis={account.emojis} showFullLink - />{' '} - {field.verified_at && } - - + /> + {field.verified_at && ( + + )} + + - + ))} @@ -83,41 +139,46 @@ const AccountInformation: React.FC = ({ account }) => { )} - {account?.created_at && ( - - - - {t('content.created_at', { - date: new Date(account.created_at).toLocaleDateString('zh-CN', { + + + + {t( + 'content.created_at', + { + date: new Date(account?.created_at!).toLocaleDateString('zh-CN', { year: 'numeric', month: 'long', day: 'numeric' }) - })} - - - )} + } || null + )} + + {t('content.summary.statuses_count', { - count: account?.statuses_count + count: account?.statuses_count || 0 })} - + {t('content.summary.followers_count', { - count: account?.followers_count + count: account?.followers_count || 0 })} - + {t('content.summary.following_count', { - count: account?.following_count + count: account?.following_count || 0 })} @@ -136,26 +197,40 @@ const styles = StyleSheet.create({ borderRadius: 8 }, display_name: { - fontSize: StyleConstants.Font.Size.L, - fontWeight: StyleConstants.Font.Weight.Bold, + flexDirection: 'row', marginTop: StyleConstants.Spacing.M, marginBottom: StyleConstants.Spacing.XS }, account: { - fontSize: StyleConstants.Font.Size.M, - marginBottom: StyleConstants.Spacing.S + flexDirection: 'row', + alignItems: 'center', + marginBottom: StyleConstants.Spacing.L }, + account_types: { marginLeft: StyleConstants.Spacing.S }, fields: { - marginBottom: StyleConstants.Spacing.S + borderTopWidth: 0.5, + marginBottom: StyleConstants.Spacing.M + }, + field: { + flex: 1, + flexDirection: 'row', + borderBottomWidth: 0.5, + paddingTop: StyleConstants.Spacing.S, + paddingBottom: StyleConstants.Spacing.S }, note: { - marginBottom: StyleConstants.Spacing.M + marginBottom: StyleConstants.Spacing.L }, created_at: { flexDirection: 'row', + alignItems: 'center', marginBottom: StyleConstants.Spacing.M }, + created_at_icon: { + marginRight: StyleConstants.Spacing.XS + }, summary: { + flex: 1, flexDirection: 'row', justifyContent: 'space-between' } diff --git a/src/screens/Shared/Webview.tsx b/src/screens/Shared/Webview.tsx index e32fc309..e3b1d4e4 100644 --- a/src/screens/Shared/Webview.tsx +++ b/src/screens/Shared/Webview.tsx @@ -1,8 +1,11 @@ import { useNavigation } from '@react-navigation/native' import React, { useRef, useState } from 'react' import { useTranslation } from 'react-i18next' +import { ActionSheetIOS } from 'react-native' import { createNativeStackNavigator } from 'react-native-screens/native-stack' import { WebView } from 'react-native-webview' +import BottomSheet from 'src/components/BottomSheet' +import BottomSheetRow from 'src/components/BottomSheet/Row' import { HeaderLeft, HeaderRight } from 'src/components/Header' @@ -24,6 +27,7 @@ const ScreenSharedWebview: React.FC = ({ const navigation = useNavigation() const { t } = useTranslation('sharedWebview') const [title, setTitle] = useState(t('heading.loading')) + const [bottomSheet, showBottomSheet] = useState(false) const webview = useRef(null) return ( @@ -40,19 +44,56 @@ const ScreenSharedWebview: React.FC = ({ ), headerRight: () => ( webview.current?.reload()} + icon='more-horizontal' + onPress={() => showBottomSheet(true)} /> ) }} > {() => ( - setTitle(nativeEvent.title)} - onError={() => setTitle(t('heading.error'))} - /> + <> + setTitle(nativeEvent.title)} + onError={() => setTitle(t('heading.error'))} + /> + showBottomSheet(false)} + > + { + ActionSheetIOS.showShareActionSheetWithOptions( + { + url: uri, + excludedActivityTypes: [ + 'com.apple.UIKit.activity.Mail', + 'com.apple.UIKit.activity.Print', + 'com.apple.UIKit.activity.SaveToCameraRoll', + 'com.apple.UIKit.activity.OpenInIBooks' + ] + }, + () => {}, + () => { + showBottomSheet(false) + } + ) + }} + icon='share' + text={'分享链接'} + /> + { + showBottomSheet(false) + webview.current?.reload() + }} + icon='refresh-cw' + text='刷新' + /> + + )} diff --git a/src/utils/styles/ThemeManager.tsx b/src/utils/styles/ThemeManager.tsx index 13727a57..443132e6 100644 --- a/src/utils/styles/ThemeManager.tsx +++ b/src/utils/styles/ThemeManager.tsx @@ -1,5 +1,5 @@ import React, { createContext, useContext, useEffect, useState } from 'react' -import { Appearance } from 'react-native-appearance' +import { useColorScheme } from 'react-native-appearance' import { useSelector } from 'react-redux' import { ColorDefinitions, getTheme } from 'src/utils/styles/themes' import { getSettingsTheme } from '../slices/settingsSlice' @@ -19,11 +19,10 @@ export const ManageThemeContext = createContext({ export const useTheme = () => useContext(ManageThemeContext) const ThemeManager: React.FC = ({ children }) => { + const osTheme = useColorScheme() const userTheme = useSelector(getSettingsTheme) const currentMode = - userTheme === 'auto' - ? (Appearance.getColorScheme() as 'light' | 'dark') - : userTheme + userTheme === 'auto' ? (osTheme as 'light' | 'dark') : userTheme const [mode, setMode] = useState(currentMode) diff --git a/src/utils/styles/constants.ts b/src/utils/styles/constants.ts index 5b5e9719..8f724d60 100644 --- a/src/utils/styles/constants.ts +++ b/src/utils/styles/constants.ts @@ -4,9 +4,10 @@ export const StyleConstants = { Font: { Size: { S: 12, - M: 14, + M: 16, L: 18 }, + LineHeight: { M: 20 }, Weight: { Bold: '600' as '600' } @@ -19,7 +20,7 @@ export const StyleConstants = { L: Base * 6, XL: Base * 10, Global: { - PagePadding: Base * 6 + PagePadding: Base * 4 } },