added clickable link to message

This commit is contained in:
Roland Osborne 2025-01-08 13:42:07 -08:00
parent 6f1af1ccaf
commit 29d55c3fcb
5 changed files with 1693 additions and 1304 deletions

View File

@ -611,6 +611,7 @@
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
USE_HERMES = true;
};
name = Debug;

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,7 @@
},
"dependencies": {
"@bam.tech/react-native-image-resizer": "^3.0.11",
"@braintree/sanitize-url": "^6.0.4",
"@openspacelabs/react-native-zoomable-view": "^2.3.1",
"@react-native-clipboard/clipboard": "^1.14.2",
"@react-native-community/blur": "^4.4.0",

View File

@ -1,6 +1,6 @@
import { useRef, useEffect, useState, useCallback } from 'react';
import { avatar } from '../constants/Icons'
import { Pressable, ScrollView, View, Image, Modal } from 'react-native';
import { Pressable, Linking, ScrollView, View, Image, Modal } from 'react-native';
import {Icon, Text, TextInput, IconButton, Button, Surface, Divider} from 'react-native-paper';
import { Topic, Card, Profile } from 'databag-client-sdk';
import { ImageAsset } from './imageAsset/ImageAsset';
@ -13,6 +13,7 @@ import { MediaAsset } from '../conversation/Conversatin';
import { Confirm } from '../confirm/Confirm';
import { Shimmer } from './shimmer/Shimmer';
import {BlurView} from '@react-native-community/blur';
import { sanitizeUrl } from '@braintree/sanitize-url';
export function Message({ topic, card, profile, host, select, selected }: { topic: Topic, card: Card | null, profile: Profile | null, host: boolean, select: (id: null | string)=>void, selected: string }) {
const { state, actions } = useMessage();
@ -22,7 +23,6 @@ export function Message({ topic, card, profile, host, select, selected }: { topi
const textStyle = textColor && textSize ? { fontSize: textSize, color: textColor } : textColor ? { color: textColor } : textSize ? { fontSize: textSize } : {}
const logoUrl = profile ? profile.imageUrl : card ? card.imageUrl : avatar;
const timestamp = actions.getTimestamp(created);
const [message, setMessage] = useState('');
const [editing, setEditing] = useState(false);
const [editText, setEditText] = useState('');
const [saving, setSaving] = useState(false);
@ -33,6 +33,7 @@ export function Message({ topic, card, profile, host, select, selected }: { topi
const [reporting, setReporting] = useState(false);
const loadedCount = useRef(0);
const [showAsset, setShowAsset] = useState(false);
const [message, setMessage] = useState([]);
useEffect(() => {
setTimeout(() => setShowAsset(true), 2000);
@ -42,6 +43,35 @@ export function Message({ topic, card, profile, host, select, selected }: { topi
setEditText(text);
}, [text]);
useEffect(() => {
const urlPattern = new RegExp('(https?:\\/\\/)?(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.[a-z]{2,4}\\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*)');
const hostPattern = new RegExp('^https?:\\/\\/', 'i');
let plain = '';
let clickable = [];
const parsed = !text ? '' : text.split(' ');
if (parsed?.length > 0) {
const words = parsed as string[];
words.forEach((word, index) => {
if (!!urlPattern.test(word)) {
clickable.push(<Text key={index}>{ plain }</Text>);
plain = '';
const url = !!hostPattern.test(word) ? word : `https://${word}`;
clickable.push(<Text key={'link-' + index} onPress={() => Linking.openURL(sanitizeUrl(url))} style={{ fontStyle: 'italic' }}>{ sanitizeUrl(word) + ' ' }</Text>);
}
else {
plain += `${word} `;
}
})
}
if (plain) {
clickable.push(<Text key={parsed.length}>{ plain }</Text>);
}
setMessage(clickable)
}, [text, locked]);
const loaded = () => {
loadedCount.current += 1;
if (loadedCount.current >= assets.length) {
@ -198,7 +228,7 @@ export function Message({ topic, card, profile, host, select, selected }: { topi
</Pressable>
<View style={styles.padding}>
{ !locked && status === 'confirmed' && text && (
<Text style={{ ...styles.text, ...textStyle }}>{ text }</Text>
<Text style={{ ...styles.text, ...textStyle }}>{ message }</Text>
)}
{ !locked && status !== 'confirmed' && (
<View>

View File

@ -1030,20 +1030,7 @@
"@babel/parser" "^7.25.9"
"@babel/types" "^7.25.9"
"@babel/traverse--for-generate-function-map@npm:@babel/traverse@^7.25.3":
version "7.26.4"
resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.4.tgz"
integrity sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==
dependencies:
"@babel/code-frame" "^7.26.2"
"@babel/generator" "^7.26.3"
"@babel/parser" "^7.26.3"
"@babel/template" "^7.25.9"
"@babel/types" "^7.26.3"
debug "^4.3.1"
globals "^11.1.0"
"@babel/traverse@^7.20.0", "@babel/traverse@^7.25.3", "@babel/traverse@^7.25.9":
"@babel/traverse--for-generate-function-map@npm:@babel/traverse@^7.25.3", "@babel/traverse@^7.20.0", "@babel/traverse@^7.25.3", "@babel/traverse@^7.25.9":
version "7.26.4"
resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.4.tgz"
integrity sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==
@ -1074,6 +1061,11 @@
resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
"@braintree/sanitize-url@^6.0.4":
version "6.0.4"
resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz#923ca57e173c6b232bbbb07347b1be982f03e783"
integrity sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==
"@callstack/react-theme-provider@^3.0.9":
version "3.0.9"
resolved "https://registry.npmjs.org/@callstack/react-theme-provider/-/react-theme-provider-3.0.9.tgz"