mirror of
https://github.com/RetroShare/RSNewWebUI.git
synced 2026-09-12 19:50:04 +05:00
Addded quote chat message feature
This commit is contained in:
parent
e35dfebe33
commit
6202ff7077
@ -1058,10 +1058,16 @@ const ChatRoomJoinView = () => {
|
||||
|
||||
const Layout = {
|
||||
dismissMenu: () => {
|
||||
let redraw = false;
|
||||
if (ChatHubState.activeMenu) {
|
||||
ChatHubState.activeMenu = null;
|
||||
m.redraw();
|
||||
redraw = true;
|
||||
}
|
||||
if (ChatHubState.messageContextMenu && ChatHubState.messageContextMenu.show) {
|
||||
ChatHubState.messageContextMenu.show = false;
|
||||
redraw = true;
|
||||
}
|
||||
if (redraw) m.redraw();
|
||||
},
|
||||
oninit: () => {
|
||||
ChatHubState.activeTab = 'chat';
|
||||
@ -1481,7 +1487,45 @@ const Layout = {
|
||||
'Select a chat room from the left panel to view details or join a conversation.'
|
||||
),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
ChatHubState.messageContextMenu.show && m('.chat-msg-context-menu', {
|
||||
style: `position: fixed; top: ${ChatHubState.messageContextMenu.y}px; left: ${ChatHubState.messageContextMenu.x}px; background: #ffffff; border: 1px solid #cbd5e1; border-radius: 0.5rem; box-shadow: 0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -2px rgba(0,0,0,0.05); padding: 0.35rem 0; z-index: 3000; min-width: 160px;`,
|
||||
onclick: (e) => e.stopPropagation(),
|
||||
}, [
|
||||
m('.context-menu-item', {
|
||||
style: 'padding: 0.5rem 1rem; font-size: 0.85rem; font-weight: 600; color: #1e293b; display: flex; align-items: center; gap: 0.6rem; cursor: pointer; transition: background 0.15s ease;',
|
||||
onmouseenter: (e) => (e.currentTarget.style.background = '#f1f5f9'),
|
||||
onmouseleave: (e) => (e.currentTarget.style.background = 'transparent'),
|
||||
onclick: () => {
|
||||
const { username, messageText } = ChatHubState.messageContextMenu;
|
||||
const quoteHeader = `> [${username}]: ${messageText}\n`;
|
||||
const textarea = document.querySelector('.chat-hub-input-area textarea') || document.querySelector('#msginput');
|
||||
if (textarea) {
|
||||
textarea.value = (textarea.value ? textarea.value.trim() + '\n' : '') + quoteHeader;
|
||||
textarea.focus();
|
||||
}
|
||||
ChatHubState.messageContextMenu.show = false;
|
||||
m.redraw();
|
||||
},
|
||||
}, [
|
||||
m('i.fas.fa-quote-right', { style: 'color: #3b82f6;' }),
|
||||
'Quote Message'
|
||||
]),
|
||||
m('.context-menu-item', {
|
||||
style: 'padding: 0.5rem 1rem; font-size: 0.85rem; font-weight: 600; color: #1e293b; display: flex; align-items: center; gap: 0.6rem; cursor: pointer; transition: background 0.15s ease;',
|
||||
onmouseenter: (e) => (e.currentTarget.style.background = '#f1f5f9'),
|
||||
onmouseleave: (e) => (e.currentTarget.style.background = 'transparent'),
|
||||
onclick: () => {
|
||||
const { messageText } = ChatHubState.messageContextMenu;
|
||||
navigator.clipboard.writeText(messageText);
|
||||
ChatHubState.messageContextMenu.show = false;
|
||||
m.redraw();
|
||||
},
|
||||
}, [
|
||||
m('i.far.fa-copy', { style: 'color: #64748b;' }),
|
||||
'Copy Text'
|
||||
]),
|
||||
])
|
||||
]);
|
||||
},
|
||||
};
|
||||
|
||||
@ -149,7 +149,7 @@ function renderChatMessage(rawText) {
|
||||
.replaceAll('<br>', '\n')
|
||||
.replace(new RegExp('<style[^<]*</style>|<[^>]*>', 'gm'), '');
|
||||
if (cleanText) {
|
||||
parts.push(renderTextWithEmoji(cleanText));
|
||||
parts.push(renderFormattedMessageText(cleanText));
|
||||
}
|
||||
}
|
||||
|
||||
@ -182,11 +182,61 @@ function renderChatMessage(rawText) {
|
||||
|
||||
// 3. Normal text message
|
||||
const cleanText = rawText
|
||||
.replace(/<blockquote[^>]*>/gi, '\n> ')
|
||||
.replace(/<\/blockquote>/gi, '\n')
|
||||
.replaceAll('<br/>', '\n')
|
||||
.replaceAll('<br>', '\n')
|
||||
.replace(new RegExp('<style[^<]*</style>|<[^>]*>', 'gm'), '');
|
||||
|
||||
return renderTextWithEmoji(cleanText);
|
||||
return renderFormattedMessageText(cleanText);
|
||||
}
|
||||
|
||||
function renderFormattedMessageText(text) {
|
||||
if (!text) return '';
|
||||
const lines = text.split('\n');
|
||||
const elements = [];
|
||||
let currentQuoteLines = [];
|
||||
|
||||
const flushQuote = () => {
|
||||
if (currentQuoteLines.length > 0) {
|
||||
const quoteText = currentQuoteLines.join('\n');
|
||||
elements.push(
|
||||
m('blockquote.chat-quote-block', {
|
||||
style: {
|
||||
borderLeft: '3px solid #3b82f6',
|
||||
backgroundColor: '#f8fafc',
|
||||
color: '#475569',
|
||||
padding: '0.35rem 0.65rem',
|
||||
margin: '0.35rem 0',
|
||||
borderRadius: '0 0.375rem 0.375rem 0',
|
||||
fontSize: '0.9em',
|
||||
fontStyle: 'italic',
|
||||
whiteSpace: 'pre-wrap',
|
||||
wordBreak: 'break-word',
|
||||
}
|
||||
}, renderTextWithEmoji(quoteText))
|
||||
);
|
||||
currentQuoteLines = [];
|
||||
}
|
||||
};
|
||||
|
||||
lines.forEach((line, idx) => {
|
||||
if (line.trim().startsWith('>')) {
|
||||
const lineContent = line.trim().replace(/^>\s?/, '');
|
||||
currentQuoteLines.push(lineContent);
|
||||
} else {
|
||||
flushQuote();
|
||||
if (line) {
|
||||
elements.push(renderTextWithEmoji(line));
|
||||
}
|
||||
if (idx < lines.length - 1) {
|
||||
elements.push(m('br'));
|
||||
}
|
||||
}
|
||||
});
|
||||
flushQuote();
|
||||
|
||||
return elements.length > 0 ? elements : renderTextWithEmoji(text);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -381,13 +431,34 @@ const Message = () => {
|
||||
const chatType = ChatLobbyModel.currentLobby && ChatLobbyModel.currentLobby.chatType;
|
||||
const isRoom = chatType === 3;
|
||||
|
||||
const handleContextMenu = (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const sel = window.getSelection() ? window.getSelection().toString() : '';
|
||||
const targetText = sel && sel.trim() ? sel : rawText;
|
||||
|
||||
ChatHubState.messageContextMenu = {
|
||||
show: true,
|
||||
x: e.clientX,
|
||||
y: e.clientY,
|
||||
messageText: targetText,
|
||||
username: username,
|
||||
};
|
||||
m.redraw();
|
||||
};
|
||||
|
||||
if (isRoom) {
|
||||
const nickColor = getNicknameColor(gxsId, username);
|
||||
return m(
|
||||
'.message.compact',
|
||||
m('span.datetime', datetime),
|
||||
m('span.username', { style: { color: nickColor } }, username + ':'),
|
||||
m('span.messagetext', renderChatMessage(rawText))
|
||||
{
|
||||
oncontextmenu: handleContextMenu,
|
||||
},
|
||||
[
|
||||
m('span.datetime', datetime),
|
||||
m('span.username', { style: { color: nickColor } }, username + ':'),
|
||||
m('span.messagetext', renderChatMessage(rawText)),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
@ -808,6 +879,13 @@ const ChatHubState = {
|
||||
historySearchQuery: '',
|
||||
fullHistoryMessages: [],
|
||||
isHistoryLoading: false,
|
||||
messageContextMenu: {
|
||||
show: false,
|
||||
x: 0,
|
||||
y: 0,
|
||||
messageText: '',
|
||||
username: '',
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
const m = require('mithril');
|
||||
const rs = require('rswebui');
|
||||
const peopleState = require('people/people_state');
|
||||
const chatState = require('chat/chat_state');
|
||||
|
||||
const HistoryBrowserModal = () => {
|
||||
return {
|
||||
oninit: (vnode) => {
|
||||
const chatState = require('chat/chat_state');
|
||||
const isRoom = vnode.attrs && vnode.attrs.isRoom;
|
||||
if (isRoom) {
|
||||
chatState.ChatHubState.historySearchQuery = '';
|
||||
@ -19,6 +19,7 @@ const HistoryBrowserModal = () => {
|
||||
}
|
||||
},
|
||||
view: (vnode) => {
|
||||
const chatState = require('chat/chat_state');
|
||||
const isRoom = vnode.attrs && vnode.attrs.isRoom;
|
||||
const stateObj = isRoom ? chatState.ChatHubState : peopleState.State;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user