mirror of
https://github.com/Qortal/chrome-extension.git
synced 2025-03-28 08:15:55 +00:00
added app links in messages
This commit is contained in:
parent
b16516a450
commit
6d9f326d2f
@ -1,67 +1,108 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import DOMPurify from 'dompurify';
|
import DOMPurify from 'dompurify';
|
||||||
import './styles.css'; // Ensure this CSS file is imported
|
import './styles.css';
|
||||||
|
import { executeEvent } from '../../utils/events';
|
||||||
|
|
||||||
export const MessageDisplay = ({ htmlContent , isReply}) => {
|
const extractComponents = (url) => {
|
||||||
|
console.log('url', url);
|
||||||
|
if (!url.startsWith("qortal://")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
url = url.replace(/^(qortal\:\/\/)/, "");
|
||||||
|
if (url.includes("/")) {
|
||||||
|
let parts = url.split("/");
|
||||||
|
const service = parts[0].toUpperCase();
|
||||||
|
parts.shift();
|
||||||
|
const name = parts[0];
|
||||||
|
parts.shift();
|
||||||
|
let identifier;
|
||||||
|
const path = parts.join("/");
|
||||||
|
return { service, name, identifier, path };
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
function processText(input) {
|
||||||
|
const linkRegex = /(qortal:\/\/\S+)/g;
|
||||||
|
function processNode(node) {
|
||||||
|
if (node.nodeType === Node.TEXT_NODE) {
|
||||||
|
const parts = node.textContent.split(linkRegex);
|
||||||
|
if (parts.length > 0) {
|
||||||
|
const fragment = document.createDocumentFragment();
|
||||||
|
parts.forEach((part) => {
|
||||||
|
if (part.startsWith('qortal://')) {
|
||||||
|
const link = document.createElement('span');
|
||||||
|
link.setAttribute('data-url', part);
|
||||||
|
link.textContent = part;
|
||||||
|
link.style.color = 'var(--code-block-text-color)';
|
||||||
|
link.style.textDecoration = 'underline';
|
||||||
|
link.style.cursor = 'pointer';
|
||||||
|
fragment.appendChild(link);
|
||||||
|
} else {
|
||||||
|
fragment.appendChild(document.createTextNode(part));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
node.replaceWith(fragment);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Array.from(node.childNodes).forEach(processNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapper = document.createElement('div');
|
||||||
|
wrapper.innerHTML = input;
|
||||||
|
processNode(wrapper);
|
||||||
|
return wrapper.innerHTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MessageDisplay = ({ htmlContent, isReply }) => {
|
||||||
const linkify = (text) => {
|
const linkify = (text) => {
|
||||||
// Regular expression to find URLs starting with https://, http://, or www.
|
let textFormatted = text;
|
||||||
const urlPattern = /(\bhttps?:\/\/[^\s<]+|\bwww\.[^\s<]+)/g;
|
const urlPattern = /(\bhttps?:\/\/[^\s<]+|\bwww\.[^\s<]+)/g;
|
||||||
|
textFormatted = text.replace(urlPattern, (url) => {
|
||||||
// Replace plain text URLs with anchor tags
|
|
||||||
return text?.replace(urlPattern, (url) => {
|
|
||||||
const href = url.startsWith('http') ? url : `https://${url}`;
|
const href = url.startsWith('http') ? url : `https://${url}`;
|
||||||
return `<a href="${href}" class="auto-link">${DOMPurify.sanitize(url)}</a>`;
|
return `<a href="${DOMPurify.sanitize(href)}" class="auto-link">${DOMPurify.sanitize(url)}</a>`;
|
||||||
});
|
});
|
||||||
|
return processText(textFormatted);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Sanitize and linkify the content
|
|
||||||
const sanitizedContent = DOMPurify.sanitize(linkify(htmlContent), {
|
const sanitizedContent = DOMPurify.sanitize(linkify(htmlContent), {
|
||||||
ALLOWED_TAGS: [
|
ALLOWED_TAGS: [
|
||||||
'a', 'b', 'i', 'em', 'strong', 'p', 'br', 'div', 'span', 'img',
|
'a', 'b', 'i', 'em', 'strong', 'p', 'br', 'div', 'span', 'img',
|
||||||
'ul', 'ol', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'code', 'pre', 'table', 'thead', 'tbody', 'tr', 'th', 'td'
|
'ul', 'ol', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'code', 'pre', 'table', 'thead', 'tbody', 'tr', 'th', 'td'
|
||||||
],
|
],
|
||||||
ALLOWED_ATTR: [
|
ALLOWED_ATTR: [
|
||||||
'href', 'target', 'rel', 'class', 'src', 'alt', 'title',
|
'href', 'target', 'rel', 'class', 'src', 'alt', 'title',
|
||||||
'width', 'height', 'style', 'align', 'valign', 'colspan', 'rowspan', 'border', 'cellpadding', 'cellspacing'
|
'width', 'height', 'style', 'align', 'valign', 'colspan', 'rowspan', 'border', 'cellpadding', 'cellspacing', 'data-url'
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
// Function to handle link clicks
|
const handleClick = async (e) => {
|
||||||
const handleClick = (e) => {
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
// Ensure we are targeting an <a> element
|
const target = e.target;
|
||||||
const target = e.target.closest('a');
|
if (target.tagName === 'A') {
|
||||||
if (target) {
|
|
||||||
const href = target.getAttribute('href');
|
const href = target.getAttribute('href');
|
||||||
|
window.electronAPI.openExternal(href);
|
||||||
|
} else if (target.getAttribute('data-url')) {
|
||||||
|
const url = target.getAttribute('data-url');
|
||||||
|
const res = extractComponents(url);
|
||||||
|
if (res) {
|
||||||
|
const { service, name, identifier, path } = res;
|
||||||
|
executeEvent("addTab", { data: { service, name, identifier, path } });
|
||||||
|
executeEvent("open-dev-mode", { });
|
||||||
|
|
||||||
if (chrome && chrome.tabs) {
|
|
||||||
chrome.tabs.create({ url: href }, (tab) => {
|
|
||||||
if (chrome.runtime.lastError) {
|
|
||||||
console.error('Error opening tab:', chrome.runtime.lastError);
|
|
||||||
} else {
|
|
||||||
console.log('Tab opened successfully:', tab);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.error('chrome.tabs API is not available.');
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
console.error('No <a> tag found or href is null.');
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`tiptap ${isReply ? 'isReply' : ''}`}
|
className={`tiptap ${isReply ? 'isReply' : ''}`}
|
||||||
dangerouslySetInnerHTML={{ __html: sanitizedContent }}
|
dangerouslySetInnerHTML={{ __html: sanitizedContent }}
|
||||||
onClick={(e) => {
|
onClick={handleClick}
|
||||||
// Delegate click handling to the parent div
|
|
||||||
if (e.target.tagName === 'A') {
|
|
||||||
handleClick(e);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1281,6 +1281,46 @@ export const Group = ({
|
|||||||
initiatedGetMembers.current = false;
|
initiatedGetMembers.current = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const openDevModeFunc = () => {
|
||||||
|
if (isMobile) {
|
||||||
|
setMobileViewMode("apps");
|
||||||
|
}
|
||||||
|
if (!isMobile) {
|
||||||
|
setDesktopViewMode('apps')
|
||||||
|
|
||||||
|
}
|
||||||
|
setIsOpenSideViewDirects(false)
|
||||||
|
setIsOpenSideViewGroups(false)
|
||||||
|
setGroupSection("default");
|
||||||
|
setSelectedGroup(null);
|
||||||
|
setNewChat(false);
|
||||||
|
setSelectedDirect(null);
|
||||||
|
setSecretKey(null);
|
||||||
|
setGroupOwner(null)
|
||||||
|
lastFetchedSecretKey.current = null;
|
||||||
|
initiatedGetMembers.current = false;
|
||||||
|
setSecretKeyPublishDate(null);
|
||||||
|
setAdmins([]);
|
||||||
|
setSecretKeyDetails(null);
|
||||||
|
setAdminsWithNames([]);
|
||||||
|
setMembers([]);
|
||||||
|
setMemberCountFromSecretKeyData(null);
|
||||||
|
setTriedToFetchSecretKey(false);
|
||||||
|
setFirstSecretKeyInCreation(false);
|
||||||
|
setIsOpenSideViewDirects(false)
|
||||||
|
setIsOpenSideViewGroups(false)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
subscribeToEvent("open-dev-mode", openDevModeFunc);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
unsubscribeFromEvent("open-dev-mode", openDevModeFunc);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
const logoutEventFunc = () => {
|
const logoutEventFunc = () => {
|
||||||
resetAllStatesAndRefs();
|
resetAllStatesAndRefs();
|
||||||
clearStatesMessageQueueProvider();
|
clearStatesMessageQueueProvider();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user