Lots of updates

This commit is contained in:
Zhiyuan Zheng 2020-11-24 00:18:47 +01:00
parent fba1d0d531
commit 8200375c92
No known key found for this signature in database
GPG Key ID: 078A93AB607D85E0
23 changed files with 378 additions and 152 deletions

View File

@ -16,9 +16,18 @@ import ScreenMe from 'src/screens/Me'
import { themes } from 'src/utils/styles/themes' import { themes } from 'src/utils/styles/themes'
import { useTheme } from 'src/utils/styles/ThemeManager' import { useTheme } from 'src/utils/styles/ThemeManager'
import getCurrentTab from 'src/utils/getCurrentTab'
enableScreens() enableScreens()
const Tab = createBottomTabNavigator() const Tab = createBottomTabNavigator<RootStackParamList>()
export type RootStackParamList = {
'Screen-Local': undefined
'Screen-Public': { publicTab: boolean }
'Screen-Post': undefined
'Screen-Notifications': undefined
'Screen-Me': undefined
}
export const Index: React.FC = () => { export const Index: React.FC = () => {
const { mode, theme } = useTheme() const { mode, theme } = useTheme()
@ -65,11 +74,7 @@ export const Index: React.FC = () => {
listeners={({ navigation, route }) => ({ listeners={({ navigation, route }) => ({
tabPress: e => { tabPress: e => {
e.preventDefault() e.preventDefault()
const { navigation.navigate(getCurrentTab(navigation), {
length,
[length - 1]: last
} = navigation.dangerouslyGetState().history
navigation.navigate(last.key.split(new RegExp(/(.*)-/))[1], {
screen: 'Screen-Shared-Compose' screen: 'Screen-Shared-Compose'
}) })
} }

View File

@ -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<Props> = ({ text, destructive = false }) => {
const { theme } = useTheme()
return (
<View style={styles.core}>
<Text style={{ color: destructive ? theme.dangerous : theme.primary }}>
{text}
</Text>
</View>
)
}
const MenuButton: React.FC<Props> = ({ ...props }) => {
const { theme } = useTheme()
return (
<Pressable
style={[styles.base, { borderBottomColor: theme.separator }]}
onPress={() =>
props.alertOption &&
Alert.alert(
props.alertOption.title,
props.alertOption.message,
props.alertOption.buttons,
props.alertOption.options
)
}
>
<Core {...props} />
</Pressable>
)
}
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

View File

@ -1,8 +1,24 @@
import React from 'react' 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 }) => { const MenuContainer: React.FC = ({ ...props }) => {
return <View>{props.children}</View> const { theme } = useTheme()
return (
<View style={[styles.base, { borderTopColor: theme.separator }]}>
{props.children}
</View>
)
} }
const styles = StyleSheet.create({
base: {
borderTopWidth: 1,
marginBottom: constants.SPACING_M
}
})
export default MenuContainer export default MenuContainer

View File

@ -4,6 +4,8 @@ import { useNavigation } from '@react-navigation/native'
import { Feather } from '@expo/vector-icons' import { Feather } from '@expo/vector-icons'
import { useTheme } from 'src/utils/styles/ThemeManager' import { useTheme } from 'src/utils/styles/ThemeManager'
import constants from 'src/utils/styles/constants'
export interface Props { export interface Props {
icon?: string icon?: string
title: string title: string
@ -16,8 +18,17 @@ const Core: React.FC<Props> = ({ icon, title, navigateTo }) => {
return ( return (
<View style={styles.core}> <View style={styles.core}>
{icon && <Feather name={icon} size={24} style={styles.iconLeading} />} {icon && (
<Text>{title}</Text> <Feather
name={icon}
size={constants.FONT_SIZE_M + 2}
style={styles.iconLeading}
color={theme.primary}
/>
)}
<Text style={{ color: theme.primary, fontSize: constants.FONT_SIZE_M }}>
{title}
</Text>
{navigateTo && ( {navigateTo && (
<Feather <Feather
name='chevron-right' name='chevron-right'
@ -31,11 +42,12 @@ const Core: React.FC<Props> = ({ icon, title, navigateTo }) => {
} }
const MenuItem: React.FC<Props> = ({ ...props }) => { const MenuItem: React.FC<Props> = ({ ...props }) => {
const { theme } = useTheme()
const navigation = useNavigation() const navigation = useNavigation()
return props.navigateTo ? ( return props.navigateTo ? (
<Pressable <Pressable
style={styles.base} style={[styles.base, { borderBottomColor: theme.separator }]}
onPress={() => { onPress={() => {
navigation.navigate(props.navigateTo!, props.navigateToParams) navigation.navigate(props.navigateTo!, props.navigateToParams)
}} }}
@ -52,15 +64,14 @@ const MenuItem: React.FC<Props> = ({ ...props }) => {
const styles = StyleSheet.create({ const styles = StyleSheet.create({
base: { base: {
height: 50, height: 50,
borderBottomColor: 'lightgray',
borderBottomWidth: 1 borderBottomWidth: 1
}, },
core: { core: {
flex: 1, flex: 1,
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
paddingLeft: 12, paddingLeft: constants.GLOBAL_PAGE_PADDING,
paddingRight: 12 paddingRight: constants.GLOBAL_PAGE_PADDING
}, },
iconLeading: { iconLeading: {
marginRight: 8 marginRight: 8

View File

@ -0,0 +1,8 @@
import React from 'react'
import { Text } from 'react-native'
const PleaseLogin = () => {
return <Text></Text>
}
export default PleaseLogin

View File

@ -7,9 +7,12 @@ import { Feather } from '@expo/vector-icons'
import Timeline from './Timelines/Timeline' import Timeline from './Timelines/Timeline'
import sharedScreens from 'src/screens/Shared/sharedScreens' import sharedScreens from 'src/screens/Shared/sharedScreens'
import { InstancesState } from 'src/utils/slices/instancesSlice' import { getRemoteUrl, InstancesState } from 'src/utils/slices/instancesSlice'
import { RootState } from 'src/store' import { RootState, store } from 'src/store'
import { useTheme } from 'src/utils/styles/ThemeManager' 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() const Stack = createNativeStackNavigator()
@ -25,22 +28,24 @@ const Page = ({
{localRegistered || page === 'RemotePublic' ? ( {localRegistered || page === 'RemotePublic' ? (
<Timeline page={page} /> <Timeline page={page} />
) : ( ) : (
<Text></Text> <PleaseLogin />
)} )}
</View> </View>
) )
} }
export interface Props { export interface Props {
name: string name: 'Screen-Local-Root' | 'Screen-Public-Root'
content: { title: string; page: App.Pages }[] content: { title: string; page: App.Pages }[]
} }
const Timelines: React.FC<Props> = ({ name, content }) => { const Timelines: React.FC<Props> = ({ name, content }) => {
const navigation = useNavigation()
const { theme } = useTheme() const { theme } = useTheme()
const localRegistered = useSelector( const localRegistered = useSelector(
(state: RootState) => state.instances.local.url (state: RootState) => state.instances.local.url
) )
const publicDomain = getRemoteUrl(store.getState())
const [segment, setSegment] = useState(0) const [segment, setSegment] = useState(0)
const [renderHeader, setRenderHeader] = useState(false) const [renderHeader, setRenderHeader] = useState(false)
const [segmentManuallyTriggered, setSegmentManuallyTriggered] = useState( const [segmentManuallyTriggered, setSegmentManuallyTriggered] = useState(
@ -59,58 +64,80 @@ const Timelines: React.FC<Props> = ({ name, content }) => {
<Stack.Screen <Stack.Screen
name={name} name={name}
options={{ options={{
headerRight: () => headerTitle: name === 'Screen-Public-Root' ? publicDomain : '',
renderHeader ? ( ...(renderHeader &&
<Feather name='search' size={24} color={theme.secondary} /> localRegistered && {
) : null, headerCenter: () => (
headerCenter: () => <SegmentedControl
renderHeader ? ( values={[content[0].title, content[1].title]}
<SegmentedControl selectedIndex={segment}
values={[content[0].title, content[1].title]} onChange={({ nativeEvent }) => {
selectedIndex={segment} setSegmentManuallyTriggered(true)
onChange={({ nativeEvent }) => { setSegment(nativeEvent.selectedSegmentIndex)
setSegmentManuallyTriggered(true) horizontalPaging.current.scrollToIndex({
setSegment(nativeEvent.selectedSegmentIndex) index: nativeEvent.selectedSegmentIndex
horizontalPaging.current.scrollToIndex({ })
index: nativeEvent.selectedSegmentIndex }}
}) style={{ width: 150, height: 30 }}
}} />
style={{ width: 150, height: 30 }} ),
/> headerRight: () => (
) : null <Feather
name='search'
size={24}
color={theme.secondary}
onPress={() => {
navigation.navigate(getCurrentTab(navigation), {
screen: 'Screen-Shared-Search'
})
}}
/>
)
})
}} }}
> >
{() => ( {() => {
<FlatList return (
style={{ width: Dimensions.get('window').width, height: '100%' }} <FlatList
data={content} style={{ width: Dimensions.get('window').width, height: '100%' }}
extraData={localRegistered} data={content}
keyExtractor={({ page }) => page} extraData={localRegistered}
renderItem={({ item, index }) => ( keyExtractor={({ page }) => page}
<Page key={index} item={item} localRegistered={localRegistered} /> renderItem={({ item, index }) => {
)} if (!localRegistered && index === 0) {
ref={horizontalPaging} return null
bounces={false} }
getItemLayout={(data, index) => ({ return (
length: Dimensions.get('window').width, <Page
offset: Dimensions.get('window').width * index, key={index}
index item={item}
})} localRegistered={localRegistered}
horizontal />
onMomentumScrollEnd={() => setSegmentManuallyTriggered(false)} )
onScroll={({ nativeEvent }) => }}
!segmentManuallyTriggered && ref={horizontalPaging}
setSegment( bounces={false}
nativeEvent.contentOffset.x <= getItemLayout={(data, index) => ({
Dimensions.get('window').width / 2 length: Dimensions.get('window').width,
? 0 offset: Dimensions.get('window').width * index,
: 1 index
) })}
} horizontal
pagingEnabled onMomentumScrollEnd={() => setSegmentManuallyTriggered(false)}
showsHorizontalScrollIndicator={false} onScroll={({ nativeEvent }) =>
/> !segmentManuallyTriggered &&
)} setSegment(
nativeEvent.contentOffset.x <=
Dimensions.get('window').width / 2
? 0
: 1
)
}
pagingEnabled
showsHorizontalScrollIndicator={false}
/>
)
}}
</Stack.Screen> </Stack.Screen>
{sharedScreens(Stack)} {sharedScreens(Stack)}

View File

@ -13,7 +13,8 @@ const TimelineSeparator = () => {
const styles = StyleSheet.create({ const styles = StyleSheet.create({
base: { base: {
borderTopWidth: 1, 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
} }
}) })

View File

@ -2,6 +2,8 @@ import React from 'react'
import { Image, StyleSheet, Text } from 'react-native' import { Image, StyleSheet, Text } from 'react-native'
import { useTheme } from 'src/utils/styles/ThemeManager' import { useTheme } from 'src/utils/styles/ThemeManager'
import constants from 'src/utils/styles/constants'
const regexEmoji = new RegExp(/(:[a-z0-9_]+:)/) const regexEmoji = new RegExp(/(:[a-z0-9_]+:)/)
export interface Props { export interface Props {
@ -23,7 +25,7 @@ const Emojis: React.FC<Props> = ({
fontSize: size, fontSize: size,
lineHeight: size + 2, lineHeight: size + 2,
color: theme.primary, color: theme.primary,
...(fontBold && { fontWeight: 'bold' }) ...(fontBold && { fontWeight: constants.FONT_WEIGHT_BOLD })
}, },
image: { image: {
width: size, width: size,

View File

@ -5,7 +5,7 @@ import Timelines from 'src/components/Timelines'
const ScreenLocal: React.FC = () => { const ScreenLocal: React.FC = () => {
return ( return (
<Timelines <Timelines
name='Local' name='Screen-Local-Root'
content={[ content={[
{ title: '关注', page: 'Following' }, { title: '关注', page: 'Following' },
{ title: '本站', page: 'Local' } { title: '本站', page: 'Local' }

View File

@ -8,24 +8,30 @@ import ScreenMeFavourites from './Me/Favourites'
import ScreenMeLists from './Me/Lists' import ScreenMeLists from './Me/Lists'
import sharedScreens from 'src/screens/Shared/sharedScreens' import sharedScreens from 'src/screens/Shared/sharedScreens'
import ScreenMeListsList from './Me/Root/Lists/List' import ScreenMeListsList from './Me/Root/Lists/List'
import { useSelector } from 'react-redux'
import { RootState } from 'src/store'
const Stack = createNativeStackNavigator() const Stack = createNativeStackNavigator()
const ScreenMe: React.FC = () => { const ScreenMe: React.FC = () => {
const localRegistered = useSelector(
(state: RootState) => state.instances.local.url
)
return ( return (
<Stack.Navigator <Stack.Navigator>
screenOptions={{
headerTitle: 'test'
}}
>
<Stack.Screen <Stack.Screen
name='Screen-Me-Root' name='Screen-Me-Root'
component={ScreenMeRoot} component={ScreenMeRoot}
options={{ options={
headerTranslucent: true, localRegistered
headerStyle: { backgroundColor: 'rgba(255, 255, 255, 0)' }, ? {
headerCenter: () => <></> headerTranslucent: true,
}} headerStyle: { backgroundColor: 'rgba(255, 255, 255, 0)' },
headerCenter: () => <></>
}
: { headerTitle: '我的长毛象' }
}
/> />
<Stack.Screen <Stack.Screen
name='Screen-Me-Conversations' name='Screen-Me-Conversations'

View File

@ -9,6 +9,7 @@ import Login from './Root/Login'
import MyInfo from './Root/MyInfo' import MyInfo from './Root/MyInfo'
import MyCollections from './Root/MyCollections' import MyCollections from './Root/MyCollections'
import Settings from './Root/Settings' import Settings from './Root/Settings'
import Logout from './Root/Logout'
const ScreenMeRoot: React.FC = () => { const ScreenMeRoot: React.FC = () => {
const localRegistered = useSelector( const localRegistered = useSelector(
@ -26,6 +27,7 @@ const ScreenMeRoot: React.FC = () => {
<MyCollections id={getLocalAccountId(store.getState())!} /> <MyCollections id={getLocalAccountId(store.getState())!} />
)} )}
<Settings /> <Settings />
{localRegistered && <Logout />}
</ScrollView> </ScrollView>
) )
} }

View File

@ -1,5 +1,5 @@
import React, { useCallback, useEffect, useState } from 'react' 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 { useQuery } from 'react-query'
import { debounce } from 'lodash' import { debounce } from 'lodash'
@ -9,8 +9,12 @@ import * as AuthSession from 'expo-auth-session'
import { useDispatch } from 'react-redux' import { useDispatch } from 'react-redux'
import { updateLocal } from 'src/utils/slices/instancesSlice' import { updateLocal } from 'src/utils/slices/instancesSlice'
import { useNavigation } from '@react-navigation/native' 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 Login: React.FC = () => {
const { theme } = useTheme()
const navigation = useNavigation() const navigation = useNavigation()
const dispatch = useDispatch() const dispatch = useDispatch()
const [instance, setInstance] = useState('') const [instance, setInstance] = useState('')
@ -109,23 +113,34 @@ const Login: React.FC = () => {
} }
) )
dispatch(updateLocal({ url: instance, token: accessToken })) dispatch(updateLocal({ url: instance, token: accessToken }))
navigation.navigate('Local') navigation.navigate('Screen-Local-Root')
} }
})() })()
}, [response]) }, [response])
return ( return (
<View> <View style={styles.base}>
<TextInput <TextInput
style={{ height: 40, borderColor: 'gray', borderWidth: 1 }} style={{
height: 50,
color: theme.primary,
borderColor: theme.border,
borderWidth: 1,
padding: constants.SPACING_M
}}
onChangeText={onChangeText} onChangeText={onChangeText}
autoCapitalize='none' autoCapitalize='none'
autoCorrect={false} autoCorrect={false}
autoFocus
clearButtonMode='unless-editing' clearButtonMode='unless-editing'
keyboardType='url' keyboardType='url'
textContentType='URL' textContentType='URL'
onSubmitEditing={async () =>
isSuccess && data && data.uri && (await createApplication())
}
placeholder='输入服务器' placeholder='输入服务器'
placeholderTextColor='#888888' placeholderTextColor={theme.secondary}
returnKeyType='go'
/> />
<Button <Button
title='登录' title='登录'
@ -134,11 +149,17 @@ const Login: React.FC = () => {
/> />
{isSuccess && data && data.uri && ( {isSuccess && data && data.uri && (
<View> <View>
<Text>{data.title}</Text> <Text style={{ color: theme.primary }}>{data.title}</Text>
</View> </View>
)} )}
</View> </View>
) )
} }
const styles = StyleSheet.create({
base: {
padding: constants.GLOBAL_PAGE_PADDING
}
})
export default Login export default Login

View File

@ -0,0 +1,46 @@
import React from 'react'
import { useDispatch } from 'react-redux'
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'
const Logout: React.FC = () => {
const dispatch = useDispatch()
const navigation = useNavigation()
const alertOption = {
title: '确认退出登录?',
message: '退出登录后,需要重新认证账号',
buttons: [
{
text: '退出登录',
style: 'destructive' as const,
onPress: () => {
dispatch(updateLocal({}))
navigation.navigate('Screen-Public', {
screen: 'Screen-Public-Root',
params: { publicTab: true }
})
}
},
{
text: '取消',
style: 'cancel' as const
}
]
}
return (
<MenuContainer>
<MenuButton
text='退出当前账号'
destructive={true}
alertOption={alertOption}
/>
</MenuContainer>
)
}
export default Logout

View File

@ -1,5 +1,5 @@
import React from 'react' import React from 'react'
import { MenuContainer, MenuHeader, MenuItem } from 'src/components/Menu' import { MenuContainer, MenuItem } from 'src/components/Menu'
export interface Props { export interface Props {
id: Mastodon.Account['id'] id: Mastodon.Account['id']
@ -8,7 +8,6 @@ export interface Props {
const MyInfo: React.FC<Props> = ({ id }) => { const MyInfo: React.FC<Props> = ({ id }) => {
return ( return (
<MenuContainer> <MenuContainer>
<MenuHeader heading='我的东西' />
<MenuItem icon='mail' title='私信' navigateTo='Screen-Me-Conversations' /> <MenuItem icon='mail' title='私信' navigateTo='Screen-Me-Conversations' />
<MenuItem icon='bookmark' title='书签' navigateTo='Screen-Me-Bookmarks' /> <MenuItem icon='bookmark' title='书签' navigateTo='Screen-Me-Bookmarks' />
<MenuItem icon='star' title='喜欢' navigateTo='Screen-Me-Favourites' /> <MenuItem icon='star' title='喜欢' navigateTo='Screen-Me-Favourites' />

View File

@ -1,10 +1,9 @@
import React from 'react' import React from 'react'
import { MenuContainer, MenuHeader, MenuItem } from 'src/components/Menu' import { MenuContainer, MenuItem } from 'src/components/Menu'
const Settings: React.FC = () => { const Settings: React.FC = () => {
return ( return (
<MenuContainer> <MenuContainer>
<MenuHeader heading='设置' />
<MenuItem icon='settings' title='设置' navigateTo='Local' /> <MenuItem icon='settings' title='设置' navigateTo='Local' />
</MenuContainer> </MenuContainer>
) )

View File

@ -1,36 +1,25 @@
import React, { useEffect, useState } from 'react' import React from 'react'
import { createNativeStackNavigator } from 'react-native-screens/native-stack' import { createNativeStackNavigator } from 'react-native-screens/native-stack'
import { Feather } from '@expo/vector-icons'
import Timeline from 'src/components/Timelines/Timeline' import Timeline from 'src/components/Timelines/Timeline'
import sharedScreens from 'src/screens/Shared/sharedScreens' import sharedScreens from 'src/screens/Shared/sharedScreens'
import { useTheme } from 'src/utils/styles/ThemeManager' import { useSelector } from 'react-redux'
import { RootState } from 'src/store'
import PleaseLogin from 'src/components/PleaseLogin'
const Stack = createNativeStackNavigator() const Stack = createNativeStackNavigator()
const ScreenNotifications: React.FC = () => { const ScreenNotifications: React.FC = () => {
const { theme } = useTheme() const localRegistered = useSelector(
(state: RootState) => state.instances.local.url
const [renderHeader, setRenderHeader] = useState(false) )
useEffect(() => {
const nbr = setTimeout(() => setRenderHeader(true), 50)
return
}, [])
return ( return (
<Stack.Navigator <Stack.Navigator screenOptions={{ headerTitle: '通知' }}>
screenOptions={{ <Stack.Screen name='Screen-Notifications-Root'>
headerRight: () => {() =>
renderHeader ? ( localRegistered ? <Timeline page='Notifications' /> : <PleaseLogin />
<Feather name='search' size={24} color={theme.secondary} /> }
) : null,
headerTitle: '通知',
headerLargeTitle: true
}}
>
<Stack.Screen name='Notifications'>
{() => <Timeline page='Notifications' />}
</Stack.Screen> </Stack.Screen>
{sharedScreens(Stack)} {sharedScreens(Stack)}

View File

@ -5,7 +5,7 @@ import Timelines from 'src/components/Timelines'
const ScreenPublic: React.FC = () => { const ScreenPublic: React.FC = () => {
return ( return (
<Timelines <Timelines
name='Public' name='Screen-Public-Root'
content={[ content={[
{ title: '跨站', page: 'LocalPublic' }, { title: '跨站', page: 'LocalPublic' },
{ title: '他站', page: 'RemotePublic' } { title: '他站', page: 'RemotePublic' }

View File

@ -0,0 +1,7 @@
import React from 'react'
const ScreenSharedSearch: React.FC = () => {
return <></>
}
export default ScreenSharedSearch

View File

@ -5,27 +5,9 @@ import ScreenSharedHashtag from 'src/screens/Shared/Hashtag'
import ScreenSharedToot from 'src/screens/Shared/Toot' import ScreenSharedToot from 'src/screens/Shared/Toot'
import ScreenSharedWebview from 'src/screens/Shared/Webview' import ScreenSharedWebview from 'src/screens/Shared/Webview'
import Compose from 'src/screens/Shared/Compose' import Compose from 'src/screens/Shared/Compose'
import { TypedNavigator } from '@react-navigation/native' import ScreenSharedSearch from './Search'
import { NativeStackNavigationOptions } from 'react-native-screens/lib/typescript'
import {
NativeStackNavigationEventMap,
NativeStackNavigatorProps
} from 'react-native-screens/lib/typescript/types'
const sharedScreens = ( const sharedScreens = (Stack: any) => {
Stack: TypedNavigator<
Record<string, object | undefined>,
any,
NativeStackNavigationOptions,
NativeStackNavigationEventMap,
({
initialRouteName,
children,
screenOptions,
...rest
}: NativeStackNavigatorProps) => JSX.Element
>
) => {
return [ return [
<Stack.Screen <Stack.Screen
key='Screen-Shared-Account' key='Screen-Shared-Account'
@ -68,6 +50,14 @@ const sharedScreens = (
options={{ options={{
stackPresentation: 'fullScreenModal' stackPresentation: 'fullScreenModal'
}} }}
/>,
<Stack.Screen
key='Screen-Shared-Search'
name='Screen-Shared-Search'
component={ScreenSharedSearch}
options={{
stackPresentation: 'modal'
}}
/> />
] ]
} }

View File

@ -0,0 +1,9 @@
const getCurrentTab = (navigation: any) => {
const {
length,
[length - 1]: last
} = navigation.dangerouslyGetState().history
return `Screen-${last.key.split(new RegExp(/Screen-(.*?)-/))[1]}`
}
export default getCurrentTab

View File

@ -17,15 +17,34 @@ export type InstancesState = {
} }
} }
const initialStateLocal = {
url: undefined,
token: undefined,
account: {
id: undefined,
preferences: {
'posting:default:visibility': undefined,
'posting:default:sensitive': undefined,
'posting:default:language': undefined,
'reading:expand:media': undefined,
'reading:expand:spoilers': undefined
}
}
}
export const updateLocal = createAsyncThunk( export const updateLocal = createAsyncThunk(
'instances/updateLocal', 'instances/updateLocal',
async ({ async ({
url, url,
token token
}: { }: {
url: InstancesState['local']['url'] url?: InstancesState['local']['url']
token: InstancesState['local']['token'] token?: InstancesState['local']['token']
}) => { }) => {
if (!url || !token) {
return initialStateLocal
}
const { const {
body: { id } body: { id }
} = await client({ } = await client({
@ -58,22 +77,9 @@ export const updateLocal = createAsyncThunk(
const instancesSlice = createSlice({ const instancesSlice = createSlice({
name: 'instances', name: 'instances',
initialState: { initialState: {
local: { local: initialStateLocal,
url: undefined,
token: undefined,
account: {
id: undefined,
preferences: {
'posting:default:visibility': undefined,
'posting:default:sensitive': undefined,
'posting:default:language': undefined,
'reading:expand:media': undefined,
'reading:expand:spoilers': undefined
}
}
},
remote: { remote: {
url: 'mastodon.social' url: 'm.cmx.im'
} }
} as InstancesState, } as InstancesState,
reducers: {}, reducers: {},
@ -85,6 +91,7 @@ const instancesSlice = createSlice({
}) })
export const getLocalUrl = (state: RootState) => state.instances.local.url export const getLocalUrl = (state: RootState) => state.instances.local.url
export const getRemoteUrl = (state: RootState) => state.instances.remote.url
export const getLocalAccountId = (state: RootState) => export const getLocalAccountId = (state: RootState) =>
state.instances.local.account.id state.instances.local.account.id
export const getLocalAccountPreferences = (state: RootState) => export const getLocalAccountPreferences = (state: RootState) =>

View File

@ -3,6 +3,8 @@ export default {
FONT_SIZE_M: 14, FONT_SIZE_M: 14,
FONT_SIZE_L: 18, FONT_SIZE_L: 18,
FONT_WEIGHT_BOLD: '600',
SPACING_XS: 4, SPACING_XS: 4,
SPACING_S: 8, SPACING_S: 8,
SPACING_M: 16, SPACING_M: 16,

View File

@ -7,6 +7,7 @@ export type ColorDefinitions =
| 'link' | 'link'
| 'border' | 'border'
| 'separator' | 'separator'
| 'dangerous'
const themeColors: { const themeColors: {
[key in ColorDefinitions]: { [key in ColorDefinitions]: {
@ -37,6 +38,10 @@ const themeColors: {
separator: { separator: {
light: 'rgba(0, 0, 0, 0.1)', light: 'rgba(0, 0, 0, 0.1)',
dark: 'rgba(255, 255, 255, 0.1)' dark: 'rgba(255, 255, 255, 0.1)'
},
dangerous: {
light: 'rgb(255, 59, 48)',
dark: 'rgb(255, 69, 58)'
} }
} }