Skip to content
This repository was archived by the owner on Oct 19, 2024. It is now read-only.

Commit 97cad12

Browse files
committed
Basic mentions, hashtags and links highlighting working
1 parent 4cbba77 commit 97cad12

File tree

9 files changed

+185
-30
lines changed

9 files changed

+185
-30
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"@react-navigation/native": "^5.8.6",
1818
"@react-navigation/stack": "^5.12.3",
1919
"@reduxjs/toolkit": "^1.4.0",
20+
"autolinker": "^3.14.2",
2021
"expo": "~39.0.4",
2122
"expo-app-auth": "~9.2.0",
2223
"expo-av": "~8.6.0",
@@ -58,4 +59,4 @@
5859
"typescript": "~3.9.2"
5960
},
6061
"private": true
61-
}
62+
}

src/Index.tsx

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { StatusBar } from 'expo-status-bar'
1212

1313
import Local from 'src/stacks/Local'
1414
import Public from 'src/stacks/Public'
15-
import Post from 'src/stacks/Post'
15+
import PostRoot from 'src/stacks/PostRoot'
1616
import Notifications from 'src/stacks/Notifications'
1717
import Me from 'src/stacks/Me'
1818

@@ -36,7 +36,7 @@ export const Index: React.FC = () => {
3636
case 'Public':
3737
name = 'globe'
3838
break
39-
case 'Post':
39+
case 'PostRoot':
4040
name = 'plus'
4141
break
4242
case 'Notifications':
@@ -60,7 +60,22 @@ export const Index: React.FC = () => {
6060
>
6161
<Tab.Screen name='Local' component={Local} />
6262
<Tab.Screen name='Public' component={Public} />
63-
<Tab.Screen name='Post' component={Post} />
63+
<Tab.Screen
64+
name='PostRoot'
65+
component={PostRoot}
66+
listeners={({ navigation, route }) => ({
67+
tabPress: e => {
68+
e.preventDefault()
69+
const {
70+
length,
71+
[length - 1]: last
72+
} = navigation.dangerouslyGetState().history
73+
navigation.navigate(last.key.split(new RegExp(/(.*?)-/))[1], {
74+
screen: 'PostToot'
75+
})
76+
}
77+
})}
78+
/>
6479
<Tab.Screen name='Notifications' component={Notifications} />
6580
<Tab.Screen name='Me' component={Me} />
6681
</Tab.Navigator>

src/api/client.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ import store, { RootState } from 'src/stacks/common/store'
22
import ky from 'ky'
33

44
const client = async ({
5+
version = 'v1',
56
method,
67
instance,
78
endpoint,
89
query,
910
body
1011
}: {
12+
version: 'v1' | 'v2'
1113
method: 'get' | 'post' | 'delete'
1214
instance: 'local' | 'remote'
1315
endpoint: string
@@ -16,13 +18,13 @@ const client = async ({
1618
}
1719
body?: object
1820
}): Promise<any> => {
19-
const state: RootState["instanceInfo"] = store.getState().instanceInfo
21+
const state: RootState['instanceInfo'] = store.getState().instanceInfo
2022

2123
let response
2224
try {
2325
response = await ky(endpoint, {
2426
method: method,
25-
prefixUrl: `https://${state[instance]}/api/v1`,
27+
prefixUrl: `https://${state[instance]}/api/${version}`,
2628
searchParams: query,
2729
headers: {
2830
'Content-Type': 'application/json',

src/stacks/Me.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { createNativeStackNavigator } from 'react-native-screens/native-stack'
44
import Base from './Me/Base'
55
import Authentication from 'src/stacks/Me/Authentication'
66

7+
import sharedScreens from 'src/stacks/Shared/sharedScreens'
8+
79
const Stack = createNativeStackNavigator()
810

911
const Me: React.FC = () => {
@@ -17,6 +19,8 @@ const Me: React.FC = () => {
1719
stackPresentation: 'modal'
1820
}}
1921
/>
22+
23+
{sharedScreens(Stack)}
2024
</Stack.Navigator>
2125
)
2226
}

src/stacks/Post.tsx

Lines changed: 0 additions & 23 deletions
This file was deleted.

src/stacks/PostRoot.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import React from 'react'
2+
3+
const PostRoot: React.FC = () => {
4+
return <></>
5+
}
6+
7+
export default PostRoot

src/stacks/Shared/PostToot.tsx

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import { Feather } from '@expo/vector-icons'
2+
import React, { useCallback, useEffect, useState } from 'react'
3+
import {
4+
Keyboard,
5+
Pressable,
6+
StyleSheet,
7+
Text,
8+
TextInput,
9+
View
10+
} from 'react-native'
11+
import { createNativeStackNavigator } from 'react-native-screens/native-stack'
12+
import Autolinker, { HtmlTag } from 'autolinker'
13+
14+
const Stack = createNativeStackNavigator()
15+
16+
const PostTootMain = () => {
17+
const [viewHeight, setViewHeight] = useState(0)
18+
const [keyboardHeight, setKeyboardHeight] = useState(0)
19+
useEffect(() => {
20+
Keyboard.addListener('keyboardDidShow', _keyboardDidShow)
21+
Keyboard.addListener('keyboardDidHide', _keyboardDidHide)
22+
23+
// cleanup function
24+
return () => {
25+
Keyboard.removeListener('keyboardDidShow', _keyboardDidShow)
26+
Keyboard.removeListener('keyboardDidHide', _keyboardDidHide)
27+
}
28+
})
29+
const _keyboardDidShow = (props: any) => {
30+
setKeyboardHeight(props.endCoordinates.height)
31+
}
32+
33+
const _keyboardDidHide = () => {
34+
setKeyboardHeight(0)
35+
}
36+
37+
const [charCount, setCharCount] = useState(0)
38+
const [formattedText, setFormattedText] = useState<React.ReactNode>()
39+
const onChangeText = useCallback(content => {
40+
const tags: string[] = []
41+
Autolinker.link(content, {
42+
email: false,
43+
phone: false,
44+
mention: 'twitter',
45+
hashtag: 'twitter',
46+
replaceFn: props => {
47+
const tag = props.getMatchedText()
48+
tags.push(tag)
49+
return tag
50+
}
51+
})
52+
53+
let _content = content
54+
const children = []
55+
tags.forEach(tag => {
56+
const parts = _content.split(tag)
57+
children.push(parts.shift())
58+
children.push(<Text style={{ color: 'red' }}>{tag}</Text>)
59+
_content = parts.join(tag)
60+
})
61+
children.push(_content)
62+
63+
setFormattedText(React.createElement(Text, null, children))
64+
setCharCount(content.length)
65+
}, [])
66+
67+
return (
68+
<View
69+
style={styles.main}
70+
onLayout={({ nativeEvent }) => {
71+
setViewHeight(nativeEvent.layout.height)
72+
}}
73+
>
74+
<TextInput
75+
style={[styles.textInput, { height: viewHeight - keyboardHeight - 44 }]}
76+
autoCapitalize='none'
77+
autoFocus
78+
enablesReturnKeyAutomatically
79+
multiline
80+
placeholder='想说点什么'
81+
// value={rawText}
82+
onChangeText={onChangeText}
83+
scrollEnabled
84+
>
85+
<Text>{formattedText}</Text>
86+
</TextInput>
87+
<Pressable style={styles.additions} onPress={() => Keyboard.dismiss()}>
88+
<Feather name='paperclip' size={24} />
89+
<Feather name='bar-chart-2' size={24} />
90+
<Feather name='eye-off' size={24} />
91+
<Text>{charCount}</Text>
92+
</Pressable>
93+
</View>
94+
)
95+
}
96+
97+
const PostToot: React.FC = () => {
98+
return (
99+
<Stack.Navigator>
100+
<Stack.Screen
101+
name='PostTootMain'
102+
component={PostTootMain}
103+
options={{
104+
headerLeft: () => <Text>取消</Text>,
105+
headerCenter: () => <></>,
106+
headerRight: () => <Text>发嘟嘟</Text>
107+
}}
108+
/>
109+
</Stack.Navigator>
110+
)
111+
}
112+
113+
const styles = StyleSheet.create({
114+
main: {
115+
width: '100%',
116+
height: '100%'
117+
},
118+
textInput: {
119+
backgroundColor: 'gray'
120+
},
121+
additions: {
122+
height: 44,
123+
backgroundColor: 'red',
124+
flexDirection: 'row'
125+
}
126+
})
127+
128+
export default PostToot

src/stacks/Shared/sharedScreens.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Account from 'src/stacks/Shared/Account'
44
import Hashtag from 'src/stacks/Shared/Hashtag'
55
import Toot from 'src/stacks/Shared/Toot'
66
import Webview from 'src/stacks/Shared/Webview'
7+
import PostToot from './PostToot'
78

89
const sharedScreens = (Stack: any) => {
910
return [
@@ -21,7 +22,7 @@ const sharedScreens = (Stack: any) => {
2122
key='Hashtag'
2223
name='Hashtag'
2324
component={Hashtag}
24-
options={({ route }) => ({
25+
options={({ route }: any) => ({
2526
title: `#${decodeURIComponent(route.params.hashtag)}`
2627
})}
2728
/>,
@@ -40,6 +41,14 @@ const sharedScreens = (Stack: any) => {
4041
// options={({ route }) => ({
4142
// title: `${route.params.domain}`
4243
// })}
44+
/>,
45+
<Stack.Screen
46+
key='PostToot'
47+
name='PostToot'
48+
component={PostToot}
49+
options={{
50+
stackPresentation: 'modal'
51+
}}
4352
/>
4453
]
4554
}

yarn.lock

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1670,6 +1670,13 @@ atob@^2.1.2:
16701670
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
16711671
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
16721672

1673+
autolinker@^3.14.2:
1674+
version "3.14.2"
1675+
resolved "https://registry.yarnpkg.com/autolinker/-/autolinker-3.14.2.tgz#71856274eb768fb7149039e24d3a2be2f5c55a63"
1676+
integrity sha512-VO66nXUCZFxTq7fVHAaiAkZNXRQ1l3IFi6D5P7DLoyIEAn2E8g7TWbyEgLlz1uW74LfWmu1A17IPWuPQyGuNVg==
1677+
dependencies:
1678+
tslib "^1.9.3"
1679+
16731680
available-typed-arrays@^1.0.0, available-typed-arrays@^1.0.2:
16741681
version "1.0.2"
16751682
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz#6b098ca9d8039079ee3f77f7b783c4480ba513f5"
@@ -5791,6 +5798,11 @@ [email protected]:
57915798
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
57925799
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
57935800

5801+
tslib@^1.9.3:
5802+
version "1.14.1"
5803+
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
5804+
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
5805+
57945806
type-fest@^0.7.1:
57955807
version "0.7.1"
57965808
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48"

0 commit comments

Comments
 (0)