diff --git a/app/mobile/ios/Databag.xcodeproj/project.pbxproj b/app/mobile/ios/Databag.xcodeproj/project.pbxproj index 5761ce0e..c36d2958 100644 --- a/app/mobile/ios/Databag.xcodeproj/project.pbxproj +++ b/app/mobile/ios/Databag.xcodeproj/project.pbxproj @@ -13,7 +13,6 @@ 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 46D8108CBA031189090AFC14 /* Pods_Databag_DatabagTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1181227D40684F18A9414840 /* Pods_Databag_DatabagTests.framework */; }; 7B13A774299E21170048D0DD /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 7B13A773299E21170048D0DD /* GoogleService-Info.plist */; }; - 7B6135A329B439B80094A6E7 /* login.png in Resources */ = {isa = PBXBuildFile; fileRef = 7B6135A229B439B80094A6E7 /* login.png */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; A0B1EC4533FCFC5940B5FD7F /* Pods_Databag.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9462C028F47F083241BB7941 /* Pods_Databag.framework */; }; /* End PBXBuildFile section */ @@ -43,7 +42,6 @@ 5709B34CF0A7D63546082F79 /* Pods-Databag.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Databag.release.xcconfig"; path = "Target Support Files/Pods-Databag/Pods-Databag.release.xcconfig"; sourceTree = ""; }; 5B7EB9410499542E8C5724F5 /* Pods-Databag-DatabagTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Databag-DatabagTests.debug.xcconfig"; path = "Target Support Files/Pods-Databag-DatabagTests/Pods-Databag-DatabagTests.debug.xcconfig"; sourceTree = ""; }; 7B13A773299E21170048D0DD /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; - 7B6135A229B439B80094A6E7 /* login.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = login.png; sourceTree = ""; }; 7B6135A429B68A7B0094A6E7 /* Databag.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = Databag.entitlements; path = Databag/Databag.entitlements; sourceTree = ""; }; 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = Databag/LaunchScreen.storyboard; sourceTree = ""; }; 89C6BE57DB24E9ADA2F236DE /* Pods-Databag-DatabagTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Databag-DatabagTests.release.xcconfig"; path = "Target Support Files/Pods-Databag-DatabagTests/Pods-Databag-DatabagTests.release.xcconfig"; sourceTree = ""; }; @@ -97,7 +95,6 @@ 13B07FB51A68108700A75B9A /* Images.xcassets */, 13B07FB61A68108700A75B9A /* Info.plist */, 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */, - 7B6135A229B439B80094A6E7 /* login.png */, 13B07FB71A68108700A75B9A /* main.m */, ); name = Databag; @@ -253,7 +250,6 @@ buildActionMask = 2147483647; files = ( 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */, - 7B6135A329B439B80094A6E7 /* login.png in Resources */, 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, 7B13A774299E21170048D0DD /* GoogleService-Info.plist in Resources */, ); @@ -575,7 +571,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "c++14"; + CLANG_CXX_LANGUAGE_STANDARD = "c++17"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; @@ -647,7 +643,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "c++14"; + CLANG_CXX_LANGUAGE_STANDARD = "c++17"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; diff --git a/app/mobile/src/session/conversation/topicItem/TopicItem.jsx b/app/mobile/src/session/conversation/topicItem/TopicItem.jsx index eed90eb5..d590eaf7 100644 --- a/app/mobile/src/session/conversation/topicItem/TopicItem.jsx +++ b/app/mobile/src/session/conversation/topicItem/TopicItem.jsx @@ -131,8 +131,8 @@ export function TopicItem({ item, focused, focus, hosting, remove, update, block return ( - - + + { state.logo !== 'avatar' && state.logo && ( )} @@ -141,7 +141,7 @@ export function TopicItem({ item, focused, focus, hosting, remove, update, block )} { state.name } { state.timestamp } - + { state.status === 'confirmed' && ( <> { state.transform === 'complete' && state.assets && ( @@ -175,7 +175,7 @@ export function TopicItem({ item, focused, focus, hosting, remove, update, block )} - + { focused && ( { state.editable && ( diff --git a/app/mobile/src/session/conversation/topicItem/useTopicItem.hook.js b/app/mobile/src/session/conversation/topicItem/useTopicItem.hook.js index f2330a4c..7be7e10a 100644 --- a/app/mobile/src/session/conversation/topicItem/useTopicItem.hook.js +++ b/app/mobile/src/session/conversation/topicItem/useTopicItem.hook.js @@ -1,13 +1,15 @@ import { useState, useEffect, useContext } from 'react'; +import { Linking } from 'react-native'; import { ConversationContext } from 'context/ConversationContext'; import { CardContext } from 'context/CardContext'; import { ProfileContext } from 'context/ProfileContext'; import { AccountContext } from 'context/AccountContext'; import moment from 'moment'; -import { useWindowDimensions } from 'react-native'; +import { useWindowDimensions, Text } from 'react-native'; import Colors from 'constants/Colors'; import { getCardByGuid } from 'context/cardUtil'; import { decryptTopicSubject } from 'context/sealUtil'; +import * as DOMPurify from 'dompurify'; export function useTopicItem(item, hosting, remove, contentKey) { @@ -95,7 +97,7 @@ export function useTopicItem(item, hosting, remove, contentKey) { try { sealed = false; parsed = JSON.parse(data); - message = parsed.text; + message = clickableText(parsed.text); assets = parsed.assets; if (parsed.textSize === 'small') { fontSize = 10; @@ -138,7 +140,7 @@ export function useTopicItem(item, hosting, remove, contentKey) { if (unsealed) { sealed = false; parsed = unsealed.message; - message = parsed?.text; + message = clickableText(parsed?.text); if (parsed?.textSize === 'small') { fontSize = 10; } @@ -194,6 +196,31 @@ export function useTopicItem(item, hosting, remove, contentKey) { } }; + const clickableText = (text) => { + var pattern = new RegExp('^(https?:\\/\\/)?'+ // protocol + '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name + '((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address + '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path + '(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string + '(\\#[-a-z\\d_]*)?$','i'); // fragment locator + + let clickable = []; + let group = ''; + const words = text == null ? '' : text.split(' '); + words.forEach((word, index) => { + if (!!pattern.test(word)) { + clickable.push({ group }); + group = ''; + clickable.push( Linking.openURL(word)} style={{ fontStyle: 'italic' }}>{ word + ' ' }); + } + else { + group += `${word} `; + } + }) + clickable.push({ group }); + return { clickable }; + }; + const actions = { showCarousel: (index) => { updateState({ carousel: true, carouselIndex: index });