Add support for web links

zio/stable
Paul Frazee 2022-11-18 13:59:17 -06:00
parent 9d13e05dbf
commit 6e2b7a0b90
4 changed files with 67 additions and 30 deletions

View File

@ -108,7 +108,7 @@ export const ComposePost = observer(function ComposePost({
: undefined
const textDecorated = useMemo(() => {
const re = /(@[a-z0-9\.]*)/gi
const re = /(@[a-z0-9\.]*)|(https?:\/\/[\S]+)/gi
const segments = []
let match
let start = 0

View File

@ -1,6 +1,7 @@
import React from 'react'
import {observer} from 'mobx-react-lite'
import {
Linking,
StyleProp,
Text,
TouchableOpacity,
@ -8,6 +9,7 @@ import {
ViewStyle,
} from 'react-native'
import {useStores} from '../../../state'
import {RootStoreModel} from '../../../state'
import {LinkActionsModel} from '../../../state/models/shell-ui'
export const Link = observer(function Link({
@ -23,13 +25,10 @@ export const Link = observer(function Link({
}) {
const store = useStores()
const onPress = () => {
store.shell.closeModal() // close any active modals
store.nav.navigate(href)
handleLink(store, href, false)
}
const onLongPress = () => {
store.shell.closeModal() // close any active modals
store.nav.newTab(href, title)
// store.shell.openModal(new LinkActionsModel(href, title || href))
handleLink(store, href, true)
}
return (
<TouchableOpacity
@ -55,12 +54,10 @@ export const TextLink = observer(function Link({
}) {
const store = useStores()
const onPress = () => {
store.shell.closeModal() // close any active modals
store.nav.navigate(href)
handleLink(store, href, false)
}
const onLongPress = () => {
store.shell.closeModal() // close any active modals
store.nav.newTab(href, title)
handleLink(store, href, true)
}
return (
<Text style={style} onPress={onPress} onLongPress={onLongPress}>
@ -68,3 +65,15 @@ export const TextLink = observer(function Link({
</Text>
)
})
function handleLink(store: RootStoreModel, href: string, longPress: boolean) {
if (href.startsWith('http')) {
Linking.openURL(href)
} else if (longPress) {
store.shell.closeModal() // close any active modals
store.nav.newTab(href)
} else {
store.shell.closeModal() // close any active modals
store.nav.navigate(href)
}
}

View File

@ -32,14 +32,25 @@ export function RichText({
if (typeof segment === 'string') {
els.push(segment)
} else {
els.push(
<TextLink
key={key}
text={segment.text}
href={`/profile/${segment.entity.value}`}
style={[style, s.blue3]}
/>,
)
if (segment.entity.type === 'mention') {
els.push(
<TextLink
key={key}
text={segment.text}
href={`/profile/${segment.entity.value}`}
style={[style, s.blue3]}
/>,
)
} else if (segment.entity.type === 'link') {
els.push(
<TextLink
key={key}
text={segment.text}
href={segment.entity.value}
style={[style, s.blue3]}
/>,
)
}
}
key++
}

View File

@ -63,19 +63,36 @@ export function extractEntities(
): Entity[] | undefined {
let match
let ents: Entity[] = []
const re = /(^|\s)(@)([a-zA-Z0-9\.-]+)(\b)/dg
while ((match = re.exec(text))) {
if (knownHandles && !knownHandles.has(match[3])) {
continue // not a known handle
{
// mentions
const re = /(^|\s)(@)([a-zA-Z0-9\.-]+)(\b)/dg
while ((match = re.exec(text))) {
if (knownHandles && !knownHandles.has(match[3])) {
continue // not a known handle
}
ents.push({
type: 'mention',
value: match[3],
index: {
start: match.indices[2][0], // skip the (^|\s) but include the '@'
end: match.indices[3][1],
},
})
}
}
{
// links
const re = /(^|\s)(https?:\/\/[\S]+)(\b)/dg
while ((match = re.exec(text))) {
ents.push({
type: 'link',
value: match[2],
index: {
start: match.indices[1][0], // skip the (^|\s) but include the '@'
end: match.indices[2][1],
},
})
}
ents.push({
type: 'mention',
value: match[3],
index: {
start: match.indices[2][0], // skip the (^|\s) but include the '@'
end: match.indices[3][1],
},
})
}
return ents.length > 0 ? ents : undefined
}