Rename style file and add theme to chat

This commit is contained in:
Nicola Benaglia 2025-04-18 19:39:07 +02:00
parent 2013561db7
commit 69ff35b776
3 changed files with 741 additions and 619 deletions

View File

@ -1,28 +1,28 @@
import React, { useEffect, useMemo } from 'react'; import { useMemo } from 'react';
import DOMPurify from 'dompurify'; import DOMPurify from 'dompurify';
import './styles.css'; import './chat.css';
import { executeEvent } from '../../utils/events'; import { executeEvent } from '../../utils/events';
import { Embed } from '../Embeds/Embed'; import { Embed } from '../Embeds/Embed';
export const extractComponents = (url) => { export const extractComponents = (url) => {
if (!url || !url.startsWith("qortal://")) { if (!url || !url.startsWith('qortal://')) {
return null; return null;
} }
// Skip links starting with "qortal://use-" // Skip links starting with "qortal://use-"
if (url.startsWith("qortal://use-")) { if (url.startsWith('qortal://use-')) {
return null; return null;
} }
url = url.replace(/^(qortal\:\/\/)/, ""); url = url.replace(/^(qortal\:\/\/)/, '');
if (url.includes("/")) { if (url.includes('/')) {
let parts = url.split("/"); let parts = url.split('/');
const service = parts[0].toUpperCase(); const service = parts[0].toUpperCase();
parts.shift(); parts.shift();
const name = parts[0]; const name = parts[0];
parts.shift(); parts.shift();
let identifier; let identifier;
const path = parts.join("/"); const path = parts.join('/');
return { service, name, identifier, path }; return { service, name, identifier, path };
} }
@ -64,8 +64,7 @@ function processText(input) {
} }
const linkify = (text) => { const linkify = (text) => {
if (!text) return ""; // Return an empty string if text is null or undefined if (!text) return ''; // Return an empty string if text is null or undefined
let textFormatted = text; let textFormatted = text;
const urlPattern = /(\bhttps?:\/\/[^\s<]+|\bwww\.[^\s<]+)/g; const urlPattern = /(\bhttps?:\/\/[^\s<]+|\bwww\.[^\s<]+)/g;
textFormatted = text.replace(urlPattern, (url) => { textFormatted = text.replace(urlPattern, (url) => {
@ -75,22 +74,66 @@ const linkify = (text) => {
return processText(textFormatted); return processText(textFormatted);
}; };
export const MessageDisplay = ({ htmlContent, isReply }) => { export const MessageDisplay = ({ htmlContent, isReply }) => {
const sanitizedContent = useMemo(() => {
const sanitizedContent = useMemo(()=> {
return DOMPurify.sanitize(linkify(htmlContent), { return DOMPurify.sanitize(linkify(htmlContent), {
ALLOWED_TAGS: [ ALLOWED_TAGS: [
'a', 'b', 'i', 'em', 'strong', 'p', 'br', 'div', 'span', 'img', 'a',
'ul', 'ol', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'code', 'pre', 'table', 'thead', 'tbody', 'tr', 'th', 'td', 's', 'hr' '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',
's',
'hr',
], ],
ALLOWED_ATTR: [ ALLOWED_ATTR: [
'href', 'target', 'rel', 'class', 'src', 'alt', 'title', 'href',
'width', 'height', 'style', 'align', 'valign', 'colspan', 'rowspan', 'border', 'cellpadding', 'cellspacing', 'data-url' 'target',
'rel',
'class',
'src',
'alt',
'title',
'width',
'height',
'style',
'align',
'valign',
'colspan',
'rowspan',
'border',
'cellpadding',
'cellspacing',
'data-url',
], ],
}).replace(/<span[^>]*data-url="qortal:\/\/use-embed\/[^"]*"[^>]*>.*?<\/span>/g, ''); }).replace(
}, [htmlContent]) /<span[^>]*data-url="qortal:\/\/use-embed\/[^"]*"[^>]*>.*?<\/span>/g,
''
);
}, [htmlContent]);
const handleClick = async (e) => { const handleClick = async (e) => {
e.preventDefault(); e.preventDefault();
@ -98,7 +141,7 @@ export const MessageDisplay = ({ htmlContent, isReply }) => {
const target = e.target; const target = e.target;
if (target.tagName === 'A') { if (target.tagName === 'A') {
const href = target.getAttribute('href'); const href = target.getAttribute('href');
if(window?.electronAPI){ if (window?.electronAPI) {
window.electronAPI.openExternal(href); window.electronAPI.openExternal(href);
} else { } else {
window.open(href, '_system'); window.open(href, '_system');
@ -106,32 +149,32 @@ export const MessageDisplay = ({ htmlContent, isReply }) => {
} else if (target.getAttribute('data-url')) { } else if (target.getAttribute('data-url')) {
const url = target.getAttribute('data-url'); const url = target.getAttribute('data-url');
let copyUrl = url let copyUrl = url;
try { try {
copyUrl = copyUrl.replace(/^(qortal:\/\/)/, '') copyUrl = copyUrl.replace(/^(qortal:\/\/)/, '');
if (copyUrl.startsWith('use-')) { if (copyUrl.startsWith('use-')) {
// Handle the new 'use' format // Handle the new 'use' format
const parts = copyUrl.split('/') const parts = copyUrl.split('/');
const type = parts[0].split('-')[1] // e.g., 'group' from 'use-group' const type = parts[0].split('-')[1]; // e.g., 'group' from 'use-group'
parts.shift() parts.shift();
const action = parts.length > 0 ? parts[0].split('-')[1] : null // e.g., 'invite' from 'action-invite' const action = parts.length > 0 ? parts[0].split('-')[1] : null; // e.g., 'invite' from 'action-invite'
parts.shift() parts.shift();
const idPrefix = parts.length > 0 ? parts[0].split('-')[0] : null // e.g., 'groupid' from 'groupid-321' const idPrefix = parts.length > 0 ? parts[0].split('-')[0] : null; // e.g., 'groupid' from 'groupid-321'
const id = parts.length > 0 ? parts[0].split('-')[1] : null // e.g., '321' from 'groupid-321' const id = parts.length > 0 ? parts[0].split('-')[1] : null; // e.g., '321' from 'groupid-321'
if(action === 'join'){ if (action === 'join') {
executeEvent("globalActionJoinGroup", { groupId: id}); executeEvent('globalActionJoinGroup', { groupId: id });
return return;
}
} }
} catch (error) {
//error
} }
} catch (error) {
//error
}
const res = extractComponents(url); const res = extractComponents(url);
if (res) { if (res) {
const { service, name, identifier, path } = res; const { service, name, identifier, path } = res;
executeEvent("addTab", { data: { service, name, identifier, path } }); executeEvent('addTab', { data: { service, name, identifier, path } });
executeEvent("open-apps-mode", { }); executeEvent('open-apps-mode', {});
} }
} }
}; };
@ -141,19 +184,17 @@ export const MessageDisplay = ({ htmlContent, isReply }) => {
let embedData = null; let embedData = null;
if (embedLink) { if (embedLink) {
embedData = embedLink[0] embedData = embedLink[0];
} }
return ( return (
<> <>
{embedLink && ( {embedLink && <Embed embedLink={embedData} />}
<Embed embedLink={embedData} /> <div
)} className={`tiptap ${isReply ? 'isReply' : ''}`}
<div dangerouslySetInnerHTML={{ __html: sanitizedContent }}
className={`tiptap ${isReply ? 'isReply' : ''}`} onClick={handleClick}
dangerouslySetInnerHTML={{ __html: sanitizedContent }} />
onClick={handleClick}
/>
</> </>
); );
}; };

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
.tiptap { .tiptap {
margin-top: 0; margin-top: 0;
color: white; /* Set default font color to white */ color: ''; /* Set default font color to white */
width: 100%; width: 100%;
} }
@ -105,46 +105,45 @@
color: white; /* Ensure paragraph text color is white */ color: white; /* Ensure paragraph text color is white */
margin: 0px; margin: 0px;
} }
.tiptap p.is-editor-empty:first-child::before { .tiptap p.is-editor-empty:first-child::before {
color: #adb5bd; color: #adb5bd;
content: attr(data-placeholder); content: attr(data-placeholder);
float: left; float: left;
height: 0; height: 0;
pointer-events: none; pointer-events: none;
} }
.tiptap p:empty::before { .tiptap p:empty::before {
content: ''; content: '';
display: inline-block; display: inline-block;
} }
.tiptap a { .tiptap a {
color: cadetblue color: cadetblue;
} }
.tiptap img { .tiptap img {
display: block; display: block;
max-width: 100%; max-width: 100%;
} }
.isReply p { .isReply p {
font-size: 12px !important; font-size: 12px !important;
} }
.tiptap [data-type="mention"] { .tiptap [data-type='mention'] {
box-decoration-break: clone; box-decoration-break: clone;
color: lightblue; color: lightblue;
padding: 0.1rem 0.3rem; padding: 0.1rem 0.3rem;
} }
.unread-divider { .unread-divider {
width: 90%; width: 90%;
color: white; color: white;
border-bottom: 1px solid white; border-bottom: 1px solid white;
display: flex; display: flex;
justify-content: center; justify-content: center;
border-radius: 2px; border-radius: 2px;
} }
.mention-item { .mention-item {
@ -176,4 +175,4 @@
background-color: gray; background-color: gray;
} }
} }
} }