diff options
author | Paul Frazee <pfrazee@gmail.com> | 2022-11-18 13:59:17 -0600 |
---|---|---|
committer | Paul Frazee <pfrazee@gmail.com> | 2022-11-18 13:59:17 -0600 |
commit | 6e2b7a0b90ae8140d81d2d66c87ec9e40d9f45ec (patch) | |
tree | f36f902da70006364e839ee53d55a468c7539e21 /src | |
parent | 9d13e05dbf0bb6430060ddf556006b1721444edc (diff) | |
download | voidsky-6e2b7a0b90ae8140d81d2d66c87ec9e40d9f45ec.tar.zst |
Add support for web links
Diffstat (limited to 'src')
-rw-r--r-- | src/view/com/composer/ComposePost.tsx | 2 | ||||
-rw-r--r-- | src/view/com/util/Link.tsx | 27 | ||||
-rw-r--r-- | src/view/com/util/RichText.tsx | 27 | ||||
-rw-r--r-- | src/view/lib/strings.ts | 41 |
4 files changed, 67 insertions, 30 deletions
diff --git a/src/view/com/composer/ComposePost.tsx b/src/view/com/composer/ComposePost.tsx index b7abbed48..ab4834116 100644 --- a/src/view/com/composer/ComposePost.tsx +++ b/src/view/com/composer/ComposePost.tsx @@ -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 diff --git a/src/view/com/util/Link.tsx b/src/view/com/util/Link.tsx index 4931438b8..ff3d25cb5 100644 --- a/src/view/com/util/Link.tsx +++ b/src/view/com/util/Link.tsx @@ -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) + } +} diff --git a/src/view/com/util/RichText.tsx b/src/view/com/util/RichText.tsx index 35948455a..f865c873a 100644 --- a/src/view/com/util/RichText.tsx +++ b/src/view/com/util/RichText.tsx @@ -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++ } diff --git a/src/view/lib/strings.ts b/src/view/lib/strings.ts index 6d963b281..b12fbd398 100644 --- a/src/view/lib/strings.ts +++ b/src/view/lib/strings.ts @@ -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 } |