add new editor
This commit is contained in:
parent
53f2aa93f7
commit
8d61f8eb2d
@ -20,10 +20,26 @@
|
||||
"@lit-labs/motion": "^1.0.3",
|
||||
"@material/mwc-list": "0.27.0",
|
||||
"@material/mwc-select": "0.27.0",
|
||||
"@tiptap/core": "^2.0.0-beta.209",
|
||||
"@tiptap/extension-image": "^2.0.0-beta.209",
|
||||
"@tiptap/extension-placeholder": "^2.0.0-beta.209",
|
||||
"@tiptap/extension-underline": "^2.0.0-beta.209",
|
||||
"@tiptap/html": "^2.0.0-beta.209",
|
||||
"@tiptap/starter-kit": "^2.0.0-beta.209",
|
||||
"asmcrypto.js": "2.3.2",
|
||||
"compressorjs": "^1.1.1",
|
||||
"emoji-picker-js": "https://github.com/Qortal/emoji-picker-js",
|
||||
"localforage": "^1.10.0",
|
||||
"prosemirror-commands": "^1.5.0",
|
||||
"prosemirror-dropcursor": "^1.6.1",
|
||||
"prosemirror-gapcursor": "^1.3.1",
|
||||
"prosemirror-history": "^1.3.0",
|
||||
"prosemirror-keymap": "^1.2.0",
|
||||
"prosemirror-model": "^1.18.3",
|
||||
"prosemirror-schema-list": "^1.2.2",
|
||||
"prosemirror-state": "^1.4.2",
|
||||
"prosemirror-transform": "^1.7.0",
|
||||
"prosemirror-view": "^1.29.1",
|
||||
"short-unique-id": "^4.4.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -47,8 +63,6 @@
|
||||
"@polymer/paper-slider": "3.0.1",
|
||||
"@polymer/paper-spinner": "3.0.2",
|
||||
"@polymer/paper-tooltip": "3.0.1",
|
||||
"@vaadin/horizontal-layout": "23.3.2",
|
||||
"@vaadin/tabs": "23.3.2",
|
||||
"@rollup/plugin-alias": "4.0.2",
|
||||
"@rollup/plugin-babel": "6.0.3",
|
||||
"@rollup/plugin-commonjs": "24.0.0",
|
||||
@ -58,7 +72,9 @@
|
||||
"@vaadin/avatar": "23.3.2",
|
||||
"@vaadin/button": "23.3.2",
|
||||
"@vaadin/grid": "23.3.2",
|
||||
"@vaadin/horizontal-layout": "23.3.2",
|
||||
"@vaadin/icons": "23.3.2",
|
||||
"@vaadin/tabs": "23.3.2",
|
||||
"@vaadin/tooltip": "23.3.2",
|
||||
"epml": "0.3.3",
|
||||
"file-saver": "2.0.5",
|
||||
|
@ -4,6 +4,12 @@ import {animate} from '@lit-labs/motion';
|
||||
import { Epml } from '../../../epml.js';
|
||||
import { use, get, translate, registerTranslateConfig } from 'lit-translate';
|
||||
import { chatStyles } from './ChatScroller-css.js'
|
||||
import { generateHTML } from '@tiptap/core'
|
||||
import StarterKit from '@tiptap/starter-kit'
|
||||
import Underline from '@tiptap/extension-underline';
|
||||
import Placeholder from '@tiptap/extension-placeholder'
|
||||
import {unsafeHTML} from 'lit/directives/unsafe-html.js';
|
||||
import { Editor, Extension } from '@tiptap/core'
|
||||
|
||||
// import localForage from "localforage";
|
||||
registerTranslateConfig({
|
||||
@ -72,8 +78,6 @@ class ChatPage extends LitElement {
|
||||
iframeHeight: { type: Number },
|
||||
imageFile: { type: Object },
|
||||
isUploadingImage: { type: Boolean },
|
||||
chatEditor: { type: Object },
|
||||
chatEditorNewChat: { type: Object },
|
||||
userLanguage: { type: String },
|
||||
lastMessageRefVisible: { type: Boolean },
|
||||
isLoadingOldMessages: { type: Boolean },
|
||||
@ -91,7 +95,9 @@ class ChatPage extends LitElement {
|
||||
userFoundModalOpen: { type: Boolean },
|
||||
webWorker: { type: Object },
|
||||
webWorkerImage: { type: Object },
|
||||
myTrimmedMeassage: { type: String }
|
||||
myTrimmedMeassage: { type: String },
|
||||
editor: {type: Object},
|
||||
currentEditor: {type: String}
|
||||
}
|
||||
}
|
||||
|
||||
@ -299,6 +305,7 @@ class ChatPage extends LitElement {
|
||||
justify-content: center;
|
||||
min-height: 60px;
|
||||
max-height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.chat-text-area .typing-area {
|
||||
@ -348,6 +355,10 @@ class ChatPage extends LitElement {
|
||||
gap: 5px;
|
||||
width: 100%;
|
||||
}
|
||||
.repliedTo-message p {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.reply-icon {
|
||||
width: 20px;
|
||||
@ -858,6 +869,7 @@ class ChatPage extends LitElement {
|
||||
}
|
||||
this.webWorker = null;
|
||||
this.webWorkerImage = null;
|
||||
this.currentEditor = '_chatEditorDOM'
|
||||
}
|
||||
|
||||
_toggle(value) {
|
||||
@ -922,7 +934,11 @@ class ChatPage extends LitElement {
|
||||
<vaadin-icon class="reply-icon" icon="vaadin:reply" slot="icon"></vaadin-icon>
|
||||
<div class="repliedTo-message">
|
||||
<p class="senderName">${this.repliedToMessageObj.senderName ? this.repliedToMessageObj.senderName : this.repliedToMessageObj.sender}</p>
|
||||
<p class="original-message">${this.repliedToMessageObj.message}</p>
|
||||
${unsafeHTML(generateHTML(this.repliedToMessageObj.message, [
|
||||
StarterKit,
|
||||
Underline
|
||||
// other extensions …
|
||||
]))}
|
||||
</div>
|
||||
<vaadin-icon
|
||||
class="close-icon"
|
||||
@ -939,7 +955,11 @@ class ChatPage extends LitElement {
|
||||
<vaadin-icon class="reply-icon" icon="vaadin:pencil" slot="icon"></vaadin-icon>
|
||||
<div class="repliedTo-message">
|
||||
<p class="senderName">${translate("chatpage.cchange25")}</p>
|
||||
<p class="original-message">${this.editedMessageObj.message}</p>
|
||||
${unsafeHTML(generateHTML(this.editedMessageObj.message, [
|
||||
StarterKit,
|
||||
Underline
|
||||
// other extensions …
|
||||
]))}
|
||||
</div>
|
||||
<vaadin-icon
|
||||
class="close-icon"
|
||||
@ -956,14 +976,16 @@ class ChatPage extends LitElement {
|
||||
iframeId="_chatEditorDOM"
|
||||
placeholder=${this.chatEditorPlaceholder}
|
||||
._sendMessage=${this._sendMessage}
|
||||
.setChatEditor=${(editor)=> this.setChatEditor(editor)}
|
||||
.chatEditor=${this.chatEditor}
|
||||
.imageFile=${this.imageFile}
|
||||
.insertImage=${this.insertImage}
|
||||
.editedMessageObj=${this.editedMessageObj}
|
||||
?isLoading=${this.isLoading}
|
||||
?isLoadingMessages=${this.isLoadingMessages}
|
||||
?isEditMessageOpen=${this.isEditMessageOpen}>
|
||||
?isEditMessageOpen=${this.isEditMessageOpen}
|
||||
.editor=${this.editor}
|
||||
.updatePlaceholder=${(editor, value)=> this.updatePlaceholder(editor, value)}
|
||||
id="_chatEditorDOM"
|
||||
>
|
||||
</chat-text-editor>
|
||||
</div>
|
||||
</div>
|
||||
@ -985,10 +1007,9 @@ class ChatPage extends LitElement {
|
||||
`: ''}
|
||||
<wrapper-modal
|
||||
.onClickFunc=${() => {
|
||||
this.chatEditorNewChat.resetValue();
|
||||
this.removeImage();
|
||||
}}
|
||||
style=${(this.imageFile && !this.isUploadingImage) ? "display: block" : "display: none"}>
|
||||
style=${(this.imageFile && !this.isUploadingImage) ? "visibility:visible;z-index:50" : "visibility: hidden;z-index:-100"}>
|
||||
<div>
|
||||
<div class="dialog-container">
|
||||
${this.imageFile && html`
|
||||
@ -1000,20 +1021,20 @@ class ChatPage extends LitElement {
|
||||
?hasGlobalEvents=${false}
|
||||
placeholder=${this.chatEditorPlaceholder}
|
||||
._sendMessage=${this._sendMessage}
|
||||
.setChatEditor=${(editor)=> this.setChatEditorNewChat(editor)}
|
||||
.chatEditor=${this.chatEditorNewChat}
|
||||
.imageFile=${this.imageFile}
|
||||
.insertImage=${this.insertImage}
|
||||
.editedMessageObj=${this.editedMessageObj}
|
||||
?isLoading=${this.isLoading}
|
||||
?isLoadingMessages=${this.isLoadingMessages}
|
||||
id="chatTextCaption"
|
||||
.editor=${this.editorImage}
|
||||
.updatePlaceholder=${(editor, value)=> this.updatePlaceholder(editor, value)}
|
||||
>
|
||||
</chat-text-editor>
|
||||
</div>
|
||||
<div class="modal-button-row">
|
||||
<button class="modal-button-red" @click=${() => {
|
||||
this.chatEditorNewChat.resetValue();
|
||||
|
||||
this.removeImage();
|
||||
}}>
|
||||
${translate("chatpage.cchange33")}
|
||||
@ -1047,7 +1068,6 @@ class ChatPage extends LitElement {
|
||||
.onClickFunc=${() => {
|
||||
this.openForwardOpen = false;
|
||||
this.forwardActiveChatHeadUrl = {};
|
||||
this.chatEditor.enable();
|
||||
this.requestUpdate();
|
||||
} }
|
||||
style=${this.openForwardOpen ? "display: block" : "display: none"}>
|
||||
@ -1136,7 +1156,6 @@ class ChatPage extends LitElement {
|
||||
<button class="modal-button-red" @click=${() => {
|
||||
this.openForwardOpen = false;
|
||||
this.forwardActiveChatHeadUrl = {};
|
||||
this.chatEditor.enable();
|
||||
this.requestUpdate();
|
||||
}}>
|
||||
${translate("chatpage.cchange33")}
|
||||
@ -1214,16 +1233,71 @@ class ChatPage extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
|
||||
|
||||
async connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this.webWorker = new WebWorker();
|
||||
this.webWorkerImage = new WebWorkerImage();
|
||||
await this.getUpdateCompleteTextEditor();
|
||||
|
||||
const elementChatId = this.shadowRoot.getElementById('_chatEditorDOM').shadowRoot.getElementById('_chatEditorDOM')
|
||||
const elementChatImageId = this.shadowRoot.getElementById('chatTextCaption').shadowRoot.getElementById('newChat')
|
||||
console.log({elementChatId, elementChatImageId })
|
||||
this.editor = new Editor({
|
||||
element: elementChatId,
|
||||
extensions: [
|
||||
StarterKit,
|
||||
Underline,
|
||||
Placeholder.configure({
|
||||
placeholder: 'Write something …',
|
||||
}),
|
||||
Extension.create({
|
||||
addKeyboardShortcuts:()=> {
|
||||
return {
|
||||
'Enter': ()=> {
|
||||
const chatTextEditor = this.shadowRoot.getElementById('_chatEditorDOM')
|
||||
chatTextEditor.sendMessageFunc({
|
||||
})
|
||||
return true
|
||||
}
|
||||
}
|
||||
}})
|
||||
]
|
||||
})
|
||||
|
||||
this.editorImage = new Editor({
|
||||
element: elementChatImageId,
|
||||
extensions: [
|
||||
StarterKit,
|
||||
Underline,
|
||||
Placeholder.configure({
|
||||
placeholder: 'Write something …',
|
||||
}),
|
||||
Extension.create({
|
||||
addKeyboardShortcuts:()=> {
|
||||
return {
|
||||
'Enter':()=> {
|
||||
const chatTextEditor = this.shadowRoot.getElementById('chatTextCaption')
|
||||
chatTextEditor.sendMessageFunc({
|
||||
type: 'image',
|
||||
imageFile: this.imageFile,
|
||||
})
|
||||
return true
|
||||
}
|
||||
}
|
||||
}})
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
console.log('disconnected')
|
||||
this.webWorker.terminate();
|
||||
this.webWorkerImage.terminate();
|
||||
this.editor.destroy()
|
||||
this.editorImage.destroy()
|
||||
}
|
||||
|
||||
async userSearch() {
|
||||
@ -1285,18 +1359,11 @@ class ChatPage extends LitElement {
|
||||
this.lastMessageRefVisible = props;
|
||||
}
|
||||
|
||||
setChatEditor(editor) {
|
||||
this.chatEditor = editor;
|
||||
}
|
||||
|
||||
setChatEditorNewChat(editor) {
|
||||
this.chatEditorNewChat = editor;
|
||||
}
|
||||
|
||||
insertImage(file) {
|
||||
if (file.type.includes('image')) {
|
||||
this.imageFile = file;
|
||||
this.chatEditor.disable();
|
||||
this.currentEditor = 'newChat'
|
||||
return;
|
||||
}
|
||||
parentEpml.request('showSnackBar', get("chatpage.cchange28"));
|
||||
@ -1304,12 +1371,11 @@ class ChatPage extends LitElement {
|
||||
|
||||
removeImage() {
|
||||
this.imageFile = null;
|
||||
this.chatEditor.enable();
|
||||
this.resetChatEditor()
|
||||
this.currentEditor = '_chatEditorDOM'
|
||||
}
|
||||
|
||||
changeMsgInput(id) {
|
||||
|
||||
this.chatEditor.remove()
|
||||
this.chatMessageInput = this.shadowRoot.getElementById(id);
|
||||
this.initChatEditor();
|
||||
}
|
||||
@ -1452,6 +1518,7 @@ class ChatPage extends LitElement {
|
||||
})
|
||||
parentEpml.imReady();
|
||||
|
||||
|
||||
await this.initUpdate()
|
||||
}
|
||||
|
||||
@ -1472,7 +1539,6 @@ class ChatPage extends LitElement {
|
||||
|
||||
if (changedProperties && changedProperties.has('openForwardOpen')) {
|
||||
if (this.openForwardOpen === true) {
|
||||
this.chatEditor.disable();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1532,7 +1598,6 @@ async getName (recipient) {
|
||||
.getOldMessage=${this.getOldMessage}
|
||||
.setRepliedToMessageObj=${(val) => this.setRepliedToMessageObj(val)}
|
||||
.setEditedMessageObj=${(val) => this.setEditedMessageObj(val)}
|
||||
.focusChatEditor=${() => this.focusChatEditor()}
|
||||
.sendMessage=${(val) => this._sendMessage(val)}
|
||||
.sendMessageForward=${(messageText, typeMessage, chatReference, isForward, forwardParams)=> this.sendMessage(messageText, typeMessage, chatReference, isForward, forwardParams)}
|
||||
.showLastMessageRefScroller=${(val) => this.showLastMessageRefScroller(val)}
|
||||
@ -1555,6 +1620,25 @@ async getName (recipient) {
|
||||
return true;
|
||||
}
|
||||
|
||||
async getUpdateCompleteTextEditor() {
|
||||
await super.getUpdateComplete();
|
||||
const marginElements = Array.from(this.shadowRoot.querySelectorAll('chat-text-editor'));
|
||||
await Promise.all(marginElements.map(el => el.updateComplete));
|
||||
const marginElements2 = Array.from(this.shadowRoot.querySelectorAll('wrapper-modal'));
|
||||
await Promise.all(marginElements2.map(el => el.updateComplete));
|
||||
return true;
|
||||
}
|
||||
|
||||
updatePlaceholder(editor, text){
|
||||
editor.extensionManager.extensions.forEach((extension) => {
|
||||
if (extension.name === "placeholder") {
|
||||
|
||||
extension.options["placeholder"] = text
|
||||
editor.commands.focus('end')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async getOldMessage(scrollElement) {
|
||||
|
||||
if (this.isReceipient) {
|
||||
@ -1685,6 +1769,7 @@ async getName (recipient) {
|
||||
// set replied to message in chat editor
|
||||
|
||||
setRepliedToMessageObj(messageObj) {
|
||||
this.editor.commands.focus('end')
|
||||
this.repliedToMessageObj = {...messageObj};
|
||||
this.editedMessageObj = null;
|
||||
this.requestUpdate();
|
||||
@ -1693,6 +1778,7 @@ async getName (recipient) {
|
||||
// set edited message in chat editor
|
||||
|
||||
setEditedMessageObj(messageObj) {
|
||||
this.editor.commands.focus('end')
|
||||
this.editedMessageObj = {...messageObj};
|
||||
this.repliedToMessageObj = null;
|
||||
this.requestUpdate();
|
||||
@ -1701,7 +1787,6 @@ async getName (recipient) {
|
||||
closeEditMessageContainer() {
|
||||
this.editedMessageObj = null;
|
||||
this.isEditMessageOpen = !this.isEditMessageOpen;
|
||||
this.chatEditor.resetValue();
|
||||
}
|
||||
|
||||
closeRepliedToContainer() {
|
||||
@ -1709,9 +1794,7 @@ async getName (recipient) {
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
focusChatEditor() {
|
||||
this.chatEditor.focus();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* New Message Template implementation, takes in a message object.
|
||||
@ -1990,7 +2073,16 @@ async getName (recipient) {
|
||||
// Add to the messages... TODO: Save messages to localstorage and fetch from it to make it persistent...
|
||||
}
|
||||
|
||||
async _sendMessage(outSideMsg) {
|
||||
resetChatEditor(){
|
||||
if(this.currentEditor === '_chatEditorDOM'){
|
||||
this.editor.commands.setContent('')
|
||||
}
|
||||
if(this.currentEditor === 'newChat'){
|
||||
this.editorImage.commands.setContent('')
|
||||
}
|
||||
}
|
||||
|
||||
async _sendMessage(outSideMsg, msg) {
|
||||
if(this.isReceipient){
|
||||
let hasPublicKey = true
|
||||
if(!this._publicKey.hasPubKey){
|
||||
@ -2032,12 +2124,7 @@ async getName (recipient) {
|
||||
let typeMessage = 'regular';
|
||||
let workerImage;
|
||||
this.isLoading = true;
|
||||
this.chatEditor.disable();
|
||||
this.chatEditorNewChat.disable()
|
||||
const messageText = this.chatEditor.mirror.value;
|
||||
// Format and Sanitize Message
|
||||
const sanitizedMessage = messageText.replace(/ /gi, ' ').replace(/<br\s*[\/]?>/gi, '\n');
|
||||
const trimmedMessage = sanitizedMessage.trim();
|
||||
const trimmedMessage = msg
|
||||
|
||||
const getName = async (recipient)=> {
|
||||
try {
|
||||
@ -2121,10 +2208,7 @@ async getName (recipient) {
|
||||
})
|
||||
this.isDeletingImage = false
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
this.isLoading = false;
|
||||
this.chatEditor.enable();
|
||||
this.chatEditorNewChat.enable()
|
||||
return
|
||||
}
|
||||
typeMessage = 'edit';
|
||||
@ -2157,8 +2241,6 @@ async getName (recipient) {
|
||||
if (!userName) {
|
||||
parentEpml.request('showSnackBar', get("chatpage.cchange27"));
|
||||
this.isLoading = false;
|
||||
this.chatEditor.enable();
|
||||
this.chatEditorNewChat.enable()
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2193,8 +2275,6 @@ async getName (recipient) {
|
||||
parentEpml.request('showSnackBar', get("chatpage.cchange26"));
|
||||
this.isLoading = false;
|
||||
this.isUploadingImage = false;
|
||||
this.chatEditor.enable();
|
||||
this.chatEditorNewChat.enable();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@ -2210,21 +2290,17 @@ async getName (recipient) {
|
||||
worker: workerImage
|
||||
});
|
||||
this.isUploadingImage = false;
|
||||
this.imageFile = null;
|
||||
this.removeImage()
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
this.isLoading = false;
|
||||
this.isUploadingImage = false;
|
||||
this.chatEditor.enable();
|
||||
this.chatEditorNewChat.enable();
|
||||
return;
|
||||
}
|
||||
const messageTextWithImage = this.chatEditorNewChat.mirror.value;
|
||||
// Format and Sanitize Message
|
||||
const sanitizedMessageWithImage = messageTextWithImage.replace(/ /gi, ' ').replace(/<br\s*[\/]?>/gi, '\n');
|
||||
const trimmedMessageWithImage = sanitizedMessageWithImage.trim();
|
||||
|
||||
|
||||
|
||||
const messageObject = {
|
||||
messageText: trimmedMessageWithImage,
|
||||
messageText: trimmedMessage,
|
||||
images: [{
|
||||
service: "QCHAT_IMAGE",
|
||||
name: userName,
|
||||
@ -2232,7 +2308,7 @@ async getName (recipient) {
|
||||
}],
|
||||
isImageDeleted: false,
|
||||
repliedTo: '',
|
||||
version: 1
|
||||
version: 2
|
||||
};
|
||||
const stringifyMessageObject = JSON.stringify(messageObject);
|
||||
this.sendMessage(stringifyMessageObject, typeMessage);
|
||||
@ -2287,8 +2363,7 @@ async getName (recipient) {
|
||||
this.sendMessage(stringifyMessageObject, typeMessage, chatReference);
|
||||
} else if (/^\s*$/.test(trimmedMessage)) {
|
||||
this.isLoading = false;
|
||||
this.chatEditor.enable();
|
||||
this.chatEditorNewChat.enable();
|
||||
|
||||
}
|
||||
else if (this.repliedToMessageObj) {
|
||||
let chatReference = this.repliedToMessageObj.reference;
|
||||
@ -2300,7 +2375,7 @@ async getName (recipient) {
|
||||
messageText: trimmedMessage,
|
||||
images: [''],
|
||||
repliedTo: chatReference,
|
||||
version: 1
|
||||
version: 2
|
||||
}
|
||||
const stringifyMessageObject = JSON.stringify(messageObject);
|
||||
this.sendMessage(stringifyMessageObject, typeMessage);
|
||||
@ -2332,7 +2407,7 @@ async getName (recipient) {
|
||||
messageText: trimmedMessage,
|
||||
images: [''],
|
||||
repliedTo: '',
|
||||
version: 1
|
||||
version: 2
|
||||
}
|
||||
const stringifyMessageObject = JSON.stringify(messageObject)
|
||||
|
||||
@ -2448,7 +2523,6 @@ async getName (recipient) {
|
||||
|
||||
const recipientAddress = this.forwardActiveChatHeadUrl.url.split('/')[1];
|
||||
this.openForwardOpen = false;
|
||||
this.chatEditor.enable();
|
||||
if (isRecipient === true) {
|
||||
if(!publicKey.hasPubKey){
|
||||
let err4string = get("chatpage.cchange39");
|
||||
@ -2532,8 +2606,7 @@ async getName (recipient) {
|
||||
|
||||
const getSendChatResponse = (response, isForward) => {
|
||||
if (response === true) {
|
||||
this.chatEditor.resetValue();
|
||||
this.chatEditorNewChat.resetValue()
|
||||
this.resetChatEditor()
|
||||
if(isForward){
|
||||
let successString = get("blockpage.bcchange15");
|
||||
parentEpml.request('showSnackBar', `${successString}`);
|
||||
@ -2546,8 +2619,6 @@ async getName (recipient) {
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
this.chatEditor.enable();
|
||||
this.chatEditorNewChat.enable()
|
||||
this.closeEditMessageContainer()
|
||||
this.closeRepliedToContainer()
|
||||
this.openForwardOpen = false
|
||||
|
@ -190,6 +190,10 @@ export const chatStyles = css`
|
||||
text-overflow: ellipsis;
|
||||
max-width: 300px;
|
||||
}
|
||||
.replied-message p {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.message {
|
||||
color: var(--chat-bubble-msg-color);
|
||||
@ -494,4 +498,128 @@ export const chatStyles = css`
|
||||
cursor: pointer;
|
||||
background-color: #03a8f475;
|
||||
}
|
||||
|
||||
#messageContent p {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#messageContent > * + * {
|
||||
margin-top: 0.75em;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#messageContent ul,
|
||||
ol {
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
#messageContent h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
#messageContent code {
|
||||
background-color: rgba(#616161, 0.1);
|
||||
color: #616161;
|
||||
}
|
||||
|
||||
#messageContent pre {
|
||||
background: #0D0D0D;
|
||||
color: #FFF;
|
||||
font-family: 'JetBrainsMono', monospace;
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
#messageContent pre code {
|
||||
color: inherit;
|
||||
padding: 0;
|
||||
background: none;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
|
||||
#messageContent img {
|
||||
width: 1.7em;
|
||||
height: 1.5em;
|
||||
margin: 0px;
|
||||
|
||||
}
|
||||
|
||||
#messageContent blockquote {
|
||||
padding-left: 1rem;
|
||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
||||
}
|
||||
|
||||
#messageContent hr {
|
||||
border: none;
|
||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.replied-message p {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.replied-message > * + * {
|
||||
margin-top: 0.75em;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.replied-message ul,
|
||||
ol {
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
.replied-message h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.replied-message code {
|
||||
background-color: rgba(#616161, 0.1);
|
||||
color: #616161;
|
||||
}
|
||||
|
||||
.replied-message pre {
|
||||
background: #0D0D0D;
|
||||
color: #FFF;
|
||||
font-family: 'JetBrainsMono', monospace;
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
.replied-message pre code {
|
||||
color: inherit;
|
||||
padding: 0;
|
||||
background: none;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
|
||||
.replied-message img {
|
||||
width: 1.7em;
|
||||
height: 1.5em;
|
||||
margin: 0px;
|
||||
|
||||
}
|
||||
|
||||
.replied-message blockquote {
|
||||
padding-left: 1rem;
|
||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
||||
}
|
||||
|
||||
.replied-message hr {
|
||||
border: none;
|
||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
||||
margin: 2rem 0;
|
||||
}
|
||||
`
|
||||
|
@ -15,6 +15,9 @@ import '@material/mwc-dialog';
|
||||
import '@material/mwc-icon';
|
||||
import { EmojiPicker } from 'emoji-picker-js';
|
||||
import { cropAddress } from "../../utils/cropAddress";
|
||||
import { generateHTML } from '@tiptap/core'
|
||||
import StarterKit from '@tiptap/starter-kit'
|
||||
import Underline from '@tiptap/extension-underline';
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
let toggledMessage = {}
|
||||
@ -28,7 +31,6 @@ class ChatScroller extends LitElement {
|
||||
hideMessages: { type: Array },
|
||||
setRepliedToMessageObj: {attribute: false},
|
||||
setEditedMessageObj: {attribute: false},
|
||||
focusChatEditor: {attribute: false},
|
||||
sendMessage: {attribute: false},
|
||||
sendMessageForward: {attribute: false},
|
||||
showLastMessageRefScroller: { type: Function },
|
||||
@ -54,6 +56,7 @@ class ChatScroller extends LitElement {
|
||||
|
||||
|
||||
render() {
|
||||
console.log('this.messages', this.messages)
|
||||
let formattedMessages = this.messages.reduce((messageArray, message, index) => {
|
||||
const lastGroupedMessage = messageArray[messageArray.length - 1];
|
||||
let timestamp;
|
||||
@ -108,7 +111,6 @@ class ChatScroller extends LitElement {
|
||||
.hideMessages=${this.hideMessages}
|
||||
.setRepliedToMessageObj=${this.setRepliedToMessageObj}
|
||||
.setEditedMessageObj=${this.setEditedMessageObj}
|
||||
.focusChatEditor=${this.focusChatEditor}
|
||||
.sendMessage=${this.sendMessage}
|
||||
.sendMessageForward=${this.sendMessageForward}
|
||||
?isFirstMessage=${indexMessage === 0}
|
||||
@ -231,7 +233,6 @@ class MessageTemplate extends LitElement {
|
||||
showBlockAddressIcon: { type: Boolean },
|
||||
setRepliedToMessageObj: { attribute: false },
|
||||
setEditedMessageObj: { attribute: false },
|
||||
focusChatEditor: { attribute: false },
|
||||
sendMessage: { attribute: false },
|
||||
sendMessageForward: { attribute: false },
|
||||
openDialogImage: { attribute: false },
|
||||
@ -294,6 +295,7 @@ class MessageTemplate extends LitElement {
|
||||
render() {
|
||||
const hidemsg = this.hideMessages;
|
||||
let message = "";
|
||||
let messageVersion2 = ""
|
||||
let reactions = [];
|
||||
let repliedToData = null;
|
||||
let image = null;
|
||||
@ -302,6 +304,14 @@ class MessageTemplate extends LitElement {
|
||||
let isForwarded = false
|
||||
try {
|
||||
const parsedMessageObj = JSON.parse(this.messageObj.decodedMessage);
|
||||
if(parsedMessageObj.version.toString() === '2'){
|
||||
|
||||
messageVersion2 = generateHTML(parsedMessageObj.messageText, [
|
||||
StarterKit,
|
||||
Underline
|
||||
// other extensions …
|
||||
])
|
||||
}
|
||||
message = parsedMessageObj.messageText;
|
||||
repliedToData = this.messageObj.repliedToData;
|
||||
isImageDeleted = parsedMessageObj.isImageDeleted;
|
||||
@ -466,7 +476,12 @@ class MessageTemplate extends LitElement {
|
||||
${repliedToData.senderName ?? cropAddress(repliedToData.sender)}
|
||||
</p>
|
||||
<p class="replied-message">
|
||||
${repliedToData.decodedMessage.messageText}
|
||||
${unsafeHTML(generateHTML(repliedToData.decodedMessage.messageText, [
|
||||
StarterKit,
|
||||
Underline
|
||||
// other extensions …
|
||||
]))}
|
||||
<!-- ${repliedToData.decodedMessage.messageText} -->
|
||||
</p>
|
||||
</div>
|
||||
`}
|
||||
@ -501,7 +516,8 @@ class MessageTemplate extends LitElement {
|
||||
id="messageContent"
|
||||
class="message"
|
||||
style=${(image && replacedMessage !== "") &&"margin-top: 15px;"}>
|
||||
${unsafeHTML(this.emojiPicker.parse(replacedMessage))}
|
||||
|
||||
${unsafeHTML(messageVersion2)}
|
||||
<div class="${((this.isFirstMessage === false &&
|
||||
this.isSingleMessageInGroup === true &&
|
||||
this.isLastMessageInGroup === true) ||
|
||||
@ -527,7 +543,6 @@ class MessageTemplate extends LitElement {
|
||||
.originalMessage=${{...this.messageObj, message}}
|
||||
.setRepliedToMessageObj=${this.setRepliedToMessageObj}
|
||||
.setEditedMessageObj=${this.setEditedMessageObj}
|
||||
.focusChatEditor=${this.focusChatEditor}
|
||||
.myAddress=${this.myAddress}
|
||||
@blur=${() => this.showBlockIconFunc(false)}
|
||||
.sendMessage=${this.sendMessage}
|
||||
@ -634,7 +649,6 @@ class ChatMenu extends LitElement {
|
||||
originalMessage: { type: Object },
|
||||
setRepliedToMessageObj: {attribute: false},
|
||||
setEditedMessageObj: {attribute: false},
|
||||
focusChatEditor: {attribute: false},
|
||||
myAddress: { type: Object },
|
||||
emojiPicker: { attribute: false },
|
||||
sendMessage: { attribute: false },
|
||||
@ -767,7 +781,6 @@ class ChatMenu extends LitElement {
|
||||
return
|
||||
}
|
||||
this.setRepliedToMessageObj(this.originalMessage);
|
||||
this.focusChatEditor();
|
||||
}}">
|
||||
<vaadin-icon icon="vaadin:reply" slot="icon"></vaadin-icon>
|
||||
</div>
|
||||
@ -783,7 +796,6 @@ class ChatMenu extends LitElement {
|
||||
return
|
||||
}
|
||||
this.setEditedMessageObj(this.originalMessage);
|
||||
this.focusChatEditor();
|
||||
}}>
|
||||
<vaadin-icon icon="vaadin:pencil" slot="icon"></vaadin-icon>
|
||||
</div>
|
||||
|
828
qortal-ui-plugins/plugins/core/components/ChatTextEditor copy.js
Normal file
828
qortal-ui-plugins/plugins/core/components/ChatTextEditor copy.js
Normal file
@ -0,0 +1,828 @@
|
||||
import { LitElement, html, css } from "lit";
|
||||
import { get } from 'lit-translate';
|
||||
import { escape, unescape } from 'html-escaper';
|
||||
import { EmojiPicker } from 'emoji-picker-js';
|
||||
import { inputKeyCodes } from '../../utils/keyCodes.js';
|
||||
import { Epml } from '../../../epml.js';
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent });
|
||||
class ChatTextEditor extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
isLoading: { type: Boolean },
|
||||
isLoadingMessages: { type: Boolean },
|
||||
_sendMessage: { attribute: false },
|
||||
placeholder: { type: String },
|
||||
imageFile: { type: Object },
|
||||
insertImage: { attribute: false },
|
||||
iframeHeight: { type: Number },
|
||||
editedMessageObj: { type: Object },
|
||||
chatEditor: { type: Object },
|
||||
setChatEditor: { attribute: false },
|
||||
iframeId: { type: String },
|
||||
hasGlobalEvents: { type: Boolean },
|
||||
chatMessageSize: { type: Number },
|
||||
isEditMessageOpen: { type: Boolean },
|
||||
theme: {
|
||||
type: String,
|
||||
reflect: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return css`
|
||||
:host {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: auto;
|
||||
overflow-y: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
.chatbar-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
height: auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.chatbar-caption {
|
||||
border-bottom: 2px solid var(--mdc-theme-primary);
|
||||
}
|
||||
|
||||
.emoji-button {
|
||||
width: 45px;
|
||||
height: 40px;
|
||||
padding-top: 4px;
|
||||
border: none;
|
||||
outline: none;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
max-height: 40px;
|
||||
color: var(--black);
|
||||
}
|
||||
|
||||
.message-size-container {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.message-size {
|
||||
font-family: Roboto, sans-serif;
|
||||
font-size: 12px;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.paperclip-icon {
|
||||
color: var(--paperclip-icon);
|
||||
width: 25px;
|
||||
}
|
||||
|
||||
.paperclip-icon:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.send-icon {
|
||||
width: 30px;
|
||||
margin-left: 5px;
|
||||
transition: all 0.1s ease-in-out;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.send-icon:hover {
|
||||
filter: brightness(1.1);
|
||||
}
|
||||
|
||||
.file-picker-container {
|
||||
position: relative;
|
||||
height: 25px;
|
||||
width: 25px;
|
||||
}
|
||||
|
||||
.file-picker-input-container {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
z-index: 10;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
input[type=file]::-webkit-file-upload-button {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.chatbar-container textarea {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.chatbar-container .chat-editor {
|
||||
display: flex;
|
||||
max-height: -webkit-fill-available;
|
||||
width: 100%;
|
||||
border-color: transparent;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.checkmark-icon {
|
||||
width: 30px;
|
||||
color: var(--mdc-theme-primary);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.checkmark-icon:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
this.isLoadingMessages = true
|
||||
this.isLoading = false
|
||||
this.getMessageSize = this.getMessageSize.bind(this)
|
||||
this.calculateIFrameHeight = this.calculateIFrameHeight.bind(this)
|
||||
this.resetIFrameHeight = this.resetIFrameHeight.bind(this)
|
||||
this.addGlobalEventListener = this.addGlobalEventListener.bind(this)
|
||||
this.sendMessageFunc = this.sendMessageFunc.bind(this)
|
||||
this.removeGlobalEventListener = this.removeGlobalEventListener.bind(this)
|
||||
this.initialChat = this.initialChat.bind(this)
|
||||
this.iframeHeight = 42
|
||||
this.chatMessageSize = 0
|
||||
this.userName = window.parent.reduxStore.getState().app.accountInfo.names[0]
|
||||
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
|
||||
}
|
||||
|
||||
render() {
|
||||
let scrollHeightBool = false;
|
||||
try {
|
||||
if (this.chatMessageInput && this.chatMessageInput.contentDocument.body.scrollHeight > 60 && this.shadowRoot.querySelector(".chat-editor").contentDocument.body.querySelector("#chatbarId").innerHTML.trim() !== "") {
|
||||
scrollHeightBool = true;
|
||||
}
|
||||
} catch (error) {
|
||||
scrollHeightBool = false;
|
||||
}
|
||||
return html`
|
||||
<div
|
||||
class=${["chatbar-container", (this.iframeId === "newChat" || this.iframeId === "privateMessage") ? "chatbar-caption" : ""].join(" ")}
|
||||
style="${scrollHeightBool ? 'align-items: flex-end' : "align-items: center"}">
|
||||
<div
|
||||
style=${this.iframeId === "privateMessage" ? "display: none" : "display: block"}
|
||||
class="file-picker-container"
|
||||
@click=${(e) => {
|
||||
this.preventUserSendingImage(e)
|
||||
}}>
|
||||
<vaadin-icon
|
||||
class="paperclip-icon"
|
||||
icon="vaadin:paperclip"
|
||||
slot="icon"
|
||||
>
|
||||
</vaadin-icon>
|
||||
<div class="file-picker-input-container">
|
||||
<input
|
||||
@change="${e => {
|
||||
this.insertImage(e.target.files[0]);
|
||||
const filePickerInput = this.shadowRoot.getElementById('file-picker')
|
||||
if(filePickerInput){
|
||||
filePickerInput.value = ""
|
||||
}
|
||||
}
|
||||
}"
|
||||
id="file-picker"
|
||||
class="file-picker-input" type="file" name="myImage" accept="image/*" />
|
||||
</div>
|
||||
</div>
|
||||
<textarea style="color: var(--black);" tabindex='1' ?autofocus=${true} ?disabled=${this.isLoading || this.isLoadingMessages} id="messageBox" rows="1"></textarea>
|
||||
<iframe style=${(this.iframeId === "newChat" && this.iframeHeight > 42) && "height: 100%;"} id=${this.iframeId} class="chat-editor" tabindex="-1" height=${this.iframeHeight}></iframe>
|
||||
<button class="emoji-button" ?disabled=${this.isLoading || this.isLoadingMessages}>
|
||||
${html`<img class="emoji" draggable="false" alt="😀" src="/emoji/svg/1f600.svg" />`}
|
||||
</button>
|
||||
${this.editedMessageObj ? (
|
||||
html`
|
||||
<div>
|
||||
${this.isLoading === false ? html`
|
||||
<vaadin-icon
|
||||
class="checkmark-icon"
|
||||
icon="vaadin:check"
|
||||
slot="icon"
|
||||
@click=${() => {
|
||||
this.sendMessageFunc();
|
||||
}}
|
||||
>
|
||||
</vaadin-icon>
|
||||
` :
|
||||
html`
|
||||
<paper-spinner-lite active></paper-spinner-lite>
|
||||
`}
|
||||
</div>
|
||||
`
|
||||
) :
|
||||
html`
|
||||
<div
|
||||
style="${scrollHeightBool
|
||||
? 'margin-bottom: 5px;'
|
||||
: "margin-bottom: 0;"}
|
||||
${this.iframeId === 'newChat'
|
||||
? 'display: none;'
|
||||
: 'display: flex;'}">
|
||||
${this.isLoading === false ? html`
|
||||
<img
|
||||
src="/img/qchat-send-message-icon.svg"
|
||||
alt="send-icon"
|
||||
class="send-icon"
|
||||
@click=${() => {
|
||||
this.sendMessageFunc();
|
||||
}}
|
||||
/>
|
||||
` :
|
||||
html`
|
||||
<paper-spinner-lite active></paper-spinner-lite>
|
||||
`}
|
||||
</div>
|
||||
`
|
||||
}
|
||||
</div>
|
||||
${this.chatMessageSize >= 750 ?
|
||||
html`
|
||||
<div class="message-size-container" style=${this.imageFile && "margin-top: 10px;"}>
|
||||
<div class="message-size" style="${this.chatMessageSize > 1000 && 'color: #bd1515'}">
|
||||
${`Your message size is of ${this.chatMessageSize} bytes out of a maximum of 1000`}
|
||||
</div>
|
||||
</div>
|
||||
` :
|
||||
html``}
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
preventUserSendingImage(e) {
|
||||
if (!this.userName) {
|
||||
e.preventDefault();
|
||||
parentEpml.request('showSnackBar', get("chatpage.cchange27"));
|
||||
};
|
||||
}
|
||||
|
||||
initialChat(e) {
|
||||
if (!this.chatEditor?.contentDiv.matches(':focus')) {
|
||||
// WARNING: Deprecated methods from KeyBoard Event
|
||||
if (e.code === "Space" || e.keyCode === 32 || e.which === 32) {
|
||||
this.chatEditor.insertText(' ');
|
||||
} else if (inputKeyCodes.includes(e.keyCode)) {
|
||||
this.chatEditor.insertText(e.key);
|
||||
return this.chatEditor.focus();
|
||||
} else {
|
||||
return this.chatEditor.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addGlobalEventListener(){
|
||||
document.addEventListener('keydown', this.initialChat);
|
||||
}
|
||||
|
||||
removeGlobalEventListener(){
|
||||
document.removeEventListener('keydown', this.initialChat);
|
||||
}
|
||||
|
||||
async firstUpdated() {
|
||||
if (this.hasGlobalEvents) {
|
||||
this.addGlobalEventListener();
|
||||
}
|
||||
|
||||
window.addEventListener('storage', () => {
|
||||
const checkTheme = localStorage.getItem('qortalTheme');
|
||||
const chatbar = this.shadowRoot.getElementById(this.iframeId).contentWindow.document.getElementById('chatbarId');
|
||||
if (checkTheme === 'dark') {
|
||||
this.theme = 'dark';
|
||||
chatbar.style.cssText = "color:#ffffff;"
|
||||
} else {
|
||||
this.theme = 'light';
|
||||
chatbar.style.cssText = "color:#080808;"
|
||||
}
|
||||
})
|
||||
|
||||
this.emojiPickerHandler = this.shadowRoot.querySelector('.emoji-button');
|
||||
this.mirrorChatInput = this.shadowRoot.getElementById('messageBox');
|
||||
this.chatMessageInput = this.shadowRoot.getElementById(this.iframeId);
|
||||
|
||||
this.emojiPicker = new EmojiPicker({
|
||||
style: "twemoji",
|
||||
twemojiBaseUrl: '/emoji/',
|
||||
showPreview: false,
|
||||
showVariants: false,
|
||||
showAnimation: false,
|
||||
position: 'top-start',
|
||||
boxShadow: 'rgba(4, 4, 5, 0.15) 0px 0px 0px 1px, rgba(0, 0, 0, 0.24) 0px 8px 16px 0px',
|
||||
zIndex: 100
|
||||
|
||||
});
|
||||
|
||||
this.emojiPicker.on('emoji', selection => {
|
||||
const emojiHtmlString = `<img class="emoji" draggable="false" alt="${selection.emoji}" src="${selection.url}">`;
|
||||
this.chatEditor.insertEmoji(emojiHtmlString);
|
||||
});
|
||||
|
||||
|
||||
this.emojiPickerHandler.addEventListener('click', () => this.emojiPicker.togglePicker(this.emojiPickerHandler));
|
||||
|
||||
await this.updateComplete;
|
||||
this.initChatEditor();
|
||||
}
|
||||
|
||||
async updated(changedProperties) {
|
||||
if (changedProperties && changedProperties.has('editedMessageObj')) {
|
||||
if (this.editedMessageObj) {
|
||||
this.chatEditor.insertText(this.editedMessageObj.message);
|
||||
this.getMessageSize(this.editedMessageObj.message);
|
||||
} else {
|
||||
this.chatEditor.insertText("");
|
||||
this.chatMessageSize = 0;
|
||||
}
|
||||
}
|
||||
if (changedProperties && changedProperties.has('placeholder')) {
|
||||
const captionEditor = this.shadowRoot.getElementById(this.iframeId).contentWindow.document.getElementById('chatbarId');
|
||||
captionEditor.setAttribute('data-placeholder', this.placeholder);
|
||||
}
|
||||
|
||||
if (changedProperties && changedProperties.has("imageFile")) {
|
||||
this.chatMessageInput = "newChat";
|
||||
}
|
||||
}
|
||||
|
||||
shouldUpdate(changedProperties) {
|
||||
// Only update element if prop1 changed.
|
||||
if(changedProperties.has('setChatEditor') && changedProperties.size === 1) return false
|
||||
return true
|
||||
}
|
||||
|
||||
sendMessageFunc(props) {
|
||||
if (this.chatMessageSize > 1000 ) {
|
||||
parentEpml.request('showSnackBar', get("chatpage.cchange29"));
|
||||
return;
|
||||
};
|
||||
this.chatMessageSize = 0;
|
||||
this.chatEditor.updateMirror();
|
||||
this._sendMessage(props);
|
||||
}
|
||||
|
||||
getMessageSize(message){
|
||||
try {
|
||||
const messageText = message;
|
||||
// Format and Sanitize Message
|
||||
const sanitizedMessage = messageText.replace(/ /gi, ' ').replace(/<br\s*[\/]?>/gi, '\n');
|
||||
const trimmedMessage = sanitizedMessage.trim();
|
||||
let messageObject = {};
|
||||
|
||||
if (this.repliedToMessageObj) {
|
||||
let chatReference = this.repliedToMessageObj.reference;
|
||||
if (this.repliedToMessageObj.chatReference) {
|
||||
chatReference = this.repliedToMessageObj.chatReference;
|
||||
}
|
||||
messageObject = {
|
||||
messageText: trimmedMessage,
|
||||
images: [''],
|
||||
repliedTo: chatReference,
|
||||
version: 1
|
||||
}
|
||||
} else if (this.editedMessageObj) {
|
||||
let message = "";
|
||||
try {
|
||||
const parsedMessageObj = JSON.parse(this.editedMessageObj.decodedMessage);
|
||||
message = parsedMessageObj;
|
||||
} catch (error) {
|
||||
message = this.messageObj.decodedMessage
|
||||
}
|
||||
messageObject = {
|
||||
...message,
|
||||
messageText: trimmedMessage,
|
||||
}
|
||||
} else if(this.imageFile && this.iframeId === 'newChat') {
|
||||
messageObject = {
|
||||
messageText: trimmedMessage,
|
||||
images: [{
|
||||
service: "QCHAT_IMAGE",
|
||||
name: '123456789123456789123456789',
|
||||
identifier: '123456'
|
||||
}],
|
||||
repliedTo: '',
|
||||
version: 1
|
||||
};
|
||||
} else {
|
||||
messageObject = {
|
||||
messageText: trimmedMessage,
|
||||
images: [''],
|
||||
repliedTo: '',
|
||||
version: 1
|
||||
};
|
||||
}
|
||||
|
||||
const stringified = JSON.stringify(messageObject);
|
||||
const size = new Blob([stringified]).size;
|
||||
this.chatMessageSize = size;
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
calculateIFrameHeight(height) {
|
||||
setTimeout(()=> {
|
||||
const editorTest = this.shadowRoot.getElementById(this.iframeId).contentWindow.document.getElementById('chatbarId').scrollHeight;
|
||||
this.iframeHeight = editorTest + 20;
|
||||
}, 50)
|
||||
}
|
||||
resetIFrameHeight(height) {
|
||||
this.iframeHeight = 42;
|
||||
}
|
||||
initChatEditor() {
|
||||
const ChatEditor = function (editorConfig) {
|
||||
const ChatEditor = function () {
|
||||
const editor = this;
|
||||
editor.init();
|
||||
};
|
||||
|
||||
ChatEditor.prototype.getValue = function () {
|
||||
const editor = this;
|
||||
|
||||
if (editor.contentDiv) {
|
||||
return editor.contentDiv.innerHTML;
|
||||
}
|
||||
};
|
||||
|
||||
ChatEditor.prototype.setValue = function (value) {
|
||||
const editor = this;
|
||||
|
||||
if (value) {
|
||||
editor.contentDiv.innerHTML = value;
|
||||
editor.updateMirror();
|
||||
}
|
||||
|
||||
editor.focus();
|
||||
};
|
||||
|
||||
ChatEditor.prototype.resetValue = function () {
|
||||
const editor = this;
|
||||
editor.contentDiv.innerHTML = '';
|
||||
editor.updateMirror();
|
||||
editor.focus();
|
||||
editorConfig.resetIFrameHeight()
|
||||
};
|
||||
|
||||
ChatEditor.prototype.styles = function () {
|
||||
const editor = this;
|
||||
|
||||
editor.styles = document.createElement('style');
|
||||
editor.styles.setAttribute('type', 'text/css');
|
||||
editor.styles.innerText = `
|
||||
html {
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.chatbar-body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.chatbar-body::-webkit-scrollbar-track {
|
||||
background-color: whitesmoke;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
.chatbar-body::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
border-radius: 7px;
|
||||
background-color: whitesmoke;
|
||||
}
|
||||
|
||||
.chatbar-body::-webkit-scrollbar-thumb {
|
||||
background-color: rgb(180, 176, 176);
|
||||
border-radius: 7px;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.chatbar-body::-webkit-scrollbar-thumb:hover {
|
||||
background-color: rgb(148, 146, 146);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div {
|
||||
font-size: 1rem;
|
||||
line-height: 1.38rem;
|
||||
font-weight: 400;
|
||||
font-family: "Open Sans", helvetica, sans-serif;
|
||||
padding-right: 3px;
|
||||
text-align: left;
|
||||
white-space: break-spaces;
|
||||
word-break: break-word;
|
||||
outline: none;
|
||||
min-height: 20px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div[contentEditable=true]:empty:before {
|
||||
content: attr(data-placeholder);
|
||||
display: block;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
white-space: nowrap;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
div[contentEditable=false]{
|
||||
background: rgba(0,0,0,0.1);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
img.emoji {
|
||||
width: 1.7em;
|
||||
height: 1.5em;
|
||||
margin-bottom: -2px;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
`;
|
||||
editor.content.head.appendChild(editor.styles);
|
||||
};
|
||||
|
||||
ChatEditor.prototype.enable = function () {
|
||||
const editor = this;
|
||||
|
||||
editor.contentDiv.setAttribute('contenteditable', 'true');
|
||||
editor.focus();
|
||||
};
|
||||
|
||||
ChatEditor.prototype.getMirrorElement = function (){
|
||||
return editor.mirror
|
||||
}
|
||||
|
||||
ChatEditor.prototype.disable = function () {
|
||||
const editor = this;
|
||||
|
||||
editor.contentDiv.setAttribute('contenteditable', 'false');
|
||||
};
|
||||
|
||||
ChatEditor.prototype.state = function () {
|
||||
const editor = this;
|
||||
|
||||
return editor.contentDiv.getAttribute('contenteditable');
|
||||
};
|
||||
|
||||
ChatEditor.prototype.focus = function () {
|
||||
const editor = this;
|
||||
|
||||
editor.contentDiv.focus();
|
||||
};
|
||||
|
||||
ChatEditor.prototype.clearSelection = function () {
|
||||
const editor = this;
|
||||
|
||||
let selection = editor.content.getSelection().toString();
|
||||
if (!/^\s*$/.test(selection)) editor.content.getSelection().removeAllRanges();
|
||||
};
|
||||
|
||||
ChatEditor.prototype.insertEmoji = function (emojiImg) {
|
||||
const editor = this;
|
||||
|
||||
const doInsert = () => {
|
||||
|
||||
if (editor.content.queryCommandSupported("InsertHTML")) {
|
||||
editor.content.execCommand("insertHTML", false, emojiImg);
|
||||
editor.updateMirror();
|
||||
}
|
||||
};
|
||||
|
||||
editor.focus();
|
||||
return doInsert();
|
||||
};
|
||||
|
||||
ChatEditor.prototype.insertText = function (text) {
|
||||
const editor = this;
|
||||
|
||||
const parsedText = editorConfig.emojiPicker.parse(text);
|
||||
const doPaste = () => {
|
||||
|
||||
if (editor.content.queryCommandSupported("InsertHTML")) {
|
||||
editor.content.execCommand("insertHTML", false, parsedText);
|
||||
editor.updateMirror();
|
||||
}
|
||||
};
|
||||
|
||||
editor.focus();
|
||||
return doPaste();
|
||||
};
|
||||
|
||||
ChatEditor.prototype.updateMirror = function () {
|
||||
const editor = this;
|
||||
|
||||
const chatInputValue = editor.getValue();
|
||||
const filteredValue = chatInputValue.replace(/<img.*?alt=".*?/g, '').replace(/".?src=.*?>/g, '');
|
||||
|
||||
let unescapedValue = editorConfig.unescape(filteredValue);
|
||||
editor.mirror.value = unescapedValue;
|
||||
};
|
||||
|
||||
ChatEditor.prototype.listenChanges = function () {
|
||||
|
||||
const editor = this;
|
||||
|
||||
const events = ['drop', 'contextmenu', 'mouseup', 'click', 'touchend', 'keydown', 'blur', 'paste']
|
||||
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
const event = events[i]
|
||||
editor.content.body.addEventListener(event, async function (e) {
|
||||
|
||||
if (e.type === 'click') {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
if (e.type === 'paste') {
|
||||
e.preventDefault();
|
||||
const item_list = await navigator.clipboard.read();
|
||||
let image_type; // we will feed this later
|
||||
const item = item_list.find( item => // choose the one item holding our image
|
||||
item.types.some( type => {
|
||||
if (type.startsWith( 'image/')) {
|
||||
image_type = type;
|
||||
return true;
|
||||
}
|
||||
})
|
||||
);
|
||||
if(item){
|
||||
const blob = item && await item.getType( image_type );
|
||||
var file = new File([blob], "name", {
|
||||
type: image_type
|
||||
});
|
||||
|
||||
editorConfig.insertImage(file)
|
||||
} else {
|
||||
navigator.clipboard.readText()
|
||||
.then(clipboardText => {
|
||||
let escapedText = editorConfig.escape(clipboardText);
|
||||
editor.insertText(escapedText);
|
||||
})
|
||||
.then(() => {
|
||||
editorConfig.getMessageSize(editorConfig.editableElement.contentDocument.body.querySelector("#chatbarId").innerHTML);
|
||||
})
|
||||
.catch(err => {
|
||||
// Fallback if everything fails...
|
||||
let textData = (e.originalEvent || e).clipboardData.getData('text/plain');
|
||||
editor.insertText(textData);
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e.type === 'contextmenu') {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e.type === 'keydown') {
|
||||
await new Promise((res, rej) => {
|
||||
setTimeout(() => {
|
||||
editorConfig.calculateIFrameHeight(editorConfig.editableElement.contentDocument.body.scrollHeight);
|
||||
editorConfig.getMessageSize(editorConfig.editableElement.contentDocument.body.querySelector("#chatbarId").innerHTML);
|
||||
}, 0);
|
||||
res();
|
||||
})
|
||||
|
||||
// Handle Enter
|
||||
if (e.keyCode === 13 && !e.shiftKey) {
|
||||
|
||||
|
||||
if (editor.state() === 'false') return false;
|
||||
if (editorConfig.iframeId === 'newChat') {
|
||||
editorConfig.sendFunc(
|
||||
{
|
||||
type: 'image',
|
||||
imageFile: editorConfig.imageFile,
|
||||
}
|
||||
);
|
||||
} else {
|
||||
editorConfig.sendFunc();
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle Commands with CTR or CMD
|
||||
if (e.ctrlKey || e.metaKey) {
|
||||
switch (e.keyCode) {
|
||||
case 66:
|
||||
case 98: e.preventDefault();
|
||||
return false;
|
||||
case 73:
|
||||
case 105: e.preventDefault();
|
||||
return false;
|
||||
case 85:
|
||||
case 117: e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (e.type === 'blur') {
|
||||
editor.clearSelection();
|
||||
}
|
||||
|
||||
if (e.type === 'drop') {
|
||||
e.preventDefault();
|
||||
|
||||
let droppedText = e.dataTransfer.getData('text/plain')
|
||||
let escapedText = editorConfig.escape(droppedText)
|
||||
|
||||
editor.insertText(escapedText);
|
||||
return false;
|
||||
}
|
||||
|
||||
editor.updateMirror();
|
||||
});
|
||||
}
|
||||
|
||||
editor.content.addEventListener('click', function (event) {
|
||||
event.preventDefault();
|
||||
editor.focus();
|
||||
});
|
||||
};
|
||||
|
||||
ChatEditor.prototype.remove = function () {
|
||||
const editor = this;
|
||||
var old_element = editor.content.body;
|
||||
var new_element = old_element.cloneNode(true);
|
||||
editor.content.body.parentNode.replaceChild(new_element, old_element);
|
||||
while (editor.content.body.firstChild) {
|
||||
editor.content.body.removeChild(editor.content.body.lastChild);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
ChatEditor.prototype.init = function () {
|
||||
const editor = this;
|
||||
|
||||
editor.frame = editorConfig.editableElement;
|
||||
editor.mirror = editorConfig.mirrorElement;
|
||||
|
||||
editor.content = (editor.frame.contentDocument || editor.frame.document);
|
||||
editor.content.body.classList.add("chatbar-body");
|
||||
|
||||
let elemDiv = document.createElement('div');
|
||||
elemDiv.setAttribute('contenteditable', 'true');
|
||||
elemDiv.setAttribute('spellcheck', 'false');
|
||||
elemDiv.setAttribute('data-placeholder', editorConfig.placeholder);
|
||||
elemDiv.style.cssText = `width:100%; ${editorConfig.theme === "dark" ? "color:#ffffff;" : "color: #080808"}`;
|
||||
elemDiv.id = 'chatbarId';
|
||||
editor.content.body.appendChild(elemDiv);
|
||||
editor.contentDiv = editor.frame.contentDocument.body.firstChild;
|
||||
editor.styles();
|
||||
editor.listenChanges();
|
||||
|
||||
};
|
||||
|
||||
|
||||
function doInit() {
|
||||
return new ChatEditor();
|
||||
}
|
||||
return doInit();
|
||||
};
|
||||
|
||||
const editorConfig = {
|
||||
getMessageSize: this.getMessageSize,
|
||||
calculateIFrameHeight: this.calculateIFrameHeight,
|
||||
mirrorElement: this.mirrorChatInput,
|
||||
editableElement: this.chatMessageInput,
|
||||
sendFunc: this.sendMessageFunc,
|
||||
emojiPicker: this.emojiPicker,
|
||||
escape: escape,
|
||||
unescape: unescape,
|
||||
placeholder: this.placeholder,
|
||||
imageFile: this.imageFile,
|
||||
requestUpdate: this.requestUpdate,
|
||||
insertImage: this.insertImage,
|
||||
chatMessageSize: this.chatMessageSize,
|
||||
addGlobalEventListener: this.addGlobalEventListener,
|
||||
removeGlobalEventListener: this.removeGlobalEventListener,
|
||||
iframeId: this.iframeId,
|
||||
theme: this.theme,
|
||||
resetIFrameHeight: this.resetIFrameHeight
|
||||
};
|
||||
const newChat = new ChatEditor(editorConfig);
|
||||
this.setChatEditor(newChat);
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define("chat-text-editor", ChatTextEditor)
|
@ -4,6 +4,10 @@ import { escape, unescape } from 'html-escaper';
|
||||
import { EmojiPicker } from 'emoji-picker-js';
|
||||
import { inputKeyCodes } from '../../utils/keyCodes.js';
|
||||
import { Epml } from '../../../epml.js';
|
||||
import { Editor } from '@tiptap/core'
|
||||
import StarterKit from '@tiptap/starter-kit'
|
||||
import Underline from '@tiptap/extension-underline';
|
||||
import Image from '@tiptap/extension-image'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent });
|
||||
class ChatTextEditor extends LitElement {
|
||||
@ -17,12 +21,12 @@ class ChatTextEditor extends LitElement {
|
||||
insertImage: { attribute: false },
|
||||
iframeHeight: { type: Number },
|
||||
editedMessageObj: { type: Object },
|
||||
chatEditor: { type: Object },
|
||||
setChatEditor: { attribute: false },
|
||||
iframeId: { type: String },
|
||||
hasGlobalEvents: { type: Boolean },
|
||||
chatMessageSize: { type: Number },
|
||||
isEditMessageOpen: { type: Boolean },
|
||||
editor: {type: Object},
|
||||
theme: {
|
||||
type: String,
|
||||
reflect: true
|
||||
@ -39,8 +43,8 @@ class ChatTextEditor extends LitElement {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: auto;
|
||||
overflow-y: hidden;
|
||||
width: 100%;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
.chatbar-container {
|
||||
width: 100%;
|
||||
@ -63,6 +67,7 @@ class ChatTextEditor extends LitElement {
|
||||
cursor: pointer;
|
||||
max-height: 40px;
|
||||
color: var(--black);
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.message-size-container {
|
||||
@ -101,6 +106,7 @@ class ChatTextEditor extends LitElement {
|
||||
position: relative;
|
||||
height: 25px;
|
||||
width: 25px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.file-picker-input-container {
|
||||
@ -141,6 +147,129 @@ class ChatTextEditor extends LitElement {
|
||||
.checkmark-icon:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.element {
|
||||
width: 100%;
|
||||
max-height: 100%;
|
||||
overflow: auto;
|
||||
color: var(--black);
|
||||
padding: 0px 10px;
|
||||
}
|
||||
.element::-webkit-scrollbar-track {
|
||||
background-color: whitesmoke;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
.element::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
border-radius: 7px;
|
||||
background-color: whitesmoke;
|
||||
}
|
||||
|
||||
.element::-webkit-scrollbar-thumb {
|
||||
background-color: rgb(180, 176, 176);
|
||||
border-radius: 7px;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.element::-webkit-scrollbar-thumb:hover {
|
||||
background-color: rgb(148, 146, 146);
|
||||
cursor: pointer;
|
||||
}
|
||||
.ProseMirror:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.is-active {
|
||||
background-color: var(--white)
|
||||
}
|
||||
|
||||
.ProseMirror > * + * {
|
||||
margin-top: 0.75em;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.ProseMirror ul,
|
||||
ol {
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
.ProseMirror h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.ProseMirror code {
|
||||
background-color: rgba(#616161, 0.1);
|
||||
color: #616161;
|
||||
}
|
||||
|
||||
.ProseMirror pre {
|
||||
background: #0D0D0D;
|
||||
color: #FFF;
|
||||
font-family: 'JetBrainsMono', monospace;
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
.ProseMirror pre code {
|
||||
color: inherit;
|
||||
padding: 0;
|
||||
background: none;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
|
||||
.ProseMirror img {
|
||||
width: 1.7em;
|
||||
height: 1.5em;
|
||||
margin: 0px;
|
||||
|
||||
}
|
||||
|
||||
.ProseMirror blockquote {
|
||||
padding-left: 1rem;
|
||||
border-left: 2px solid rgba(#0D0D0D, 0.1);
|
||||
}
|
||||
|
||||
.ProseMirror hr {
|
||||
border: none;
|
||||
border-top: 2px solid rgba(#0D0D0D, 0.1);
|
||||
margin: 2rem 0;
|
||||
}
|
||||
.chatbar-button-single {
|
||||
background: var(--white);
|
||||
outline: none;
|
||||
border: none;
|
||||
color: var(--black);
|
||||
padding: 4px 8px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
margin-right: 2px;
|
||||
filter: brightness(100%);
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.chatbar-button-single:hover {
|
||||
filter: brightness(120%);
|
||||
}
|
||||
.chatbar-buttons {
|
||||
visibility: hidden;
|
||||
transition: all .2s;
|
||||
}
|
||||
.chatbar-container:hover .chatbar-buttons {
|
||||
visibility: visible;
|
||||
}
|
||||
.ProseMirror p.is-editor-empty:first-child::before {
|
||||
color: #adb5bd;
|
||||
content: attr(data-placeholder);
|
||||
float: left;
|
||||
height: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
`
|
||||
}
|
||||
|
||||
@ -159,21 +288,68 @@ class ChatTextEditor extends LitElement {
|
||||
this.chatMessageSize = 0
|
||||
this.userName = window.parent.reduxStore.getState().app.accountInfo.names[0]
|
||||
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
|
||||
this.editor = null
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log('this.editor', this.editor)
|
||||
let scrollHeightBool = false;
|
||||
try {
|
||||
if (this.chatMessageInput && this.chatMessageInput.contentDocument.body.scrollHeight > 60 && this.shadowRoot.querySelector(".chat-editor").contentDocument.body.querySelector("#chatbarId").innerHTML.trim() !== "") {
|
||||
console.log('this.chatMessageInput', this.chatMessageInput)
|
||||
if (this.chatMessageInput && this.chatMessageInput.scrollHeight > 60) {
|
||||
scrollHeightBool = true;
|
||||
}
|
||||
} catch (error) {
|
||||
scrollHeightBool = false;
|
||||
}
|
||||
return html`
|
||||
|
||||
<div
|
||||
class=${["chatbar-container", (this.iframeId === "newChat" || this.iframeId === "privateMessage") ? "chatbar-caption" : ""].join(" ")}
|
||||
style="${scrollHeightBool ? 'align-items: flex-end' : "align-items: center"}">
|
||||
style="align-items: flex-end; position: relative">
|
||||
<div
|
||||
class=${["chatbar-container", "chatbar-buttons"].join(" ")}
|
||||
style="align-items: center; position:absolute; top: -20px">
|
||||
<button
|
||||
@click=${() => this.editor.chain().focus().toggleBold().run()}
|
||||
?disabled=${
|
||||
this.editor &&
|
||||
!this.editor.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleBold()
|
||||
.run()
|
||||
}
|
||||
class=${["chatbar-button-single",this.editor && this.editor.isActive('bold') ? 'is-active' : ''].join(" ")}
|
||||
>
|
||||
bold
|
||||
</button>
|
||||
<button
|
||||
@click=${() => this.editor.chain().focus().toggleItalic().run()}
|
||||
?disabled=${ this.editor &&
|
||||
!this.editor.can()
|
||||
.chain()
|
||||
.focus()
|
||||
.toggleItalic()
|
||||
.run()
|
||||
}
|
||||
class=${["chatbar-button-single",this.editor && this.editor.isActive('italic') ? 'is-active' : ''].join(' ')}
|
||||
>
|
||||
italic
|
||||
</button>
|
||||
<button
|
||||
@click=${() => this.editor.chain().focus().toggleCodeBlock().run()}
|
||||
class=${["chatbar-button-single",this.editor && this.editor.isActive('codeBlock') ? 'is-active' : ''].join(' ')}
|
||||
>
|
||||
code block
|
||||
</button>
|
||||
<button
|
||||
@click=${() => this.editor.chain().focus().toggleUnderline().run()}
|
||||
class=${["chatbar-button-single", this.editor && this.editor.isActive('underline') ? 'is-active' : ''].join(' ')}
|
||||
>
|
||||
underline
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
style=${this.iframeId === "privateMessage" ? "display: none" : "display: block"}
|
||||
class="file-picker-container"
|
||||
@ -201,13 +377,14 @@ class ChatTextEditor extends LitElement {
|
||||
</div>
|
||||
</div>
|
||||
<textarea style="color: var(--black);" tabindex='1' ?autofocus=${true} ?disabled=${this.isLoading || this.isLoadingMessages} id="messageBox" rows="1"></textarea>
|
||||
<iframe style=${(this.iframeId === "newChat" && this.iframeHeight > 42) && "height: 100%;"} id=${this.iframeId} class="chat-editor" tabindex="-1" height=${this.iframeHeight}></iframe>
|
||||
<!-- <iframe style=${(this.iframeId === "newChat" && this.iframeHeight > 42) && "height: 100%;"} id=${this.iframeId} class="chat-editor" tabindex="-1" height=${this.iframeHeight}></iframe> -->
|
||||
<div id=${this.iframeId} class="element"></div>
|
||||
<button class="emoji-button" ?disabled=${this.isLoading || this.isLoadingMessages}>
|
||||
${html`<img class="emoji" draggable="false" alt="😀" src="/emoji/svg/1f600.svg" />`}
|
||||
</button>
|
||||
${this.editedMessageObj ? (
|
||||
html`
|
||||
<div>
|
||||
<div style="margin-bottom: 10px">
|
||||
${this.isLoading === false ? html`
|
||||
<vaadin-icon
|
||||
class="checkmark-icon"
|
||||
@ -227,9 +404,7 @@ class ChatTextEditor extends LitElement {
|
||||
) :
|
||||
html`
|
||||
<div
|
||||
style="${scrollHeightBool
|
||||
? 'margin-bottom: 5px;'
|
||||
: "margin-bottom: 0;"}
|
||||
style="margin-bottom: 10px;
|
||||
${this.iframeId === 'newChat'
|
||||
? 'display: none;'
|
||||
: 'display: flex;'}">
|
||||
@ -271,17 +446,17 @@ class ChatTextEditor extends LitElement {
|
||||
}
|
||||
|
||||
initialChat(e) {
|
||||
if (!this.chatEditor?.contentDiv.matches(':focus')) {
|
||||
// WARNING: Deprecated methods from KeyBoard Event
|
||||
if (e.code === "Space" || e.keyCode === 32 || e.which === 32) {
|
||||
this.chatEditor.insertText(' ');
|
||||
} else if (inputKeyCodes.includes(e.keyCode)) {
|
||||
this.chatEditor.insertText(e.key);
|
||||
return this.chatEditor.focus();
|
||||
} else {
|
||||
return this.chatEditor.focus();
|
||||
}
|
||||
}
|
||||
// if (!this.chatEditor?.contentDiv.matches(':focus')) {
|
||||
// // WARNING: Deprecated methods from KeyBoard Event
|
||||
// if (e.code === "Space" || e.keyCode === 32 || e.which === 32) {
|
||||
// this.chatEditor.insertText(' ');
|
||||
// } else if (inputKeyCodes.includes(e.keyCode)) {
|
||||
// this.chatEditor.insertText(e.key);
|
||||
// return this.chatEditor.focus();
|
||||
// } else {
|
||||
// return this.chatEditor.focus();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
addGlobalEventListener(){
|
||||
@ -294,24 +469,38 @@ class ChatTextEditor extends LitElement {
|
||||
|
||||
async firstUpdated() {
|
||||
if (this.hasGlobalEvents) {
|
||||
this.addGlobalEventListener();
|
||||
// this.addGlobalEventListener();
|
||||
}
|
||||
Image.configure({
|
||||
inline: true,
|
||||
})
|
||||
// this.editor = new Editor({
|
||||
// element: this.shadowRoot.querySelector('.element'),
|
||||
// extensions: [
|
||||
// StarterKit,
|
||||
// Underline,
|
||||
// Image
|
||||
// ],
|
||||
// content: '<p>Hello World!</p>',
|
||||
// })
|
||||
|
||||
window.addEventListener('storage', () => {
|
||||
const checkTheme = localStorage.getItem('qortalTheme');
|
||||
const chatbar = this.shadowRoot.getElementById(this.iframeId).contentWindow.document.getElementById('chatbarId');
|
||||
const chatbar = this.shadowRoot.querySelector('.element')
|
||||
if (checkTheme === 'dark') {
|
||||
this.theme = 'dark';
|
||||
chatbar.style.cssText = "color:#ffffff;"
|
||||
|
||||
} else {
|
||||
this.theme = 'light';
|
||||
chatbar.style.cssText = "color:#080808;"
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
this.emojiPickerHandler = this.shadowRoot.querySelector('.emoji-button');
|
||||
this.mirrorChatInput = this.shadowRoot.getElementById('messageBox');
|
||||
this.chatMessageInput = this.shadowRoot.getElementById(this.iframeId);
|
||||
this.chatMessageInput = this.shadowRoot.querySelector('.element')
|
||||
|
||||
this.emojiPicker = new EmojiPicker({
|
||||
style: "twemoji",
|
||||
@ -327,29 +516,32 @@ class ChatTextEditor extends LitElement {
|
||||
|
||||
this.emojiPicker.on('emoji', selection => {
|
||||
const emojiHtmlString = `<img class="emoji" draggable="false" alt="${selection.emoji}" src="${selection.url}">`;
|
||||
this.chatEditor.insertEmoji(emojiHtmlString);
|
||||
console.log('hello insert 6', selection)
|
||||
this.editor.commands.insertContent(selection.emoji, {
|
||||
parseOptions: {
|
||||
preserveWhitespace: false
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
this.emojiPickerHandler.addEventListener('click', () => this.emojiPicker.togglePicker(this.emojiPickerHandler));
|
||||
|
||||
await this.updateComplete;
|
||||
this.initChatEditor();
|
||||
// this.initChatEditor();
|
||||
}
|
||||
|
||||
async updated(changedProperties) {
|
||||
if (changedProperties && changedProperties.has('editedMessageObj')) {
|
||||
if (this.editedMessageObj) {
|
||||
this.chatEditor.insertText(this.editedMessageObj.message);
|
||||
this.editor.commands.setContent(this.editedMessageObj.message)
|
||||
this.getMessageSize(this.editedMessageObj.message);
|
||||
} else {
|
||||
this.chatEditor.insertText("");
|
||||
this.chatMessageSize = 0;
|
||||
}
|
||||
}
|
||||
if (changedProperties && changedProperties.has('placeholder')) {
|
||||
const captionEditor = this.shadowRoot.getElementById(this.iframeId).contentWindow.document.getElementById('chatbarId');
|
||||
captionEditor.setAttribute('data-placeholder', this.placeholder);
|
||||
this.updatePlaceholder(this.editor, this.placeholder )
|
||||
}
|
||||
|
||||
if (changedProperties && changedProperties.has("imageFile")) {
|
||||
@ -364,13 +556,12 @@ class ChatTextEditor extends LitElement {
|
||||
}
|
||||
|
||||
sendMessageFunc(props) {
|
||||
if (this.chatMessageSize > 1000 ) {
|
||||
parentEpml.request('showSnackBar', get("chatpage.cchange29"));
|
||||
return;
|
||||
};
|
||||
this.chatMessageSize = 0;
|
||||
this.chatEditor.updateMirror();
|
||||
this._sendMessage(props);
|
||||
// if (this.chatMessageSize > 1000 ) {
|
||||
// parentEpml.request('showSnackBar', get("chatpage.cchange29"));
|
||||
// return;
|
||||
// };
|
||||
// this.chatMessageSize = 0;
|
||||
this._sendMessage(props, this.editor.getJSON());
|
||||
}
|
||||
|
||||
getMessageSize(message){
|
||||
@ -442,387 +633,7 @@ class ChatTextEditor extends LitElement {
|
||||
resetIFrameHeight(height) {
|
||||
this.iframeHeight = 42;
|
||||
}
|
||||
initChatEditor() {
|
||||
const ChatEditor = function (editorConfig) {
|
||||
const ChatEditor = function () {
|
||||
const editor = this;
|
||||
editor.init();
|
||||
};
|
||||
|
||||
ChatEditor.prototype.getValue = function () {
|
||||
const editor = this;
|
||||
|
||||
if (editor.contentDiv) {
|
||||
return editor.contentDiv.innerHTML;
|
||||
}
|
||||
};
|
||||
|
||||
ChatEditor.prototype.setValue = function (value) {
|
||||
const editor = this;
|
||||
|
||||
if (value) {
|
||||
editor.contentDiv.innerHTML = value;
|
||||
editor.updateMirror();
|
||||
}
|
||||
|
||||
editor.focus();
|
||||
};
|
||||
|
||||
ChatEditor.prototype.resetValue = function () {
|
||||
const editor = this;
|
||||
editor.contentDiv.innerHTML = '';
|
||||
editor.updateMirror();
|
||||
editor.focus();
|
||||
editorConfig.resetIFrameHeight()
|
||||
};
|
||||
|
||||
ChatEditor.prototype.styles = function () {
|
||||
const editor = this;
|
||||
|
||||
editor.styles = document.createElement('style');
|
||||
editor.styles.setAttribute('type', 'text/css');
|
||||
editor.styles.innerText = `
|
||||
html {
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.chatbar-body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.chatbar-body::-webkit-scrollbar-track {
|
||||
background-color: whitesmoke;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
.chatbar-body::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
border-radius: 7px;
|
||||
background-color: whitesmoke;
|
||||
}
|
||||
|
||||
.chatbar-body::-webkit-scrollbar-thumb {
|
||||
background-color: rgb(180, 176, 176);
|
||||
border-radius: 7px;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.chatbar-body::-webkit-scrollbar-thumb:hover {
|
||||
background-color: rgb(148, 146, 146);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div {
|
||||
font-size: 1rem;
|
||||
line-height: 1.38rem;
|
||||
font-weight: 400;
|
||||
font-family: "Open Sans", helvetica, sans-serif;
|
||||
padding-right: 3px;
|
||||
text-align: left;
|
||||
white-space: break-spaces;
|
||||
word-break: break-word;
|
||||
outline: none;
|
||||
min-height: 20px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div[contentEditable=true]:empty:before {
|
||||
content: attr(data-placeholder);
|
||||
display: block;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
white-space: nowrap;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
div[contentEditable=false]{
|
||||
background: rgba(0,0,0,0.1);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
img.emoji {
|
||||
width: 1.7em;
|
||||
height: 1.5em;
|
||||
margin-bottom: -2px;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
`;
|
||||
editor.content.head.appendChild(editor.styles);
|
||||
};
|
||||
|
||||
ChatEditor.prototype.enable = function () {
|
||||
const editor = this;
|
||||
|
||||
editor.contentDiv.setAttribute('contenteditable', 'true');
|
||||
editor.focus();
|
||||
};
|
||||
|
||||
ChatEditor.prototype.getMirrorElement = function (){
|
||||
return editor.mirror
|
||||
}
|
||||
|
||||
ChatEditor.prototype.disable = function () {
|
||||
const editor = this;
|
||||
|
||||
editor.contentDiv.setAttribute('contenteditable', 'false');
|
||||
};
|
||||
|
||||
ChatEditor.prototype.state = function () {
|
||||
const editor = this;
|
||||
|
||||
return editor.contentDiv.getAttribute('contenteditable');
|
||||
};
|
||||
|
||||
ChatEditor.prototype.focus = function () {
|
||||
const editor = this;
|
||||
|
||||
editor.contentDiv.focus();
|
||||
};
|
||||
|
||||
ChatEditor.prototype.clearSelection = function () {
|
||||
const editor = this;
|
||||
|
||||
let selection = editor.content.getSelection().toString();
|
||||
if (!/^\s*$/.test(selection)) editor.content.getSelection().removeAllRanges();
|
||||
};
|
||||
|
||||
ChatEditor.prototype.insertEmoji = function (emojiImg) {
|
||||
const editor = this;
|
||||
|
||||
const doInsert = () => {
|
||||
|
||||
if (editor.content.queryCommandSupported("InsertHTML")) {
|
||||
editor.content.execCommand("insertHTML", false, emojiImg);
|
||||
editor.updateMirror();
|
||||
}
|
||||
};
|
||||
|
||||
editor.focus();
|
||||
return doInsert();
|
||||
};
|
||||
|
||||
ChatEditor.prototype.insertText = function (text) {
|
||||
const editor = this;
|
||||
|
||||
const parsedText = editorConfig.emojiPicker.parse(text);
|
||||
const doPaste = () => {
|
||||
|
||||
if (editor.content.queryCommandSupported("InsertHTML")) {
|
||||
editor.content.execCommand("insertHTML", false, parsedText);
|
||||
editor.updateMirror();
|
||||
}
|
||||
};
|
||||
|
||||
editor.focus();
|
||||
return doPaste();
|
||||
};
|
||||
|
||||
ChatEditor.prototype.updateMirror = function () {
|
||||
const editor = this;
|
||||
|
||||
const chatInputValue = editor.getValue();
|
||||
const filteredValue = chatInputValue.replace(/<img.*?alt=".*?/g, '').replace(/".?src=.*?>/g, '');
|
||||
|
||||
let unescapedValue = editorConfig.unescape(filteredValue);
|
||||
editor.mirror.value = unescapedValue;
|
||||
};
|
||||
|
||||
ChatEditor.prototype.listenChanges = function () {
|
||||
|
||||
const editor = this;
|
||||
|
||||
const events = ['drop', 'contextmenu', 'mouseup', 'click', 'touchend', 'keydown', 'blur', 'paste']
|
||||
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
const event = events[i]
|
||||
editor.content.body.addEventListener(event, async function (e) {
|
||||
|
||||
if (e.type === 'click') {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
if (e.type === 'paste') {
|
||||
e.preventDefault();
|
||||
const item_list = await navigator.clipboard.read();
|
||||
let image_type; // we will feed this later
|
||||
const item = item_list.find( item => // choose the one item holding our image
|
||||
item.types.some( type => {
|
||||
if (type.startsWith( 'image/')) {
|
||||
image_type = type;
|
||||
return true;
|
||||
}
|
||||
})
|
||||
);
|
||||
if(item){
|
||||
const blob = item && await item.getType( image_type );
|
||||
var file = new File([blob], "name", {
|
||||
type: image_type
|
||||
});
|
||||
|
||||
editorConfig.insertImage(file)
|
||||
} else {
|
||||
navigator.clipboard.readText()
|
||||
.then(clipboardText => {
|
||||
let escapedText = editorConfig.escape(clipboardText);
|
||||
editor.insertText(escapedText);
|
||||
})
|
||||
.then(() => {
|
||||
editorConfig.getMessageSize(editorConfig.editableElement.contentDocument.body.querySelector("#chatbarId").innerHTML);
|
||||
})
|
||||
.catch(err => {
|
||||
// Fallback if everything fails...
|
||||
let textData = (e.originalEvent || e).clipboardData.getData('text/plain');
|
||||
editor.insertText(textData);
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e.type === 'contextmenu') {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e.type === 'keydown') {
|
||||
await new Promise((res, rej) => {
|
||||
setTimeout(() => {
|
||||
editorConfig.calculateIFrameHeight(editorConfig.editableElement.contentDocument.body.scrollHeight);
|
||||
editorConfig.getMessageSize(editorConfig.editableElement.contentDocument.body.querySelector("#chatbarId").innerHTML);
|
||||
}, 0);
|
||||
res();
|
||||
})
|
||||
|
||||
// Handle Enter
|
||||
if (e.keyCode === 13 && !e.shiftKey) {
|
||||
|
||||
|
||||
if (editor.state() === 'false') return false;
|
||||
if (editorConfig.iframeId === 'newChat') {
|
||||
editorConfig.sendFunc(
|
||||
{
|
||||
type: 'image',
|
||||
imageFile: editorConfig.imageFile,
|
||||
}
|
||||
);
|
||||
} else {
|
||||
editorConfig.sendFunc();
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle Commands with CTR or CMD
|
||||
if (e.ctrlKey || e.metaKey) {
|
||||
switch (e.keyCode) {
|
||||
case 66:
|
||||
case 98: e.preventDefault();
|
||||
return false;
|
||||
case 73:
|
||||
case 105: e.preventDefault();
|
||||
return false;
|
||||
case 85:
|
||||
case 117: e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (e.type === 'blur') {
|
||||
editor.clearSelection();
|
||||
}
|
||||
|
||||
if (e.type === 'drop') {
|
||||
e.preventDefault();
|
||||
|
||||
let droppedText = e.dataTransfer.getData('text/plain')
|
||||
let escapedText = editorConfig.escape(droppedText)
|
||||
|
||||
editor.insertText(escapedText);
|
||||
return false;
|
||||
}
|
||||
|
||||
editor.updateMirror();
|
||||
});
|
||||
}
|
||||
|
||||
editor.content.addEventListener('click', function (event) {
|
||||
event.preventDefault();
|
||||
editor.focus();
|
||||
});
|
||||
};
|
||||
|
||||
ChatEditor.prototype.remove = function () {
|
||||
const editor = this;
|
||||
var old_element = editor.content.body;
|
||||
var new_element = old_element.cloneNode(true);
|
||||
editor.content.body.parentNode.replaceChild(new_element, old_element);
|
||||
while (editor.content.body.firstChild) {
|
||||
editor.content.body.removeChild(editor.content.body.lastChild);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
ChatEditor.prototype.init = function () {
|
||||
const editor = this;
|
||||
|
||||
editor.frame = editorConfig.editableElement;
|
||||
editor.mirror = editorConfig.mirrorElement;
|
||||
|
||||
editor.content = (editor.frame.contentDocument || editor.frame.document);
|
||||
editor.content.body.classList.add("chatbar-body");
|
||||
|
||||
let elemDiv = document.createElement('div');
|
||||
elemDiv.setAttribute('contenteditable', 'true');
|
||||
elemDiv.setAttribute('spellcheck', 'false');
|
||||
elemDiv.setAttribute('data-placeholder', editorConfig.placeholder);
|
||||
elemDiv.style.cssText = `width:100%; ${editorConfig.theme === "dark" ? "color:#ffffff;" : "color: #080808"}`;
|
||||
elemDiv.id = 'chatbarId';
|
||||
editor.content.body.appendChild(elemDiv);
|
||||
editor.contentDiv = editor.frame.contentDocument.body.firstChild;
|
||||
editor.styles();
|
||||
editor.listenChanges();
|
||||
|
||||
};
|
||||
|
||||
|
||||
function doInit() {
|
||||
return new ChatEditor();
|
||||
}
|
||||
return doInit();
|
||||
};
|
||||
|
||||
const editorConfig = {
|
||||
getMessageSize: this.getMessageSize,
|
||||
calculateIFrameHeight: this.calculateIFrameHeight,
|
||||
mirrorElement: this.mirrorChatInput,
|
||||
editableElement: this.chatMessageInput,
|
||||
sendFunc: this.sendMessageFunc,
|
||||
emojiPicker: this.emojiPicker,
|
||||
escape: escape,
|
||||
unescape: unescape,
|
||||
placeholder: this.placeholder,
|
||||
imageFile: this.imageFile,
|
||||
requestUpdate: this.requestUpdate,
|
||||
insertImage: this.insertImage,
|
||||
chatMessageSize: this.chatMessageSize,
|
||||
addGlobalEventListener: this.addGlobalEventListener,
|
||||
removeGlobalEventListener: this.removeGlobalEventListener,
|
||||
iframeId: this.iframeId,
|
||||
theme: this.theme,
|
||||
resetIFrameHeight: this.resetIFrameHeight
|
||||
};
|
||||
const newChat = new ChatEditor(editorConfig);
|
||||
this.setChatEditor(newChat);
|
||||
}
|
||||
}
|
||||
|
||||
window.customElements.define("chat-text-editor", ChatTextEditor)
|
||||
|
@ -22,6 +22,10 @@ import '@material/mwc-dialog'
|
||||
import '@material/mwc-icon'
|
||||
import '@material/mwc-snackbar'
|
||||
import '@vaadin/grid'
|
||||
import StarterKit from '@tiptap/starter-kit'
|
||||
import Underline from '@tiptap/extension-underline';
|
||||
import Placeholder from '@tiptap/extension-placeholder'
|
||||
import { Editor, Extension } from '@tiptap/core'
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
@ -47,7 +51,8 @@ class Chat extends LitElement {
|
||||
openPrivateMessage: { type: Boolean },
|
||||
userFound: { type: Array},
|
||||
userFoundModalOpen: { type: Boolean },
|
||||
userSelected: { type: Object }
|
||||
userSelected: { type: Object },
|
||||
editor: {type: Object}
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,6 +99,66 @@ class Chat extends LitElement {
|
||||
this.activeChatHeadUrl = url
|
||||
}
|
||||
|
||||
resetChatEditor(){
|
||||
|
||||
this.editor.commands.setContent('')
|
||||
|
||||
}
|
||||
async getUpdateCompleteTextEditor() {
|
||||
await super.getUpdateComplete();
|
||||
const marginElements = Array.from(this.shadowRoot.querySelectorAll('chat-text-editor'));
|
||||
await Promise.all(marginElements.map(el => el.updateComplete));
|
||||
const marginElements2 = Array.from(this.shadowRoot.querySelectorAll('wrapper-modal'));
|
||||
await Promise.all(marginElements2.map(el => el.updateComplete));
|
||||
return true;
|
||||
}
|
||||
|
||||
async connectedCallback() {
|
||||
super.connectedCallback();
|
||||
await this.getUpdateCompleteTextEditor();
|
||||
|
||||
const elementChatId = this.shadowRoot.getElementById('messageBox').shadowRoot.getElementById('privateMessage')
|
||||
console.log({elementChatId})
|
||||
this.editor = new Editor({
|
||||
element: elementChatId,
|
||||
extensions: [
|
||||
StarterKit,
|
||||
Underline,
|
||||
Placeholder.configure({
|
||||
placeholder: 'Write something …',
|
||||
}),
|
||||
Extension.create({
|
||||
addKeyboardShortcuts:()=> {
|
||||
return {
|
||||
'Enter': ()=> {
|
||||
const chatTextEditor = this.shadowRoot.getElementById('messageBox')
|
||||
chatTextEditor.sendMessageFunc({
|
||||
})
|
||||
return true
|
||||
}
|
||||
}
|
||||
}})
|
||||
]
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
this.editor.destroy()
|
||||
|
||||
}
|
||||
|
||||
updatePlaceholder(editor, text){
|
||||
editor.extensionManager.extensions.forEach((extension) => {
|
||||
if (extension.name === "placeholder") {
|
||||
|
||||
extension.options["placeholder"] = text
|
||||
editor.commands.focus('end')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div class="container clearfix">
|
||||
@ -127,13 +192,13 @@ class Chat extends LitElement {
|
||||
<!-- Start Chatting Dialog -->
|
||||
<wrapper-modal
|
||||
.onClickFunc=${() => {
|
||||
this.chatEditor.resetValue();
|
||||
this.resetChatEditor();
|
||||
this.openPrivateMessage = false;
|
||||
this.shadowRoot.getElementById('sendTo').value = "";
|
||||
this.userFoundModalOpen = false;
|
||||
this.userFound = [];
|
||||
} }
|
||||
style=${this.openPrivateMessage ? "display: block" : "display: none"}>
|
||||
style=${this.openPrivateMessage ? "visibility:visible;z-index:50" : "visibility: hidden;z-index:-100;position: relative"}>
|
||||
<div style=${"position: relative"}>
|
||||
<div class="dialog-container">
|
||||
<div class="dialog-header" style="text-align: center">
|
||||
@ -177,21 +242,21 @@ class Chat extends LitElement {
|
||||
iframeId="privateMessage"
|
||||
?hasGlobalEvents=${false}
|
||||
placeholder="${translate("chatpage.cchange8")}"
|
||||
.setChatEditor=${(editor)=> this.setChatEditor(editor)}
|
||||
.chatEditor=${this.chatEditor}
|
||||
.imageFile=${this.imageFile}
|
||||
._sendMessage=${this._sendMessage}
|
||||
.insertImage=${this.insertImage}
|
||||
?isLoading=${this.isLoading}
|
||||
.isLoadingMessages=${false}
|
||||
id="messageBox"
|
||||
.editor=${this.editor}
|
||||
.updatePlaceholder=${(editor, value)=> this.updatePlaceholder(editor, value)}
|
||||
>
|
||||
</chat-text-editor>
|
||||
<div class="modal-button-row">
|
||||
<button
|
||||
class="modal-button-red"
|
||||
@click=${() => {
|
||||
this.chatEditor.resetValue();
|
||||
this.resetChatEditor();
|
||||
this.openPrivateMessage = false;
|
||||
}}
|
||||
?disabled="${this.isLoading}"
|
||||
@ -201,8 +266,10 @@ class Chat extends LitElement {
|
||||
<button
|
||||
class="modal-button"
|
||||
@click=${()=> {
|
||||
this.chatEditor.updateMirror()
|
||||
this._sendMessage()
|
||||
const chatTextEditor = this.shadowRoot.getElementById('messageBox')
|
||||
chatTextEditor.sendMessageFunc({
|
||||
})
|
||||
|
||||
|
||||
}}
|
||||
?disabled="${this.isLoading}">
|
||||
@ -439,26 +506,22 @@ class Chat extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
setChatEditor(editor) {
|
||||
this.chatEditor = editor;
|
||||
}
|
||||
|
||||
async _sendMessage() {
|
||||
|
||||
async _sendMessage(outSideMsg, msg) {
|
||||
this.isLoading = true;
|
||||
this.chatEditor.disable();
|
||||
const messageText = this.chatEditor.mirror.value;
|
||||
// Format and Sanitize Message
|
||||
const sanitizedMessage = messageText.replace(/ /gi, ' ').replace(/<br\s*[\/]?>/gi, '\n');
|
||||
const trimmedMessage = sanitizedMessage.trim();
|
||||
// this.chatEditor.disable();
|
||||
|
||||
const trimmedMessage = msg
|
||||
if (/^\s*$/.test(trimmedMessage)) {
|
||||
this.isLoading = false;
|
||||
this.chatEditor.enable();
|
||||
// this.chatEditor.enable();
|
||||
} else {
|
||||
const messageObject = {
|
||||
messageText: trimmedMessage,
|
||||
images: [''],
|
||||
repliedTo: '',
|
||||
version: 1
|
||||
version: 2
|
||||
}
|
||||
const stringifyMessageObject = JSON.stringify(messageObject)
|
||||
this.sendMessage(stringifyMessageObject);
|
||||
@ -510,7 +573,7 @@ class Chat extends LitElement {
|
||||
_publicKey = false;
|
||||
let err4string = get("chatpage.cchange19");
|
||||
parentEpml.request('showSnackBar', `${err4string}`);
|
||||
this.chatEditor.enable();
|
||||
// this.chatEditor.enable();
|
||||
this.isLoading = false;
|
||||
} else if (addressPublicKey !== false) {
|
||||
isEncrypted = 1;
|
||||
@ -519,7 +582,7 @@ class Chat extends LitElement {
|
||||
} else {
|
||||
let err4string = get("chatpage.cchange39");
|
||||
parentEpml.request('showSnackBar', `${err4string}`);
|
||||
this.chatEditor.enable();
|
||||
// this.chatEditor.enable();
|
||||
this.isLoading = false;
|
||||
}
|
||||
};
|
||||
@ -576,7 +639,7 @@ class Chat extends LitElement {
|
||||
this.setActiveChatHeadUrl(`direct/${recipient}`);
|
||||
this.shadowRoot.getElementById('sendTo').value = "";
|
||||
this.openPrivateMessage = false;
|
||||
this.chatEditor.resetValue();
|
||||
this.resetChatEditor();
|
||||
} else if (response.error) {
|
||||
parentEpml.request('showSnackBar', response.message);
|
||||
} else {
|
||||
@ -585,7 +648,7 @@ class Chat extends LitElement {
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
this.chatEditor.enable();
|
||||
// this.chatEditor.enable();
|
||||
};
|
||||
|
||||
// Exec..
|
||||
@ -596,7 +659,7 @@ class Chat extends LitElement {
|
||||
insertImage(file) {
|
||||
if (file.type.includes('image')) {
|
||||
this.imageFile = file;
|
||||
this.chatEditor.disable();
|
||||
// this.chatEditor.disable();
|
||||
return;
|
||||
}
|
||||
parentEpml.request('showSnackBar', get("chatpage.cchange28"));
|
||||
|
Loading…
x
Reference in New Issue
Block a user