Save entities for message edit
Support underline entity Support markdown in message edit Support markdown for messageEntityTextUrl
This commit is contained in:
parent
a885492a09
commit
3cc7d874bf
@ -565,7 +565,7 @@ export class ChatInput {
|
|||||||
//let str = this.serializeNodes(Array.from(this.messageInput.childNodes));
|
//let str = this.serializeNodes(Array.from(this.messageInput.childNodes));
|
||||||
let str = getRichValue(this.messageInput);
|
let str = getRichValue(this.messageInput);
|
||||||
|
|
||||||
//console.log('childnode str after:', str/* , getRichValue(this.messageInput) */);
|
console.log('childnode str after:', str/* , getRichValue(this.messageInput) */);
|
||||||
|
|
||||||
//return;
|
//return;
|
||||||
|
|
||||||
@ -611,7 +611,7 @@ export class ChatInput {
|
|||||||
public initMessageEditing(mid: number) {
|
public initMessageEditing(mid: number) {
|
||||||
const message = appMessagesManager.getMessage(mid);
|
const message = appMessagesManager.getMessage(mid);
|
||||||
|
|
||||||
let input = message.message;
|
let input = RichTextProcessor.wrapDraftText(message.message, {entities: message.totalEntities});
|
||||||
const f = () => {
|
const f = () => {
|
||||||
this.setTopInfo('edit', f, 'Editing', message.message, input, message);
|
this.setTopInfo('edit', f, 'Editing', message.message, input, message);
|
||||||
this.editMsgID = mid;
|
this.editMsgID = mid;
|
||||||
@ -690,7 +690,7 @@ export class ChatInput {
|
|||||||
} */
|
} */
|
||||||
|
|
||||||
if(input !== undefined) {
|
if(input !== undefined) {
|
||||||
this.messageInput.innerHTML = input ? RichTextProcessor.wrapRichText(input, {noLinks: true}) : '';
|
this.messageInput.innerHTML = input || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -130,7 +130,7 @@ export default class PopupCreatePoll extends PopupElement {
|
|||||||
|
|
||||||
private getFilledAnswers() {
|
private getFilledAnswers() {
|
||||||
const answers = Array.from(this.questions.children).map((el, idx) => {
|
const answers = Array.from(this.questions.children).map((el, idx) => {
|
||||||
const input = el.querySelector('.input-field-input');
|
const input = el.querySelector('.input-field-input') as HTMLElement;
|
||||||
return getRichValue(input);
|
return getRichValue(input);
|
||||||
}).filter(v => !!v.trim());
|
}).filter(v => !!v.trim());
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { MOUNT_CLASS_TO } from "../lib/mtproto/mtproto_config";
|
||||||
|
|
||||||
/* export function isInDOM(element: Element, parentNode?: HTMLElement): boolean {
|
/* export function isInDOM(element: Element, parentNode?: HTMLElement): boolean {
|
||||||
if(!element) {
|
if(!element) {
|
||||||
return false;
|
return false;
|
||||||
@ -45,24 +47,6 @@ export function cancelEvent(event: Event) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getRichValue(field: any) {
|
|
||||||
if(!field) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
var lines: string[] = [];
|
|
||||||
var line: string[] = [];
|
|
||||||
|
|
||||||
getRichElementValue(field, lines, line);
|
|
||||||
if (line.length) {
|
|
||||||
lines.push(line.join(''));
|
|
||||||
}
|
|
||||||
|
|
||||||
var value = lines.join('\n');
|
|
||||||
value = value.replace(/\u00A0/g, ' ');
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function placeCaretAtEnd(el: HTMLElement) {
|
export function placeCaretAtEnd(el: HTMLElement) {
|
||||||
el.focus();
|
el.focus();
|
||||||
if(typeof window.getSelection != "undefined" && typeof document.createRange != "undefined") {
|
if(typeof window.getSelection != "undefined" && typeof document.createRange != "undefined") {
|
||||||
@ -82,28 +66,84 @@ export function placeCaretAtEnd(el: HTMLElement) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getRichElementValue(node: any, lines: string[], line: string[], selNode?: Node, selOffset?: number) {
|
export function getRichValue(field: HTMLElement) {
|
||||||
|
if(!field) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const lines: string[] = [];
|
||||||
|
const line: string[] = [];
|
||||||
|
|
||||||
|
getRichElementValue(field, lines, line);
|
||||||
|
if(line.length) {
|
||||||
|
lines.push(line.join(''));
|
||||||
|
}
|
||||||
|
|
||||||
|
let value = lines.join('\n');
|
||||||
|
value = value.replace(/\u00A0/g, ' ');
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.getRichValue = getRichValue);
|
||||||
|
|
||||||
|
const markdownTags = [{
|
||||||
|
tagName: 'STRONG',
|
||||||
|
markdown: '**'
|
||||||
|
}, {
|
||||||
|
tagName: 'EM',
|
||||||
|
markdown: '__'
|
||||||
|
}, {
|
||||||
|
tagName: 'CODE',
|
||||||
|
markdown: '`'
|
||||||
|
}, {
|
||||||
|
tagName: 'PRE',
|
||||||
|
markdown: '``'
|
||||||
|
}, {
|
||||||
|
tagName: 'DEL',
|
||||||
|
markdown: '~~'
|
||||||
|
}, {
|
||||||
|
tagName: 'A',
|
||||||
|
markdown: (node: HTMLElement) => `[${(node.parentElement as HTMLAnchorElement).href}](${node.nodeValue})`
|
||||||
|
}];
|
||||||
|
export function getRichElementValue(node: HTMLElement, lines: string[], line: string[], selNode?: Node, selOffset?: number) {
|
||||||
if(node.nodeType == 3) { // TEXT
|
if(node.nodeType == 3) { // TEXT
|
||||||
if(selNode === node) {
|
if(selNode === node) {
|
||||||
var value = node.nodeValue
|
const value = node.nodeValue;
|
||||||
line.push(value.substr(0, selOffset) + '\x01' + value.substr(selOffset))
|
line.push(value.substr(0, selOffset) + '\x01' + value.substr(selOffset));
|
||||||
} else {
|
} else {
|
||||||
line.push(node.nodeValue)
|
let markdown: string;
|
||||||
|
if(node.parentNode) {
|
||||||
|
const tagName = node.parentElement.tagName;
|
||||||
|
const markdownTag = markdownTags.find(m => m.tagName == tagName);
|
||||||
|
if(markdownTag) {
|
||||||
|
if(typeof(markdownTag.markdown) === 'function') {
|
||||||
|
line.push(markdownTag.markdown(node));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
markdown = markdownTag.markdown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
line.push(markdown && node.nodeValue.trim() ? markdown + node.nodeValue + markdown : node.nodeValue);
|
||||||
}
|
}
|
||||||
return
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (node.nodeType != 1) { // NON-ELEMENT
|
|
||||||
return
|
if(node.nodeType != 1) { // NON-ELEMENT
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
var isSelected = (selNode === node)
|
|
||||||
var isBlock = node.tagName == 'DIV' || node.tagName == 'P'
|
const isSelected = (selNode === node);
|
||||||
var curChild
|
const isBlock = node.tagName == 'DIV' || node.tagName == 'P';
|
||||||
if(isBlock && line.length || node.tagName == 'BR') {
|
if(isBlock && line.length || node.tagName == 'BR') {
|
||||||
lines.push(line.join(''))
|
lines.push(line.join(''));
|
||||||
line.splice(0, line.length)
|
line.splice(0, line.length);
|
||||||
} else if(node.tagName == 'IMG') {
|
} else if(node.tagName == 'IMG') {
|
||||||
if(node.alt) {
|
if((node as HTMLImageElement).alt) {
|
||||||
line.push(node.alt);
|
line.push((node as HTMLImageElement).alt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,10 +151,10 @@ export function getRichElementValue(node: any, lines: string[], line: string[],
|
|||||||
line.push('\x01');
|
line.push('\x01');
|
||||||
}
|
}
|
||||||
|
|
||||||
var curChild = node.firstChild;
|
let curChild = node.firstChild as HTMLElement;
|
||||||
while(curChild) {
|
while(curChild) {
|
||||||
getRichElementValue(curChild, lines, line, selNode, selOffset);
|
getRichElementValue(curChild, lines, line, selNode, selOffset);
|
||||||
curChild = curChild.nextSibling;
|
curChild = curChild.nextSibling as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isSelected && selOffset) {
|
if(isSelected && selOffset) {
|
||||||
|
@ -65,8 +65,8 @@ const usernameRegExp = '[a-zA-Z\\d_]{5,32}';
|
|||||||
const botCommandRegExp = '\\/([a-zA-Z\\d_]{1,32})(?:@(' + usernameRegExp + '))?(\\b|$)';
|
const botCommandRegExp = '\\/([a-zA-Z\\d_]{1,32})(?:@(' + usernameRegExp + '))?(\\b|$)';
|
||||||
const fullRegExp = new RegExp('(^| )(@)(' + usernameRegExp + ')|(' + urlRegExp + ')|(\\n)|(' + emojiRegExp + ')|(^|[\\s\\(\\]])(#[' + alphaNumericRegExp + ']{2,64})|(^|\\s)' + botCommandRegExp, 'i')
|
const fullRegExp = new RegExp('(^| )(@)(' + usernameRegExp + ')|(' + urlRegExp + ')|(\\n)|(' + emojiRegExp + ')|(^|[\\s\\(\\]])(#[' + alphaNumericRegExp + ']{2,64})|(^|\\s)' + botCommandRegExp, 'i')
|
||||||
const emailRegExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
const emailRegExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||||
const markdownTestRegExp = /[`_*@]/;
|
//const markdownTestRegExp = /[`_*@~]/;
|
||||||
const markdownRegExp = /(^|\s|\n)(````?)([\s\S]+?)(````?)([\s\n\.,:?!;]|$)|(^|\s)(`|\*\*|__)([^\n]+?)\7([\s\.,:?!;]|$)|@(\d+)\s*\((.+?)\)/m;
|
const markdownRegExp = /(^|\s|\n)(````?)([\s\S]+?)(````?)([\s\n\.,:?!;]|$)|(^|\s)(`|~~|\*\*|__)([^\n]+?)\7([\s\.,:?!;]|$)|@(\d+)\s*\((.+?)\)|(\[(.+?)\]\((.+?)\))/m;
|
||||||
const siteHashtags: {[siteName: string]: string} = {
|
const siteHashtags: {[siteName: string]: string} = {
|
||||||
Telegram: 'tg://search_hashtag?hashtag={1}',
|
Telegram: 'tg://search_hashtag?hashtag={1}',
|
||||||
Twitter: 'https://twitter.com/hashtag/{1}',
|
Twitter: 'https://twitter.com/hashtag/{1}',
|
||||||
@ -82,8 +82,10 @@ const siteMentions: {[siteName: string]: string} = {
|
|||||||
};
|
};
|
||||||
const markdownEntities = {
|
const markdownEntities = {
|
||||||
'`': 'messageEntityCode',
|
'`': 'messageEntityCode',
|
||||||
|
'``': 'messageEntityPre',
|
||||||
'**': 'messageEntityBold',
|
'**': 'messageEntityBold',
|
||||||
'__': 'messageEntityItalic'
|
'__': 'messageEntityItalic',
|
||||||
|
'~~': 'messageEntityStrike'
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace RichTextProcessor {
|
namespace RichTextProcessor {
|
||||||
@ -212,71 +214,89 @@ namespace RichTextProcessor {
|
|||||||
})
|
})
|
||||||
} */
|
} */
|
||||||
|
|
||||||
export function parseMarkdown(text: string, entities: MessageEntity[], noTrim?: any) {
|
export function parseMarkdown(text: string, entities: MessageEntity[], noTrim?: any): string {
|
||||||
if(!markdownTestRegExp.test(text)) {
|
/* if(!markdownTestRegExp.test(text)) {
|
||||||
return noTrim ? text : text.trim();
|
return noTrim ? text : text.trim();
|
||||||
}
|
} */
|
||||||
|
|
||||||
var raw = text;
|
var raw = text;
|
||||||
var match;
|
var match;
|
||||||
var newText: any = [];
|
var newText: any = [];
|
||||||
var rawOffset = 0;
|
var rawOffset = 0;
|
||||||
var matchIndex;
|
var matchIndex;
|
||||||
while (match = raw.match(markdownRegExp)) {
|
while(match = raw.match(markdownRegExp)) {
|
||||||
matchIndex = rawOffset + match.index
|
matchIndex = rawOffset + match.index;
|
||||||
newText.push(raw.substr(0, match.index))
|
newText.push(raw.substr(0, match.index));
|
||||||
var text = (match[3] || match[8] || match[11])
|
var text = (match[3] || match[8] || match[11] || match[14]);
|
||||||
rawOffset -= text.length
|
rawOffset -= text.length;
|
||||||
text = text.replace(/^\s+|\s+$/g, '')
|
text = text.replace(/^\s+|\s+$/g, '');
|
||||||
rawOffset += text.length
|
rawOffset += text.length;
|
||||||
if (text.match(/^`*$/)) {
|
|
||||||
newText.push(match[0])
|
if(text.match(/^`*$/)) {
|
||||||
}
|
newText.push(match[0]);
|
||||||
else if (match[3]) { // pre
|
} else if(match[3]) { // pre
|
||||||
if (match[5] == '\n') {
|
if(match[5] == '\n') {
|
||||||
match[5] = ''
|
match[5] = '';
|
||||||
rawOffset -= 1
|
rawOffset -= 1;
|
||||||
}
|
}
|
||||||
newText.push(match[1] + text + match[5])
|
|
||||||
|
newText.push(match[1] + text + match[5]);
|
||||||
entities.push({
|
entities.push({
|
||||||
_: 'messageEntityPre',
|
_: 'messageEntityPre',
|
||||||
language: '',
|
language: '',
|
||||||
offset: matchIndex + match[1].length,
|
offset: matchIndex + match[1].length,
|
||||||
length: text.length
|
length: text.length
|
||||||
})
|
});
|
||||||
rawOffset -= match[2].length + match[4].length
|
|
||||||
} else if (match[7]) { // code|italic|bold
|
rawOffset -= match[2].length + match[4].length;
|
||||||
newText.push(match[6] + text + match[9])
|
} else if(match[7]) { // code|italic|bold
|
||||||
|
newText.push(match[6] + text + match[9]);
|
||||||
entities.push({
|
entities.push({
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
_: markdownEntities[match[7]],
|
_: markdownEntities[match[7]],
|
||||||
offset: matchIndex + match[6].length,
|
offset: matchIndex + match[6].length,
|
||||||
length: text.length
|
length: text.length
|
||||||
})
|
});
|
||||||
rawOffset -= match[7].length * 2
|
|
||||||
} else if (match[11]) { // custom mention
|
rawOffset -= match[7].length * 2;
|
||||||
|
} else if(match[11]) { // custom mention
|
||||||
newText.push(text)
|
newText.push(text)
|
||||||
entities.push({
|
entities.push({
|
||||||
_: 'messageEntityMentionName',
|
_: 'messageEntityMentionName',
|
||||||
user_id: +match[10],
|
user_id: +match[10],
|
||||||
offset: matchIndex,
|
offset: matchIndex,
|
||||||
length: text.length
|
length: text.length
|
||||||
})
|
});
|
||||||
rawOffset -= match[0].length - text.length
|
|
||||||
|
rawOffset -= match[0].length - text.length;
|
||||||
|
} else if(match[12]) { // text url
|
||||||
|
newText.push(text);
|
||||||
|
entities.push({
|
||||||
|
_: 'messageEntityTextUrl',
|
||||||
|
url: match[13],
|
||||||
|
offset: matchIndex,
|
||||||
|
length: text.length
|
||||||
|
});
|
||||||
|
|
||||||
|
rawOffset -= match[12].length - text.length;
|
||||||
}
|
}
|
||||||
raw = raw.substr(match.index + match[0].length)
|
|
||||||
rawOffset += match.index + match[0].length
|
raw = raw.substr(match.index + match[0].length);
|
||||||
|
rawOffset += match.index + match[0].length;
|
||||||
}
|
}
|
||||||
newText.push(raw)
|
|
||||||
newText = newText.join('')
|
newText.push(raw);
|
||||||
if (!newText.replace(/\s+/g, '').length) {
|
newText = newText.join('');
|
||||||
newText = text
|
if(!newText.replace(/\s+/g, '').length) {
|
||||||
entities.splice(0, entities.length)
|
newText = text;
|
||||||
|
entities.splice(0, entities.length);
|
||||||
}
|
}
|
||||||
if (!entities.length && !noTrim) {
|
|
||||||
newText = newText.trim()
|
if(!entities.length && !noTrim) {
|
||||||
|
newText = newText.trim();
|
||||||
}
|
}
|
||||||
return newText
|
|
||||||
|
return newText;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mergeEntities(currentEntities: MessageEntity[], newEntities: MessageEntity[], fromApi?: boolean) {
|
export function mergeEntities(currentEntities: MessageEntity[], newEntities: MessageEntity[], fromApi?: boolean) {
|
||||||
@ -355,6 +375,10 @@ namespace RichTextProcessor {
|
|||||||
noCommands: true,
|
noCommands: true,
|
||||||
fromBot: boolean,
|
fromBot: boolean,
|
||||||
noTextFormat: true,
|
noTextFormat: true,
|
||||||
|
passEntities: Partial<{
|
||||||
|
[_ in MessageEntity['_']]: true
|
||||||
|
}>,
|
||||||
|
|
||||||
nested?: true,
|
nested?: true,
|
||||||
contextHashtag?: string
|
contextHashtag?: string
|
||||||
}> = {}) {
|
}> = {}) {
|
||||||
@ -362,6 +386,7 @@ namespace RichTextProcessor {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const passEntities: typeof options.passEntities = options.passEntities || {};
|
||||||
const entities = options.entities || parseEntities(text);
|
const entities = options.entities || parseEntities(text);
|
||||||
const contextSite = options.contextSite || 'Telegram';
|
const contextSite = options.contextSite || 'Telegram';
|
||||||
const contextExternal = contextSite != 'Telegram';
|
const contextExternal = contextSite != 'Telegram';
|
||||||
@ -469,7 +494,7 @@ namespace RichTextProcessor {
|
|||||||
inner = encodeEntities(replaceUrlEncodings(entityText));
|
inner = encodeEntities(replaceUrlEncodings(entityText));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(options.noLinks) {
|
if(options.noLinks && !passEntities[entity._]) {
|
||||||
html.push(inner);
|
html.push(inner);
|
||||||
} else {
|
} else {
|
||||||
html.push(
|
html.push(
|
||||||
@ -559,6 +584,14 @@ namespace RichTextProcessor {
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'messageEntityUnderline':
|
||||||
|
html.push(
|
||||||
|
'<u>',
|
||||||
|
wrapRichNestedText(entityText, entity.nested, options),
|
||||||
|
'</u>'
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'messageEntityCode':
|
case 'messageEntityCode':
|
||||||
if(options.noTextFormat) {
|
if(options.noTextFormat) {
|
||||||
html.push(encodeEntities(entityText));
|
html.push(encodeEntities(entityText));
|
||||||
@ -599,7 +632,7 @@ namespace RichTextProcessor {
|
|||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function wrapDraftText(text: string, options: any = {}) {
|
/* export function wrapDraftText(text: string, options: any = {}) {
|
||||||
if(!text || !text.length) {
|
if(!text || !text.length) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
@ -673,8 +706,45 @@ namespace RichTextProcessor {
|
|||||||
}
|
}
|
||||||
code.push(text.substr(lastOffset));
|
code.push(text.substr(lastOffset));
|
||||||
return code.join('');
|
return code.join('');
|
||||||
|
} */
|
||||||
|
|
||||||
|
export function wrapDraftText(text: string, options: Partial<{
|
||||||
|
entities: MessageEntity[]
|
||||||
|
}> = {}) {
|
||||||
|
return wrapRichText(text, {
|
||||||
|
...options,
|
||||||
|
noLinks: true,
|
||||||
|
passEntities: {
|
||||||
|
messageEntityTextUrl: true
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//const draftEntityTypes: MessageEntity['_'][] = (['messageEntityTextUrl', 'messageEntityEmoji'] as MessageEntity['_'][]).concat(Object.values(markdownEntities) as any);
|
||||||
|
/* const draftEntityTypes: Partial<{[_ in MessageEntity['_']]: true}> = {
|
||||||
|
messageEntityCode: true,
|
||||||
|
messageEntityPre: true,
|
||||||
|
messageEntityBold: true,
|
||||||
|
messageEntityItalic: true,
|
||||||
|
messageEntityStrike: true,
|
||||||
|
messageEntityEmoji: true,
|
||||||
|
messageEntityLinebreak: true,
|
||||||
|
messageEntityUnderline: true,
|
||||||
|
messageEntityTextUrl: true
|
||||||
|
};
|
||||||
|
export function wrapDraftText(text: string, options: Partial<{
|
||||||
|
entities: MessageEntity[]
|
||||||
|
}> = {}) {
|
||||||
|
const checkEntity = (entity: MessageEntity) => {
|
||||||
|
return draftEntityTypes[entity._];
|
||||||
|
};
|
||||||
|
const entities = options.entities ? options.entities.filter(entity => {
|
||||||
|
return draftEntityTypes[entity._];
|
||||||
|
}) : [];
|
||||||
|
|
||||||
|
return wrapRichText(text, {entities});
|
||||||
|
} */
|
||||||
|
|
||||||
export function checkBrackets(url: string) {
|
export function checkBrackets(url: string) {
|
||||||
var urlLength = url.length;
|
var urlLength = url.length;
|
||||||
var urlOpenBrackets = url.split('(').length - 1;
|
var urlOpenBrackets = url.split('(').length - 1;
|
||||||
|
@ -1129,6 +1129,11 @@ $bubble-margin: .25rem;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
display: inline;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.video-play {
|
.video-play {
|
||||||
background-color: var(--message-time-background);
|
background-color: var(--message-time-background);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user