start group chat components
This commit is contained in:
parent
7639c8b211
commit
b986f1ae58
@ -0,0 +1,46 @@
|
||||
'use strict';
|
||||
import TransactionBase from '../TransactionBase.js'
|
||||
import Base58 from '../../deps/Base58.js'
|
||||
import { store } from '../../../api.js'
|
||||
import { QORT_DECIMALS } from "../../constants.js"
|
||||
|
||||
export default class AddGroupAdminTransaction extends TransactionBase {
|
||||
constructor() {
|
||||
super()
|
||||
this.type = 24
|
||||
}
|
||||
|
||||
render(html) {
|
||||
const conf = store.getState().config
|
||||
return html`
|
||||
Are you sure to update this group ?
|
||||
<div style="background: #eee; padding: 8px; margin: 8px 0; border-radius: 5px;">
|
||||
|
||||
</div>
|
||||
On pressing confirm, the group details will be updated!
|
||||
`
|
||||
}
|
||||
|
||||
|
||||
set fee(fee) {
|
||||
this._fee = fee * QORT_DECIMALS
|
||||
this._feeBytes = this.constructor.utils.int64ToBytes(this._fee)
|
||||
}
|
||||
set member(member) {
|
||||
this._member = member instanceof Uint8Array ? member : this.constructor.Base58.decode(member)
|
||||
}
|
||||
|
||||
set _groupId(_groupId){
|
||||
this._groupBytes = this.constructor.utils.int32ToBytes(_groupId)
|
||||
}
|
||||
get params() {
|
||||
const params = super.params
|
||||
params.push(
|
||||
this._groupBytes,
|
||||
this._member,
|
||||
this._feeBytes
|
||||
)
|
||||
console.log('verify params', params)
|
||||
return params
|
||||
}
|
||||
}
|
@ -58,6 +58,7 @@ export default class LeaveGroupTransaction extends TransactionBase {
|
||||
this._rGroupIdBytes,
|
||||
this._feeBytes
|
||||
)
|
||||
console.log('check exec params2', params)
|
||||
return params;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,46 @@
|
||||
'use strict';
|
||||
import TransactionBase from '../TransactionBase.js'
|
||||
import Base58 from '../../deps/Base58.js'
|
||||
import { store } from '../../../api.js'
|
||||
import { QORT_DECIMALS } from "../../constants.js"
|
||||
|
||||
export default class RemoveGroupAdminTransaction extends TransactionBase {
|
||||
constructor() {
|
||||
super()
|
||||
this.type = 25
|
||||
}
|
||||
|
||||
render(html) {
|
||||
const conf = store.getState().config
|
||||
return html`
|
||||
Are you sure to update this group ?
|
||||
<div style="background: #eee; padding: 8px; margin: 8px 0; border-radius: 5px;">
|
||||
|
||||
</div>
|
||||
On pressing confirm, the group details will be updated
|
||||
`
|
||||
}
|
||||
|
||||
|
||||
set fee(fee) {
|
||||
this._fee = fee * QORT_DECIMALS
|
||||
this._feeBytes = this.constructor.utils.int64ToBytes(this._fee)
|
||||
}
|
||||
set member(member) {
|
||||
this._member = member instanceof Uint8Array ? member : this.constructor.Base58.decode(member)
|
||||
}
|
||||
|
||||
set _groupId(_groupId){
|
||||
this._groupBytes = this.constructor.utils.int32ToBytes(_groupId)
|
||||
}
|
||||
get params() {
|
||||
const params = super.params
|
||||
params.push(
|
||||
this._groupBytes,
|
||||
this._member,
|
||||
this._feeBytes
|
||||
)
|
||||
console.log('verify params', params)
|
||||
return params
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
'use strict';
|
||||
import TransactionBase from '../TransactionBase.js'
|
||||
import Base58 from '../../deps/Base58.js'
|
||||
import { store } from '../../../api.js'
|
||||
import { QORT_DECIMALS } from "../../constants.js"
|
||||
|
||||
export default class UpdateGroupTransaction extends TransactionBase {
|
||||
constructor() {
|
||||
super()
|
||||
this.type = 23
|
||||
}
|
||||
|
||||
render(html) {
|
||||
const conf = store.getState().config
|
||||
return html`
|
||||
Are you sure to update this group ?
|
||||
<div style="background: #eee; padding: 8px; margin: 8px 0; border-radius: 5px;">
|
||||
|
||||
</div>
|
||||
On pressing confirm, the group details will be updated!
|
||||
`
|
||||
}
|
||||
|
||||
|
||||
set fee(fee) {
|
||||
this._fee = fee * QORT_DECIMALS
|
||||
this._feeBytes = this.constructor.utils.int64ToBytes(this._fee)
|
||||
}
|
||||
set newOwner(newOwner) {
|
||||
this._newOwner = newOwner instanceof Uint8Array ? newOwner : this.constructor.Base58.decode(newOwner)
|
||||
}
|
||||
set newIsOpen(newIsOpen) {
|
||||
|
||||
this._rGroupType = new Uint8Array(1)
|
||||
this._rGroupType[0] = newIsOpen
|
||||
}
|
||||
set newDescription(newDescription) {
|
||||
this._rGroupDescBytes = this.constructor.utils.stringtoUTF8Array(newDescription.toLocaleLowerCase())
|
||||
this._rGroupDescLength = this.constructor.utils.int32ToBytes(this._rGroupDescBytes.length)
|
||||
}
|
||||
set newApprovalThreshold(newApprovalThreshold) {
|
||||
this._rGroupApprovalThreshold = new Uint8Array(1)
|
||||
this._rGroupApprovalThreshold[0] = newApprovalThreshold;
|
||||
}
|
||||
set newMinimumBlockDelay(newMinimumBlockDelay) {
|
||||
this._rGroupMinimumBlockDelayBytes = this.constructor.utils.int32ToBytes(newMinimumBlockDelay)
|
||||
}
|
||||
set newMaximumBlockDelay(newMaximumBlockDelay) {
|
||||
|
||||
this._rGroupMaximumBlockDelayBytes = this.constructor.utils.int32ToBytes(newMaximumBlockDelay)
|
||||
}
|
||||
|
||||
set _groupId(_groupId){
|
||||
this._groupBytes = this.constructor.utils.int32ToBytes(_groupId)
|
||||
}
|
||||
get params() {
|
||||
const params = super.params
|
||||
params.push(
|
||||
this._groupBytes,
|
||||
this._newOwner,
|
||||
this._rGroupDescLength,
|
||||
this._rGroupDescBytes,
|
||||
this._rGroupType,
|
||||
this._rGroupApprovalThreshold,
|
||||
this._rGroupMinimumBlockDelayBytes,
|
||||
this._rGroupMaximumBlockDelayBytes,
|
||||
this._feeBytes
|
||||
)
|
||||
console.log('verify params', params)
|
||||
return params
|
||||
}
|
||||
}
|
@ -7,8 +7,11 @@ import RewardShareTransaction from './reward-share/RewardShareTransaction.js'
|
||||
import RemoveRewardShareTransaction from './reward-share/RemoveRewardShareTransaction.js'
|
||||
import CreateGroupTransaction from './groups/CreateGroupTransaction.js';
|
||||
import JoinGroupTransaction from './groups/JoinGroupTransaction.js'
|
||||
import UpdateGroupTransaction from './groups/UpdateGroupTransaction.js'
|
||||
import LeaveGroupTransaction from './groups/LeaveGroupTransaction.js'
|
||||
import PublicizeTransaction from './PublicizeTransaction.js'
|
||||
import AddGroupAdminTransaction from './groups/AddGroupAdminTransaction.js'
|
||||
import RemoveGroupAdminTransaction from './groups/RemoveGroupAdminTransaction.js'
|
||||
|
||||
export const transactionTypes = {
|
||||
2: PaymentTransaction,
|
||||
@ -18,6 +21,9 @@ export const transactionTypes = {
|
||||
181: GroupChatTransaction,
|
||||
19: PublicizeTransaction,
|
||||
22: CreateGroupTransaction,
|
||||
23: UpdateGroupTransaction,
|
||||
24: AddGroupAdminTransaction,
|
||||
25: RemoveGroupAdminTransaction,
|
||||
31: JoinGroupTransaction,
|
||||
32: LeaveGroupTransaction,
|
||||
38: RewardShareTransaction,
|
||||
|
@ -54,6 +54,9 @@
|
||||
"@vaadin/button": "23.2.5",
|
||||
"@vaadin/grid": "23.2.5",
|
||||
"@vaadin/icons": "23.2.5",
|
||||
"@vaadin/tabs": "23.2.5",
|
||||
"@vaadin/avatar": "23.2.5",
|
||||
"@vaadin/horizontal-layout": "23.2.5",
|
||||
"epml": "0.3.3",
|
||||
"file-saver": "2.0.5",
|
||||
"html-escaper": "3.0.3",
|
||||
|
335
qortal-ui-plugins/plugins/core/components/ChatGroupInvites.js
Normal file
335
qortal-ui-plugins/plugins/core/components/ChatGroupInvites.js
Normal file
@ -0,0 +1,335 @@
|
||||
import { LitElement, html, css } from "lit"
|
||||
import { render } from "lit/html.js"
|
||||
import { get, translate } from "lit-translate"
|
||||
import { Epml } from "../../../epml"
|
||||
import snackbar from "./snackbar.js"
|
||||
import "@material/mwc-button"
|
||||
import "@material/mwc-dialog"
|
||||
import "@polymer/paper-spinner/paper-spinner-lite.js"
|
||||
import "@material/mwc-icon"
|
||||
import "./WrapperModal"
|
||||
|
||||
const parentEpml = new Epml({ type: "WINDOW", source: window.parent })
|
||||
|
||||
class ChatGroupInvites extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
isLoading: { type: Boolean },
|
||||
isOpenLeaveModal: { type: Boolean },
|
||||
leaveGroupObj: { type: Object },
|
||||
error: { type: Boolean },
|
||||
message: { type: String },
|
||||
chatHeads: { type: Array },
|
||||
groupAdmin: { attribute: false },
|
||||
groupMembers: { attribute: false },
|
||||
selectedHead: { type: Object },
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
this.isLoading = false
|
||||
this.isOpenLeaveModal = false
|
||||
this.leaveGroupObj = {}
|
||||
this.leaveFee = 0.001
|
||||
this.error = false
|
||||
this.message = ""
|
||||
this.chatHeads = []
|
||||
this.groupAdmin = []
|
||||
this.groupMembers = []
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return css`
|
||||
.top-bar-icon {
|
||||
cursor: pointer;
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
transition: 0.2s all;
|
||||
}
|
||||
.top-bar-icon:hover {
|
||||
color: var(--black);
|
||||
}
|
||||
.modal-button {
|
||||
font-family: Roboto, sans-serif;
|
||||
font-size: 16px;
|
||||
color: var(--mdc-theme-primary);
|
||||
background-color: transparent;
|
||||
padding: 8px 10px;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
firstUpdated() {}
|
||||
|
||||
timeIsoString(timestamp) {
|
||||
let myTimestamp = timestamp === undefined ? 1587560082346 : timestamp
|
||||
let time = new Date(myTimestamp)
|
||||
return time.toISOString()
|
||||
}
|
||||
|
||||
resetDefaultSettings() {
|
||||
this.error = false
|
||||
this.message = ""
|
||||
this.isLoading = false
|
||||
}
|
||||
|
||||
renderErr9Text() {
|
||||
return html`${translate("grouppage.gchange49")}`
|
||||
}
|
||||
|
||||
async confirmRelationship(reference) {
|
||||
let interval = null
|
||||
let stop = false
|
||||
const getAnswer = async () => {
|
||||
|
||||
|
||||
if (!stop) {
|
||||
stop = true
|
||||
try {
|
||||
let myRef = await parentEpml.request("apiCall", {
|
||||
type: "api",
|
||||
url: `/transactions/reference/${reference}`,
|
||||
})
|
||||
if (myRef && myRef.type) {
|
||||
clearInterval(interval)
|
||||
this.isLoading = false
|
||||
this.isOpenLeaveModal = false
|
||||
}
|
||||
} catch (error) {}
|
||||
stop = false
|
||||
}
|
||||
}
|
||||
interval = setInterval(getAnswer, 5000)
|
||||
}
|
||||
|
||||
async getLastRef() {
|
||||
let myRef = await parentEpml.request("apiCall", {
|
||||
type: "api",
|
||||
url: `/addresses/lastreference/${this.selectedAddress.address}`,
|
||||
})
|
||||
return myRef
|
||||
}
|
||||
|
||||
getTxnRequestResponse(txnResponse, reference) {
|
||||
if (txnResponse === true) {
|
||||
this.message = this.renderErr9Text()
|
||||
this.error = false
|
||||
this.confirmRelationship(reference)
|
||||
} else {
|
||||
this.error = true
|
||||
this.message = ""
|
||||
throw new Error(txnResponse)
|
||||
}
|
||||
}
|
||||
|
||||
async convertBytesForSigning(transactionBytesBase58) {
|
||||
let convertedBytes = await parentEpml.request("apiCall", {
|
||||
type: "api",
|
||||
method: "POST",
|
||||
url: `/transactions/convert`,
|
||||
body: `${transactionBytesBase58}`,
|
||||
})
|
||||
return convertedBytes
|
||||
}
|
||||
|
||||
async signTx(body){
|
||||
return await parentEpml.request("apiCall", {
|
||||
type: "api",
|
||||
method: "POST",
|
||||
url: `/transactions/sign`,
|
||||
body: body,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async process(body){
|
||||
return await parentEpml.request("apiCall", {
|
||||
type: "api",
|
||||
method: "POST",
|
||||
url: `/transactions/process`,
|
||||
body: body,
|
||||
})
|
||||
}
|
||||
async _addAdmin(groupId) {
|
||||
// Reset Default Settings...
|
||||
this.resetDefaultSettings()
|
||||
const leaveFeeInput = this.leaveFee
|
||||
|
||||
this.isLoading = true
|
||||
|
||||
// Get Last Ref
|
||||
|
||||
const validateReceiver = async () => {
|
||||
let lastRef = await this.getLastRef()
|
||||
let myTransaction = await makeTransactionRequest(lastRef)
|
||||
this.getTxnRequestResponse(myTransaction, lastRef )
|
||||
}
|
||||
|
||||
// Make Transaction Request
|
||||
const makeTransactionRequest = async (lastRef) => {
|
||||
const body = {
|
||||
timestamp: Date.now(),
|
||||
reference: lastRef,
|
||||
fee: leaveFeeInput,
|
||||
ownerPublicKey: window.parent.Base58.encode(
|
||||
window.parent.reduxStore.getState().app.selectedAddress
|
||||
.keyPair.publicKey
|
||||
),
|
||||
groupId: groupId,
|
||||
member: this.selectedHead.address,
|
||||
}
|
||||
const bodyToString = JSON.stringify(body)
|
||||
let transactionBytes = await parentEpml.request("apiCall", {
|
||||
type: "api",
|
||||
method: "POST",
|
||||
url: `/groups/addadmin`,
|
||||
body: bodyToString,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
})
|
||||
const readforsign = await this.convertBytesForSigning(
|
||||
transactionBytes
|
||||
)
|
||||
const body2 = {
|
||||
privateKey: window.parent.Base58.encode(
|
||||
window.parent.reduxStore.getState().app.selectedAddress
|
||||
.keyPair.privateKey
|
||||
),
|
||||
transactionBytes: readforsign,
|
||||
}
|
||||
const bodyToString2 = JSON.stringify(body2)
|
||||
let signTransaction = await this.signTx(bodyToString2)
|
||||
let processTransaction = await this.process(signTransaction)
|
||||
return processTransaction
|
||||
}
|
||||
|
||||
validateReceiver()
|
||||
}
|
||||
|
||||
async _removeAdmin(groupId) {
|
||||
// Reset Default Settings...
|
||||
this.resetDefaultSettings()
|
||||
const leaveFeeInput = this.leaveFee
|
||||
|
||||
this.isLoading = true
|
||||
|
||||
// Get Last Ref
|
||||
|
||||
const validateReceiver = async () => {
|
||||
let lastRef = await this.getLastRef()
|
||||
let myTransaction = await makeTransactionRequest(lastRef)
|
||||
this.getTxnRequestResponse(myTransaction, lastRef)
|
||||
}
|
||||
|
||||
// Make Transaction Request
|
||||
const makeTransactionRequest = async (lastRef) => {
|
||||
const body = {
|
||||
timestamp: Date.now(),
|
||||
reference: lastRef,
|
||||
fee: leaveFeeInput,
|
||||
ownerPublicKey: window.parent.Base58.encode(
|
||||
window.parent.reduxStore.getState().app.selectedAddress
|
||||
.keyPair.publicKey
|
||||
),
|
||||
groupId: groupId,
|
||||
admin: this.selectedHead.address,
|
||||
}
|
||||
const bodyToString = JSON.stringify(body)
|
||||
let transactionBytes = await parentEpml.request("apiCall", {
|
||||
type: "api",
|
||||
method: "POST",
|
||||
url: `/groups/removeadmin`,
|
||||
body: bodyToString,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
})
|
||||
const readforsign = await this.convertBytesForSigning(
|
||||
transactionBytes
|
||||
)
|
||||
const body2 = {
|
||||
privateKey: window.parent.Base58.encode(
|
||||
window.parent.reduxStore.getState().app.selectedAddress
|
||||
.keyPair.privateKey
|
||||
),
|
||||
transactionBytes: readforsign,
|
||||
}
|
||||
const bodyToString2 = JSON.stringify(body2)
|
||||
let signTransaction = await this.signTx(bodyToString2)
|
||||
let processTransaction = await this.process(signTransaction)
|
||||
return processTransaction
|
||||
}
|
||||
|
||||
validateReceiver()
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log("leaveGroupObj", this.leaveGroupObj)
|
||||
return html`
|
||||
<vaadin-icon @click=${()=> {
|
||||
this.isOpenLeaveModal = true
|
||||
}} class="top-bar-icon" style="margin: 0px 20px" icon="vaadin:users" slot="icon"></vaadin-icon>
|
||||
|
||||
<wrapper-modal
|
||||
.removeImage=${() => {
|
||||
if (this.isLoading) return
|
||||
this.isOpenLeaveModal = false
|
||||
}}
|
||||
style=${
|
||||
this.isOpenLeaveModal ? "display: block" : "display: none"
|
||||
}>
|
||||
<div style="text-align:center">
|
||||
<h1>${translate("grouppage.gchange35")}</h1>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<button @click=${() =>
|
||||
this._addAdmin(
|
||||
this.leaveGroupObj.groupId
|
||||
)}>Promote to Admin</button>
|
||||
<button @click=${() =>
|
||||
this._removeAdmin(
|
||||
this.leaveGroupObj.groupId
|
||||
)}>Remove as Admin</button>
|
||||
<div style="text-align:right; height:36px;">
|
||||
<span ?hidden="${!this.isLoading}">
|
||||
<!-- loading message -->
|
||||
${translate("grouppage.gchange36")}
|
||||
<paper-spinner-lite
|
||||
style="margin-top:12px;"
|
||||
?active="${this.isLoading}"
|
||||
alt="Leaving"
|
||||
>
|
||||
</paper-spinner-lite>
|
||||
</span>
|
||||
<span ?hidden=${this.message === ""} style="${
|
||||
this.error ? "color:red;" : ""
|
||||
}">
|
||||
${this.message}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
<button
|
||||
@click=${() => {
|
||||
this.isOpenLeaveModal = false
|
||||
}}
|
||||
class="modal-button"
|
||||
?disabled="${this.isLoading}"
|
||||
|
||||
>
|
||||
${translate("general.close")}
|
||||
</button>
|
||||
</wrapper-modal >
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("chat-right-panel", ChatGroupInvites)
|
281
qortal-ui-plugins/plugins/core/components/ChatGroupSettings.js
Normal file
281
qortal-ui-plugins/plugins/core/components/ChatGroupSettings.js
Normal file
@ -0,0 +1,281 @@
|
||||
import { LitElement, html, css } from 'lit';
|
||||
import { render } from 'lit/html.js';
|
||||
import { get, translate } from 'lit-translate';
|
||||
import { Epml } from '../../../epml';
|
||||
import snackbar from './snackbar.js'
|
||||
import '@material/mwc-button';
|
||||
import '@material/mwc-dialog';
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js'
|
||||
import '@material/mwc-icon';
|
||||
import './WrapperModal';
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
class ChatGroupSettings extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
isLoading: { type: Boolean },
|
||||
isOpenLeaveModal: {type: Boolean},
|
||||
leaveGroupObj: { type: Object },
|
||||
error: {type: Boolean},
|
||||
message: {type: String},
|
||||
chatHeads: {type: Array},
|
||||
setActiveChatHeadUrl: {attribute: false}
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.isLoading = false;
|
||||
this.isOpenLeaveModal = false
|
||||
this.leaveGroupObj = {}
|
||||
this.leaveFee = 0.001
|
||||
this.error = false
|
||||
this.message = ''
|
||||
this.chatHeads = []
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return css`
|
||||
.top-bar-icon {
|
||||
cursor: pointer;
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
transition: .2s all;
|
||||
}
|
||||
.top-bar-icon:hover {
|
||||
color: var(--black)
|
||||
}
|
||||
.modal-button {
|
||||
font-family: Roboto, sans-serif;
|
||||
font-size: 16px;
|
||||
color: var(--mdc-theme-primary);
|
||||
background-color: transparent;
|
||||
padding: 8px 10px;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
|
||||
}
|
||||
|
||||
timeIsoString(timestamp) {
|
||||
let myTimestamp = timestamp === undefined ? 1587560082346 : timestamp
|
||||
let time = new Date(myTimestamp)
|
||||
return time.toISOString()
|
||||
}
|
||||
|
||||
resetDefaultSettings() {
|
||||
this.error = false
|
||||
this.message = ''
|
||||
this.isLoading = false
|
||||
}
|
||||
|
||||
renderErr9Text() {
|
||||
return html`${translate("grouppage.gchange49")}`
|
||||
}
|
||||
|
||||
async confirmRelationship() {
|
||||
|
||||
|
||||
let interval = null
|
||||
let stop = false
|
||||
const getAnswer = async () => {
|
||||
const currentChats = this.chatHeads
|
||||
|
||||
if (!stop) {
|
||||
stop = true;
|
||||
try {
|
||||
const findGroup = currentChats.find((item)=> item.groupId === this.leaveGroupObj.groupId)
|
||||
if (!findGroup) {
|
||||
clearInterval(interval)
|
||||
this.isLoading = false
|
||||
this.isOpenLeaveModal= false
|
||||
this.setActiveChatHeadUrl('')
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
}
|
||||
stop = false
|
||||
}
|
||||
};
|
||||
interval = setInterval(getAnswer, 5000);
|
||||
}
|
||||
|
||||
async _convertToPrivate(groupId) {
|
||||
// Reset Default Settings...
|
||||
this.resetDefaultSettings()
|
||||
const leaveFeeInput = this.leaveFee
|
||||
|
||||
this.isLoading = true
|
||||
|
||||
// Get Last Ref
|
||||
const getLastRef = async () => {
|
||||
let myRef = await parentEpml.request('apiCall', {
|
||||
type: 'api',
|
||||
url: `/addresses/lastreference/${this.selectedAddress.address}`
|
||||
})
|
||||
return myRef
|
||||
};
|
||||
|
||||
const validateReceiver = async () => {
|
||||
let lastRef = await getLastRef();
|
||||
let myTransaction = await makeTransactionRequest(lastRef)
|
||||
getTxnRequestResponse(myTransaction)
|
||||
|
||||
}
|
||||
const convertBytesForSigning = async (transactionBytesBase58) => {
|
||||
let convertedBytes = await parentEpml.request("apiCall", {
|
||||
type: "api",
|
||||
method: "POST",
|
||||
url: `/transactions/convert`,
|
||||
body: `${transactionBytesBase58}`,
|
||||
})
|
||||
return convertedBytes
|
||||
}
|
||||
|
||||
|
||||
// Make Transaction Request
|
||||
const makeTransactionRequest = async (lastRef) => {
|
||||
let groupdialog3 = get("transactions.groupdialog3")
|
||||
let groupdialog4 = get("transactions.groupdialog4")
|
||||
|
||||
const body = {
|
||||
"timestamp": Date.now(),
|
||||
"reference": lastRef,
|
||||
"fee": leaveFeeInput,
|
||||
"ownerPublicKey": window.parent.Base58.encode(window.parent.reduxStore.getState().app.selectedAddress.keyPair.publicKey),
|
||||
"groupId": groupId,
|
||||
"newOwner": "QdR4bQ1fJFnSZgswtW27eE8ToXwHqUQyaU",
|
||||
"newIsOpen": false,
|
||||
"newDescription": "my group for accounts I like",
|
||||
"newApprovalThreshold": "NONE",
|
||||
"newMinimumBlockDelay": 5,
|
||||
"newMaximumBlockDelay": 60
|
||||
}
|
||||
console.log('STRING3')
|
||||
// const bodyToString = JSON.stringify(body)
|
||||
// let transactionBytes = await parentEpml.request("apiCall", {
|
||||
// type: "api",
|
||||
// method: "POST",
|
||||
// url: `/groups/update`,
|
||||
// body: bodyToString,
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/json'
|
||||
// }
|
||||
// })
|
||||
// console.log({transactionBytes})
|
||||
// const readforsign = await convertBytesForSigning(transactionBytes)
|
||||
// // const res = await signAndProcess(transactionBytes)
|
||||
// const body2 = {
|
||||
// "privateKey": window.parent.Base58.encode(window.parent.reduxStore.getState().app.selectedAddress.keyPair.privateKey),
|
||||
// "transactionBytes": readforsign
|
||||
// }
|
||||
// const bodyToString2 = JSON.stringify(body2)
|
||||
// let signTransaction = await parentEpml.request("apiCall", {
|
||||
// type: "api",
|
||||
// method: "POST",
|
||||
// url: `/transactions/sign`,
|
||||
// body: bodyToString2,
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/json'
|
||||
// }
|
||||
// })
|
||||
// let processTransaction = await parentEpml.request("apiCall", {
|
||||
// type: "api",
|
||||
// method: "POST",
|
||||
// url: `/transactions/process`,
|
||||
// body: signTransaction,
|
||||
// })
|
||||
// return processTransaction
|
||||
console.log('this.selectedAddress.nonce', this.selectedAddress.nonce)
|
||||
let myTxnrequest = await parentEpml.request('transaction', {
|
||||
type: 23,
|
||||
nonce: this.selectedAddress.nonce,
|
||||
params: {
|
||||
_groupId: groupId,
|
||||
lastReference: lastRef,
|
||||
fee: leaveFeeInput,
|
||||
"newOwner": "QdR4bQ1fJFnSZgswtW27eE8ToXwHqUQyaU",
|
||||
"newIsOpen": false,
|
||||
"newDescription": "my group for accounts I like",
|
||||
"newApprovalThreshold": "NONE",
|
||||
"newMinimumBlockDelay": 5,
|
||||
"newMaximumBlockDelay": 60
|
||||
}
|
||||
})
|
||||
return myTxnrequest
|
||||
}
|
||||
|
||||
const getTxnRequestResponse = (txnResponse) => {
|
||||
|
||||
if (txnResponse === true) {
|
||||
this.message = this.renderErr9Text()
|
||||
this.error = false
|
||||
this.confirmRelationship()
|
||||
} else {
|
||||
this.error = true
|
||||
this.message = ""
|
||||
throw new Error(txnResponse)
|
||||
}
|
||||
}
|
||||
validateReceiver()
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log('leaveGroupObj', this.leaveGroupObj)
|
||||
return html`
|
||||
<vaadin-icon @click=${()=> {
|
||||
this.isOpenLeaveModal = true
|
||||
}} class="top-bar-icon" style="margin: 0px 20px" icon="vaadin:cog" slot="icon"></vaadin-icon>
|
||||
<!-- Leave Group Dialog -->
|
||||
<wrapper-modal
|
||||
.removeImage=${() => {
|
||||
if(this.isLoading) return
|
||||
this.isOpenLeaveModal = false
|
||||
} }
|
||||
style=${(this.isOpenLeaveModal) ? "display: block" : "display: none"}>
|
||||
<div style="text-align:center">
|
||||
<h1>${translate("grouppage.gchange35")}</h1>
|
||||
<hr>
|
||||
</div>
|
||||
<
|
||||
<button @click=${() => this._convertToPrivate(this.leaveGroupObj.groupId, this.leaveGroupObj.groupName)}> Convert a public group to private</button>
|
||||
|
||||
<div style="text-align:right; height:36px;">
|
||||
<span ?hidden="${!this.isLoading}">
|
||||
<!-- loading message -->
|
||||
${translate("grouppage.gchange36")}
|
||||
<paper-spinner-lite
|
||||
style="margin-top:12px;"
|
||||
?active="${this.isLoading}"
|
||||
alt="Leaving"
|
||||
>
|
||||
</paper-spinner-lite>
|
||||
</span>
|
||||
<span ?hidden=${this.message === ''} style="${this.error ? 'color:red;' : ''}">
|
||||
${this.message}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
<button
|
||||
@click=${() => {
|
||||
this.isOpenLeaveModal= false
|
||||
}}
|
||||
class="modal-button"
|
||||
?disabled="${this.isLoading}"
|
||||
|
||||
>
|
||||
${translate("general.close")}
|
||||
</button>
|
||||
</wrapper-modal >
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('chat-group-settings', ChatGroupSettings);
|
@ -0,0 +1,296 @@
|
||||
import { LitElement, html, css } from 'lit';
|
||||
import { render } from 'lit/html.js';
|
||||
import { get, translate } from 'lit-translate';
|
||||
import { Epml } from '../../../epml';
|
||||
import snackbar from './snackbar.js'
|
||||
import '@material/mwc-button';
|
||||
import '@material/mwc-dialog';
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js'
|
||||
import '@material/mwc-icon';
|
||||
import './WrapperModal';
|
||||
import '@vaadin/tabs'
|
||||
import '@vaadin/tabs/theme/material/vaadin-tabs.js';
|
||||
import '@vaadin/avatar';
|
||||
import '@vaadin/grid';
|
||||
import '@vaadin/grid/vaadin-grid-filter-column.js';
|
||||
import { columnBodyRenderer } from '@vaadin/grid/lit.js';
|
||||
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
class ChatGroupsManagement extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
isLoading: { type: Boolean },
|
||||
isOpenLeaveModal: {type: Boolean},
|
||||
leaveGroupObj: { type: Object },
|
||||
error: {type: Boolean},
|
||||
message: {type: String},
|
||||
chatHeads: {type: Array},
|
||||
setActiveChatHeadUrl: {attribute: false},
|
||||
selectedAddress: {attribute: Object},
|
||||
currentTab: {type: Number},
|
||||
groups: {type: Array}
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.isLoading = false;
|
||||
this.isOpenLeaveModal = false
|
||||
this.leaveGroupObj = {}
|
||||
this.fee = null
|
||||
this.error = false
|
||||
this.message = ''
|
||||
this.chatHeads = []
|
||||
this.currentTab = 0
|
||||
this.groups = []
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return css`
|
||||
.top-bar-icon {
|
||||
cursor: pointer;
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
transition: .2s all;
|
||||
}
|
||||
.top-bar-icon:hover {
|
||||
color: var(--black)
|
||||
}
|
||||
.modal-button {
|
||||
font-family: Roboto, sans-serif;
|
||||
font-size: 16px;
|
||||
color: var(--mdc-theme-primary);
|
||||
background-color: transparent;
|
||||
padding: 8px 10px;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
async getJoinedGroups(){
|
||||
let joinedG = await parentEpml.request('apiCall', {
|
||||
url: `/groups/member/${this.selectedAddress.address}`
|
||||
})
|
||||
return joinedG
|
||||
}
|
||||
|
||||
async firstUpdated() {
|
||||
|
||||
try {
|
||||
let _joinedGroups = await this.getJoinedGroups()
|
||||
this.joinedGroups = _joinedGroups
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_tabChanged(e) {
|
||||
this.currentTab = e.detail.value
|
||||
}
|
||||
|
||||
async unitFee() {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
|
||||
const url = `${nodeUrl}/transactions/unitfee?txType=LEAVE_GROUP`
|
||||
let fee = null
|
||||
|
||||
try {
|
||||
const res = await fetch(url)
|
||||
const data = await res.json()
|
||||
fee = (Number(data) / 1e8).toFixed(3)
|
||||
} catch (error) {
|
||||
fee = null
|
||||
}
|
||||
|
||||
return fee
|
||||
}
|
||||
|
||||
timeIsoString(timestamp) {
|
||||
let myTimestamp = timestamp === undefined ? 1587560082346 : timestamp
|
||||
let time = new Date(myTimestamp)
|
||||
return time.toISOString()
|
||||
}
|
||||
|
||||
resetDefaultSettings() {
|
||||
this.error = false
|
||||
this.message = ''
|
||||
this.isLoading = false
|
||||
}
|
||||
|
||||
renderErr9Text() {
|
||||
return html`${translate("grouppage.gchange49")}`
|
||||
}
|
||||
|
||||
async confirmRelationship() {
|
||||
|
||||
|
||||
let interval = null
|
||||
let stop = false
|
||||
const getAnswer = async () => {
|
||||
const currentChats = this.chatHeads
|
||||
|
||||
if (!stop) {
|
||||
stop = true;
|
||||
try {
|
||||
const findGroup = currentChats.find((item)=> item.groupId === this.leaveGroupObj.groupId)
|
||||
if (!findGroup) {
|
||||
clearInterval(interval)
|
||||
this.isLoading = false
|
||||
this.isOpenLeaveModal= false
|
||||
this.setActiveChatHeadUrl('')
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
}
|
||||
stop = false
|
||||
}
|
||||
};
|
||||
interval = setInterval(getAnswer, 5000);
|
||||
}
|
||||
|
||||
async _leaveGroup(groupId, groupName) {
|
||||
// Reset Default Settings...
|
||||
this.resetDefaultSettings()
|
||||
|
||||
const leaveFeeInput = await this.unitFee()
|
||||
if(!leaveFeeInput){
|
||||
throw Error()
|
||||
}
|
||||
this.isLoading = true
|
||||
|
||||
// Get Last Ref
|
||||
const getLastRef = async () => {
|
||||
let myRef = await parentEpml.request('apiCall', {
|
||||
type: 'api',
|
||||
url: `/addresses/lastreference/${this.selectedAddress.address}`
|
||||
})
|
||||
return myRef
|
||||
};
|
||||
|
||||
const validateReceiver = async () => {
|
||||
let lastRef = await getLastRef();
|
||||
let myTransaction = await makeTransactionRequest(lastRef)
|
||||
getTxnRequestResponse(myTransaction)
|
||||
|
||||
}
|
||||
|
||||
// Make Transaction Request
|
||||
const makeTransactionRequest = async (lastRef) => {
|
||||
let groupdialog3 = get("transactions.groupdialog3")
|
||||
let groupdialog4 = get("transactions.groupdialog4")
|
||||
let myTxnrequest = await parentEpml.request('transaction', {
|
||||
type: 32,
|
||||
nonce: this.selectedAddress.nonce,
|
||||
params: {
|
||||
fee: leaveFeeInput,
|
||||
registrantAddress: this.selectedAddress.address,
|
||||
rGroupName: groupName,
|
||||
rGroupId: groupId,
|
||||
lastReference: lastRef,
|
||||
groupdialog3: groupdialog3,
|
||||
groupdialog4: groupdialog4,
|
||||
}
|
||||
})
|
||||
return myTxnrequest
|
||||
}
|
||||
|
||||
const getTxnRequestResponse = (txnResponse) => {
|
||||
|
||||
if (txnResponse.success === false && txnResponse.message) {
|
||||
this.error = true
|
||||
this.message = txnResponse.message
|
||||
throw new Error(txnResponse)
|
||||
} else if (txnResponse.success === true && !txnResponse.data.error) {
|
||||
this.message = this.renderErr9Text()
|
||||
this.error = false
|
||||
this.confirmRelationship()
|
||||
} else {
|
||||
this.error = true
|
||||
this.message = txnResponse.data.message
|
||||
throw new Error(txnResponse)
|
||||
}
|
||||
}
|
||||
validateReceiver()
|
||||
}
|
||||
|
||||
nameRenderer(person){
|
||||
console.log({person})
|
||||
return html`
|
||||
<vaadin-horizontal-layout style="align-items: center;display:flex" theme="spacing">
|
||||
<vaadin-avatar style="margin-right:5px" img="${person.pictureUrl}" .name="${person.displayName}"></vaadin-avatar>
|
||||
<span> ${person.displayName} </span>
|
||||
</vaadin-horizontal-layout>
|
||||
`;
|
||||
};
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<vaadin-icon @click=${()=> {
|
||||
this.isOpenLeaveModal = true
|
||||
}} class="top-bar-icon" style="margin: 0px 20px" icon="vaadin:exit" slot="icon"></vaadin-icon>
|
||||
<!-- Leave Group Dialog -->
|
||||
<wrapper-modal
|
||||
.removeImage=${() => {
|
||||
if(this.isLoading) return
|
||||
this.isOpenLeaveModal = false
|
||||
} }
|
||||
customStyle=${"width: 90%; max-width: 900px; height: 90%"}
|
||||
style=${(this.isOpenLeaveModal) ? "display: block" : "display: none"}>
|
||||
<div style="width: 100%;height: 100%;display: flex; flex-direction: column;background:var(--mdc-theme-surface)">
|
||||
<div style="height: 50px;display: flex; flex:0">
|
||||
<vaadin-tabs id="tabs" selected="${this.currentTab}" @selected-changed="${this._tabChanged}" style="width: 100%">
|
||||
|
||||
<vaadin-tab>Groups</vaadin-tab>
|
||||
<vaadin-tab>Group Join Requests</vaadin-tab>
|
||||
<vaadin-tab>Invites</vaadin-tab>
|
||||
<vaadin-tab>Blocked Users</vaadin-tab>
|
||||
</vaadin-tabs>
|
||||
</div>
|
||||
|
||||
<div style="width: 100%;display: flex; flex-direction: column; flex-grow: 1; overflow:auto;background:var(--mdc-theme-surface)">
|
||||
|
||||
${this.currentTab === 0 ? html`
|
||||
<div>
|
||||
|
||||
|
||||
<!-- Groups tab -->
|
||||
<!-- Search groups and be able to join -->
|
||||
<p>Search groups</p>
|
||||
<!-- Click group and it goes to that group and open right panel and settings -->
|
||||
<p>Current groups as owner</p>
|
||||
<p>Current groups as member</p>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
|
||||
</div>
|
||||
<div style="width: 100%;height: 50;display: flex; flex: 0">
|
||||
<button
|
||||
class="modal-button"
|
||||
?disabled="${this.isLoading}"
|
||||
@click=${() => this._leaveGroup(this.leaveGroupObj.groupId, this.leaveGroupObj.groupName)}
|
||||
>
|
||||
${translate("grouppage.gchange37")}
|
||||
</button>
|
||||
<button
|
||||
@click=${() => {
|
||||
this.isOpenLeaveModal= false
|
||||
}}
|
||||
class="modal-button"
|
||||
?disabled="${this.isLoading}"
|
||||
|
||||
>
|
||||
${translate("general.close")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</wrapper-modal >
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('chat-groups-management', ChatGroupsManagement);
|
@ -21,7 +21,9 @@ class ChatHead extends LitElement {
|
||||
static get styles() {
|
||||
return css`
|
||||
li {
|
||||
padding: 10px 2px 20px 5px;
|
||||
|
||||
width: 100%;
|
||||
padding: 7px 5px 7px 5px;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -19,7 +19,8 @@ class ChatLeaveGroup extends LitElement {
|
||||
error: {type: Boolean},
|
||||
message: {type: String},
|
||||
chatHeads: {type: Array},
|
||||
setActiveChatHeadUrl: {attribute: false}
|
||||
setActiveChatHeadUrl: {attribute: false},
|
||||
selectedAddress: {attribute: Object}
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,7 +29,7 @@ class ChatLeaveGroup extends LitElement {
|
||||
this.isLoading = false;
|
||||
this.isOpenLeaveModal = false
|
||||
this.leaveGroupObj = {}
|
||||
this.leaveFee = 0.001
|
||||
this.fee = null
|
||||
this.error = false
|
||||
this.message = ''
|
||||
this.chatHeads = []
|
||||
@ -59,7 +60,24 @@ class ChatLeaveGroup extends LitElement {
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
|
||||
}
|
||||
|
||||
async unitFee() {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
|
||||
const url = `${nodeUrl}/transactions/unitfee?txType=LEAVE_GROUP`
|
||||
let fee = null
|
||||
|
||||
try {
|
||||
const res = await fetch(url)
|
||||
const data = await res.json()
|
||||
fee = (Number(data) / 1e8).toFixed(3)
|
||||
} catch (error) {
|
||||
fee = null
|
||||
}
|
||||
|
||||
return fee
|
||||
}
|
||||
|
||||
timeIsoString(timestamp) {
|
||||
@ -108,8 +126,11 @@ class ChatLeaveGroup extends LitElement {
|
||||
async _leaveGroup(groupId, groupName) {
|
||||
// Reset Default Settings...
|
||||
this.resetDefaultSettings()
|
||||
const leaveFeeInput = this.leaveFee
|
||||
|
||||
|
||||
const leaveFeeInput = await this.unitFee()
|
||||
if(!leaveFeeInput){
|
||||
throw Error()
|
||||
}
|
||||
this.isLoading = true
|
||||
|
||||
// Get Last Ref
|
||||
|
@ -3,6 +3,8 @@ import { render } from 'lit/html.js';
|
||||
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 localForage from "localforage";
|
||||
registerTranslateConfig({
|
||||
loader: lang => fetch(`/language/${lang}.json`).then(res => res.json())
|
||||
@ -20,6 +22,8 @@ import './WrapperModal';
|
||||
import './ChatSelect.js'
|
||||
import './ChatSideNavHeads.js'
|
||||
import './ChatLeaveGroup.js'
|
||||
import './ChatGroupSettings.js'
|
||||
import './ChatRightPanel.js'
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js';
|
||||
import '@material/mwc-button';
|
||||
import '@material/mwc-dialog';
|
||||
@ -615,29 +619,35 @@ class ChatPage extends LitElement {
|
||||
this.groupMembers = []
|
||||
this.shifted = false
|
||||
this.groupInfo = {}
|
||||
this.pageNumber = 1
|
||||
}
|
||||
|
||||
_toggle() {
|
||||
this.shifted = !this.shifted;
|
||||
_toggle(value) {
|
||||
console.log('toggel', value, this.shifted)
|
||||
this.shifted = value === (false || true) ? value : !this.shifted;
|
||||
this.requestUpdate()
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log('this.chatHeads', this.chatHeads)
|
||||
console.log('this._chatId', this._chatId)
|
||||
return html`
|
||||
<div class="main-container">
|
||||
<div class="chat-container">
|
||||
${(!this.isReceipient && +this._chatId !== 0) ? html`
|
||||
<div style="display:flex; height:40px; padding:3px; margin:0px;background-color: var(--chat-bubble-bg); box-sizing: border-box; align-items: center;justify-content: space-between">
|
||||
<div>
|
||||
<p style="color: var(--black);margin:0px;padding:0px">Name</p>
|
||||
<div @click=${this._toggle} style="height: 100%;display: flex;align-items: center;flex-grow: 1;cursor: pointer;cursor:pointer;user-select:none">
|
||||
<p style="color: var(--black);margin:0px;padding:0px">${this.groupInfo && this.groupInfo.groupName}</p>
|
||||
</div>
|
||||
<div style="display:flex;height:100%;align-items:center">
|
||||
<vaadin-icon class="top-bar-icon" @click=${this._toggle} style="margin: 0px 10px" icon="vaadin:info" slot="icon"></vaadin-icon>
|
||||
<vaadin-icon class="top-bar-icon" style="margin: 0px 20px" icon="vaadin:cog" slot="icon"></vaadin-icon>
|
||||
<vaadin-icon class="top-bar-icon" style="margin: 0px 20px" icon="vaadin:search" slot="icon"></vaadin-icon>
|
||||
<chat-group-settings .chatHeads=${this.chatHeads} .selectedAddress=${this.selectedAddress} .leaveGroupObj=${this.groupInfo} .setActiveChatHeadUrl=${(val)=> this.setActiveChatHeadUrl(val)}></chat-group-settings>
|
||||
<!-- <vaadin-icon class="top-bar-icon" style="margin: 0px 20px" icon="vaadin:search" slot="icon"></vaadin-icon> -->
|
||||
<!-- <vaadin-icon class="top-bar-icon" style="margin: 0px 20px" icon="vaadin:exit" slot="icon"></vaadin-icon> -->
|
||||
<chat-leave-group .chatHeads=${this.chatHeads} .selectedAddress=${this.selectedAddress} .leaveGroupObj=${this.groupInfo} .setActiveChatHeadUrl=${(val)=> this.setActiveChatHeadUrl(val)}></chat-leave-group>
|
||||
</div>
|
||||
</div>
|
||||
` : html`<div></div>`}
|
||||
|
||||
<div>
|
||||
${this.isLoadingMessages ?
|
||||
html`
|
||||
@ -829,36 +839,44 @@ class ChatPage extends LitElement {
|
||||
</div>
|
||||
</wrapper-modal>
|
||||
</div>
|
||||
<div class="chat-right-panel ${this.shifted ? "movedin" : "movedout"}" ${animate()}>
|
||||
<p>Exit Icon</p>
|
||||
<span>Group Avatar</span> <p>Group Name</p>
|
||||
<p>Group owner</p>
|
||||
<p>100 Members</p>
|
||||
<p>Description</p>
|
||||
<p>date created</p>
|
||||
<p>private / public</p>
|
||||
<p>approvalThreshold</p>
|
||||
<p>"minimumBlockDelay": 0, "maximumBlockDelay": 0</p>
|
||||
<p class="chat-right-panel-label">Admins</p>
|
||||
${this.groupAdmin.map((item)=> {
|
||||
return html`<chat-side-nav-heads activeChatHeadUrl="" setActiveChatHeadUrl=${(val)=> {
|
||||
|
||||
}} chatInfo=${JSON.stringify(item)}></chat-side-nav-heads>`
|
||||
})}
|
||||
|
||||
<p class="chat-right-panel-label">Members</p>
|
||||
${this.groupAdmin.map((item)=> {
|
||||
return html`<chat-side-nav-heads activeChatHeadUrl="" setActiveChatHeadUrl=${(val)=> {
|
||||
|
||||
}} chatInfo=${JSON.stringify(item)}></chat-side-nav-heads>`
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div class="chat-right-panel ${this.shifted ? "movedin" : "movedout"}" ${animate()}>
|
||||
<chat-right-panel .getMoreMembers=${(val)=> this.getMoreMembers(val)} .toggle=${(val)=> this._toggle(val)} .selectedAddress=${this.selectedAddress} .groupMembers=${this.groupMembers} .groupAdmin=${this.groupAdmin} .leaveGroupObj=${this.groupInfo}></chat-right-panel>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
async getMoreMembers(groupId){
|
||||
console.log('getMoreMembers', groupId)
|
||||
try {
|
||||
const getMembers = await parentEpml.request("apiCall", {
|
||||
type: "api",
|
||||
url: `/groups/members/${groupId}?onlyAdmins=false&limit=20&offset=${this.pageNumber * 20}`,
|
||||
});
|
||||
|
||||
const getMembersWithName = (getMembers.members || []).map(async (member) => {
|
||||
let memberItem = member
|
||||
try {
|
||||
const name = await this.getName(member.member)
|
||||
memberItem = {
|
||||
address: member.member,
|
||||
name: name ? name : undefined
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
|
||||
return memberItem
|
||||
})
|
||||
const membersWithName = await Promise.all(getMembersWithName)
|
||||
this.groupMembers = membersWithName
|
||||
this.pageNumber = this.pageNumber + 1
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
setForwardProperties(forwardedMessage){
|
||||
this.openForwardOpen = true
|
||||
this.forwardedMessage = forwardedMessage
|
||||
@ -957,6 +975,7 @@ class ChatPage extends LitElement {
|
||||
this.webSocket.close()
|
||||
this.webSocket= ''
|
||||
}
|
||||
this.pageNumber = 1
|
||||
const getAddressPublicKey = () => {
|
||||
|
||||
parentEpml.request('apiCall', {
|
||||
@ -1006,7 +1025,7 @@ class ChatPage extends LitElement {
|
||||
try {
|
||||
const getMembers = await parentEpml.request("apiCall", {
|
||||
type: "api",
|
||||
url: `/groups/members/${groupId}?onlyAdmins=false&limit=20`,
|
||||
url: `/groups/members/${groupId}?onlyAdmins=false&limit=20&offset=0`,
|
||||
});
|
||||
const getMembersAdmins = await parentEpml.request("apiCall", {
|
||||
type: "api",
|
||||
@ -1404,6 +1423,7 @@ async getName (recipient) {
|
||||
let decodedMessageObj = {};
|
||||
|
||||
if (isReceipientVar === true) {
|
||||
console.log('encoded', encodedMessageObj.isEncrypted, _publicKeyVar.hasPubKey,encodedMessageObj.data)
|
||||
// direct chat
|
||||
if (encodedMessageObj.isEncrypted === true && _publicKeyVar.hasPubKey === true && encodedMessageObj.data) {
|
||||
let decodedMessage = window.parent.decryptChatMessage(encodedMessageObj.data, window.parent.reduxStore.getState().app.selectedAddress.keyPair.privateKey, _publicKeyVar.key, encodedMessageObj.reference);
|
||||
|
486
qortal-ui-plugins/plugins/core/components/ChatRightPanel.js
Normal file
486
qortal-ui-plugins/plugins/core/components/ChatRightPanel.js
Normal file
@ -0,0 +1,486 @@
|
||||
import { LitElement, html, css } from "lit"
|
||||
import { render } from "lit/html.js"
|
||||
import { get, translate } from "lit-translate"
|
||||
import { Epml } from "../../../epml"
|
||||
import snackbar from "./snackbar.js"
|
||||
import "@material/mwc-button"
|
||||
import "@material/mwc-dialog"
|
||||
import "@polymer/paper-spinner/paper-spinner-lite.js"
|
||||
import "@material/mwc-icon"
|
||||
import "./WrapperModal"
|
||||
|
||||
const parentEpml = new Epml({ type: "WINDOW", source: window.parent })
|
||||
|
||||
class ChatRightPanel extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
isLoading: { type: Boolean },
|
||||
isOpenLeaveModal: { type: Boolean },
|
||||
leaveGroupObj: { type: Object },
|
||||
error: { type: Boolean },
|
||||
message: { type: String },
|
||||
chatHeads: { type: Array },
|
||||
groupAdmin: { attribute: false },
|
||||
groupMembers: { attribute: false },
|
||||
selectedHead: { type: Object },
|
||||
toggle: {attribute: false},
|
||||
getMoreMembers:{attribute: false}
|
||||
}
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
this.isLoading = false
|
||||
this.isOpenLeaveModal = false
|
||||
this.leaveGroupObj = {}
|
||||
this.leaveFee = 0.001
|
||||
this.error = false
|
||||
this.message = ""
|
||||
this.chatHeads = []
|
||||
this.groupAdmin = []
|
||||
this.groupMembers = []
|
||||
this.observerHandler = this.observerHandler.bind(this)
|
||||
this.viewElement = ''
|
||||
this.downObserverElement = ''
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return css`
|
||||
.top-bar-icon {
|
||||
cursor: pointer;
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
transition: 0.2s all;
|
||||
}
|
||||
.top-bar-icon:hover {
|
||||
color: var(--black);
|
||||
}
|
||||
.modal-button {
|
||||
font-family: Roboto, sans-serif;
|
||||
font-size: 16px;
|
||||
color: var(--mdc-theme-primary);
|
||||
background-color: transparent;
|
||||
padding: 8px 10px;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
.close-row {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
height: 50px;
|
||||
flex:0
|
||||
|
||||
}
|
||||
.container-body {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
overflow:auto;
|
||||
margin-top: 15px;
|
||||
padding: 0px 5px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.container-body::-webkit-scrollbar-track {
|
||||
background-color: whitesmoke;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
.container-body::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
border-radius: 7px;
|
||||
background-color: whitesmoke;
|
||||
}
|
||||
|
||||
.container-body::-webkit-scrollbar-thumb {
|
||||
background-color: rgb(180, 176, 176);
|
||||
border-radius: 7px;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.container-body::-webkit-scrollbar-thumb:hover {
|
||||
background-color: rgb(148, 146, 146);
|
||||
cursor: pointer;
|
||||
}
|
||||
p {
|
||||
color: var(--black);
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
word-break: break-all;
|
||||
}
|
||||
.container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
this.viewElement = this.shadowRoot.getElementById('viewElement');
|
||||
this.downObserverElement = this.shadowRoot.getElementById('downObserver');
|
||||
this.elementObserver();
|
||||
}
|
||||
|
||||
timeIsoString(timestamp) {
|
||||
let myTimestamp = timestamp === undefined ? 1587560082346 : timestamp
|
||||
let time = new Date(myTimestamp)
|
||||
return time.toISOString()
|
||||
}
|
||||
|
||||
resetDefaultSettings() {
|
||||
this.error = false
|
||||
this.message = ""
|
||||
this.isLoading = false
|
||||
}
|
||||
|
||||
renderErr9Text() {
|
||||
return html`${translate("grouppage.gchange49")}`
|
||||
}
|
||||
|
||||
async confirmRelationship(reference) {
|
||||
let interval = null
|
||||
let stop = false
|
||||
const getAnswer = async () => {
|
||||
|
||||
|
||||
if (!stop) {
|
||||
stop = true
|
||||
try {
|
||||
let myRef = await parentEpml.request("apiCall", {
|
||||
type: "api",
|
||||
url: `/transactions/reference/${reference}`,
|
||||
})
|
||||
if (myRef && myRef.type) {
|
||||
clearInterval(interval)
|
||||
this.isLoading = false
|
||||
this.isOpenLeaveModal = false
|
||||
}
|
||||
} catch (error) {}
|
||||
stop = false
|
||||
}
|
||||
}
|
||||
interval = setInterval(getAnswer, 5000)
|
||||
}
|
||||
|
||||
async unitFee(txType) {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
|
||||
const url = `${nodeUrl}/transactions/unitfee?txType=${txType}`
|
||||
let fee = null
|
||||
|
||||
try {
|
||||
const res = await fetch(url)
|
||||
const data = await res.json()
|
||||
fee = (Number(data) / 1e8).toFixed(3)
|
||||
} catch (error) {
|
||||
fee = null
|
||||
}
|
||||
|
||||
return fee
|
||||
}
|
||||
|
||||
async getLastRef() {
|
||||
let myRef = await parentEpml.request("apiCall", {
|
||||
type: "api",
|
||||
url: `/addresses/lastreference/${this.selectedAddress.address}`,
|
||||
})
|
||||
return myRef
|
||||
}
|
||||
|
||||
getTxnRequestResponse(txnResponse, reference) {
|
||||
if (txnResponse === true) {
|
||||
this.message = this.renderErr9Text()
|
||||
this.error = false
|
||||
this.confirmRelationship(reference)
|
||||
} else {
|
||||
this.error = true
|
||||
this.message = ""
|
||||
throw new Error(txnResponse)
|
||||
}
|
||||
}
|
||||
|
||||
async convertBytesForSigning(transactionBytesBase58) {
|
||||
let convertedBytes = await parentEpml.request("apiCall", {
|
||||
type: "api",
|
||||
method: "POST",
|
||||
url: `/transactions/convert`,
|
||||
body: `${transactionBytesBase58}`,
|
||||
})
|
||||
return convertedBytes
|
||||
}
|
||||
|
||||
async signTx(body){
|
||||
return await parentEpml.request("apiCall", {
|
||||
type: "api",
|
||||
method: "POST",
|
||||
url: `/transactions/sign`,
|
||||
body: body,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async process(body){
|
||||
return await parentEpml.request("apiCall", {
|
||||
type: "api",
|
||||
method: "POST",
|
||||
url: `/transactions/process`,
|
||||
body: body,
|
||||
})
|
||||
}
|
||||
async _addAdmin(groupId) {
|
||||
this.resetDefaultSettings()
|
||||
|
||||
const leaveFeeInput = await this.unitFee('ADD_GROUP_ADMIN')
|
||||
if(!leaveFeeInput){
|
||||
throw Error()
|
||||
}
|
||||
this.isLoading = true
|
||||
|
||||
// Get Last Ref
|
||||
const getLastRef = async () => {
|
||||
let myRef = await parentEpml.request('apiCall', {
|
||||
type: 'api',
|
||||
url: `/addresses/lastreference/${this.selectedAddress.address}`
|
||||
})
|
||||
return myRef
|
||||
};
|
||||
|
||||
const validateReceiver = async () => {
|
||||
let lastRef = await getLastRef();
|
||||
let myTransaction = await makeTransactionRequest(lastRef)
|
||||
getTxnRequestResponse(myTransaction)
|
||||
|
||||
}
|
||||
|
||||
// Make Transaction Request
|
||||
const makeTransactionRequest = async (lastRef) => {
|
||||
let groupdialog3 = get("transactions.groupdialog3")
|
||||
let groupdialog4 = get("transactions.groupdialog4")
|
||||
let myTxnrequest = await parentEpml.request('transaction', {
|
||||
type: 24,
|
||||
nonce: this.selectedAddress.nonce,
|
||||
params: {
|
||||
_groupId: groupId,
|
||||
fee: leaveFeeInput,
|
||||
member: this.selectedHead.address,
|
||||
lastReference: lastRef
|
||||
}
|
||||
})
|
||||
return myTxnrequest
|
||||
}
|
||||
|
||||
const getTxnRequestResponse = (txnResponse) => {
|
||||
|
||||
if (txnResponse.success === false && txnResponse.message) {
|
||||
this.error = true
|
||||
this.message = txnResponse.message
|
||||
throw new Error(txnResponse)
|
||||
} else if (txnResponse.success === true && !txnResponse.data.error) {
|
||||
this.message = this.renderErr9Text()
|
||||
this.error = false
|
||||
this.confirmRelationship()
|
||||
} else {
|
||||
this.error = true
|
||||
this.message = txnResponse.data.message
|
||||
throw new Error(txnResponse)
|
||||
}
|
||||
}
|
||||
validateReceiver()
|
||||
}
|
||||
|
||||
async _removeAdmin(groupId) {
|
||||
this.resetDefaultSettings()
|
||||
|
||||
const leaveFeeInput = await this.unitFee('REMOVE_GROUP_ADMIN')
|
||||
if(!leaveFeeInput){
|
||||
throw Error()
|
||||
}
|
||||
this.isLoading = true
|
||||
|
||||
// Get Last Ref
|
||||
const getLastRef = async () => {
|
||||
let myRef = await parentEpml.request('apiCall', {
|
||||
type: 'api',
|
||||
url: `/addresses/lastreference/${this.selectedAddress.address}`
|
||||
})
|
||||
return myRef
|
||||
};
|
||||
|
||||
const validateReceiver = async () => {
|
||||
let lastRef = await getLastRef();
|
||||
let myTransaction = await makeTransactionRequest(lastRef)
|
||||
getTxnRequestResponse(myTransaction)
|
||||
|
||||
}
|
||||
|
||||
// Make Transaction Request
|
||||
const makeTransactionRequest = async (lastRef) => {
|
||||
let groupdialog3 = get("transactions.groupdialog3")
|
||||
let groupdialog4 = get("transactions.groupdialog4")
|
||||
let myTxnrequest = await parentEpml.request('transaction', {
|
||||
type: 25,
|
||||
nonce: this.selectedAddress.nonce,
|
||||
params: {
|
||||
_groupId: groupId,
|
||||
fee: leaveFeeInput,
|
||||
member: this.selectedHead.address,
|
||||
lastReference: lastRef
|
||||
}
|
||||
})
|
||||
return myTxnrequest
|
||||
}
|
||||
|
||||
const getTxnRequestResponse = (txnResponse) => {
|
||||
|
||||
if (txnResponse.success === false && txnResponse.message) {
|
||||
this.error = true
|
||||
this.message = txnResponse.message
|
||||
throw new Error(txnResponse)
|
||||
} else if (txnResponse.success === true && !txnResponse.data.error) {
|
||||
this.message = this.renderErr9Text()
|
||||
this.error = false
|
||||
this.confirmRelationship()
|
||||
} else {
|
||||
this.error = true
|
||||
this.message = txnResponse.data.message
|
||||
throw new Error(txnResponse)
|
||||
}
|
||||
}
|
||||
validateReceiver()
|
||||
}
|
||||
|
||||
elementObserver() {
|
||||
const options = {
|
||||
root: this.viewElement,
|
||||
rootMargin: '0px',
|
||||
threshold: 1
|
||||
}
|
||||
// identify an element to observe
|
||||
const elementToObserve = this.downObserverElement;
|
||||
// passing it a callback function
|
||||
const observer = new IntersectionObserver(this.observerHandler, options);
|
||||
// call `observe()` on that MutationObserver instance,
|
||||
// passing it the element to observe, and the options object
|
||||
observer.observe(elementToObserve);
|
||||
}
|
||||
observerHandler(entries) {
|
||||
if (!entries[0].isIntersecting) {
|
||||
return
|
||||
} else {
|
||||
if(this.groupMembers.length < 20){
|
||||
return
|
||||
}
|
||||
console.log('this.leaveGroupObjp', this.leaveGroupObj)
|
||||
this.getMoreMembers(this.leaveGroupObj.groupId)
|
||||
}
|
||||
}
|
||||
render() {
|
||||
console.log('this.groupMembers', this.groupMembers)
|
||||
const owner = this.groupAdmin.filter((admin)=> admin.address === this.leaveGroupObj.owner)
|
||||
return html`
|
||||
<div class="container">
|
||||
<div class="close-row" style="margin-top: 15px">
|
||||
<vaadin-icon class="top-bar-icon" @click=${()=> this.toggle(false)} style="margin: 0px 10px" icon="vaadin:close" slot="icon"></vaadin-icon>
|
||||
</div>
|
||||
<div id="viewElement" class="container-body">
|
||||
<p style="font-size: 20px;">${this.leaveGroupObj && this.leaveGroupObj.groupName}</p>
|
||||
<p style="font-size: 14px;margin-top: 5px">${this.leaveGroupObj && this.leaveGroupObj.description}</p>
|
||||
<p style="font-size: 14px;margin-top: 10px">Members: ${this.leaveGroupObj && this.leaveGroupObj.memberCount}</p>
|
||||
|
||||
<p style="font-size: 14px;margin-top: 5px">Date created : ${new Date(this.leaveGroupObj.created).toLocaleDateString("en-US")}</p>
|
||||
<br />
|
||||
<p class="chat-right-panel-label">Group Owner</p>
|
||||
${owner.map((item) => {
|
||||
return html`<chat-side-nav-heads
|
||||
activeChatHeadUrl=""
|
||||
.setActiveChatHeadUrl=${(val) => {}}
|
||||
chatInfo=${JSON.stringify(item)}
|
||||
></chat-side-nav-heads>`
|
||||
})}
|
||||
<p class="chat-right-panel-label">Admins</p>
|
||||
${this.groupAdmin.map((item) => {
|
||||
return html`<chat-side-nav-heads
|
||||
activeChatHeadUrl=""
|
||||
.setActiveChatHeadUrl=${(val) => {}}
|
||||
chatInfo=${JSON.stringify(item)}
|
||||
></chat-side-nav-heads>`
|
||||
})}
|
||||
<p class="chat-right-panel-label">Members</p>
|
||||
${this.groupMembers.map((item) => {
|
||||
return html`<chat-side-nav-heads
|
||||
activeChatHeadUrl=""
|
||||
.setActiveChatHeadUrl=${(val) => {
|
||||
console.log({ val })
|
||||
this.selectedHead = val
|
||||
this.isOpenLeaveModal = true
|
||||
}}
|
||||
chatInfo=${JSON.stringify(item)}
|
||||
></chat-side-nav-heads>`
|
||||
})}
|
||||
<div id='downObserver'></div>
|
||||
</div>
|
||||
|
||||
<wrapper-modal
|
||||
.removeImage=${() => {
|
||||
if (this.isLoading) return
|
||||
this.isOpenLeaveModal = false
|
||||
}}
|
||||
style=${
|
||||
this.isOpenLeaveModal ? "display: block" : "display: none"
|
||||
}>
|
||||
<div style="text-align:center">
|
||||
<h1>${translate("grouppage.gchange35")}</h1>
|
||||
<hr>
|
||||
</div>
|
||||
|
||||
<button @click=${() =>
|
||||
this._addAdmin(
|
||||
this.leaveGroupObj.groupId
|
||||
)}>Promote to Admin</button>
|
||||
<button @click=${() =>
|
||||
this._removeAdmin(
|
||||
this.leaveGroupObj.groupId
|
||||
)}>Remove as Admin</button>
|
||||
<div style="text-align:right; height:36px;">
|
||||
<span ?hidden="${!this.isLoading}">
|
||||
<!-- loading message -->
|
||||
${translate("grouppage.gchange36")}
|
||||
<paper-spinner-lite
|
||||
style="margin-top:12px;"
|
||||
?active="${this.isLoading}"
|
||||
alt="Leaving"
|
||||
>
|
||||
</paper-spinner-lite>
|
||||
</span>
|
||||
<span ?hidden=${this.message === ""} style="${
|
||||
this.error ? "color:red;" : ""
|
||||
}">
|
||||
${this.message}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
<button
|
||||
@click=${() => {
|
||||
this.isOpenLeaveModal = false
|
||||
}}
|
||||
class="modal-button"
|
||||
?disabled="${this.isLoading}"
|
||||
|
||||
>
|
||||
${translate("general.close")}
|
||||
</button>
|
||||
</wrapper-modal >
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("chat-right-panel", ChatRightPanel)
|
@ -662,6 +662,7 @@ class ChatMenu extends LitElement {
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log(this.messages, 'this.messages')
|
||||
return html`
|
||||
<div class="container">
|
||||
<div
|
||||
|
@ -124,7 +124,7 @@ class ChatSideNavHeads extends LitElement {
|
||||
}
|
||||
|
||||
return html`
|
||||
<li @click=${() => this.getUrl(this.chatInfo.url)} class="clearfix">
|
||||
<li @click=${() => this.getUrl(this.chatInfo)} class="clearfix">
|
||||
${this.isImageLoaded ? html`${avatarImg}` : html`` }
|
||||
${!this.isImageLoaded && !this.chatInfo.name && !this.chatInfo.groupName ? html`<mwc-icon class="img-icon">account_circle</mwc-icon>` : html`` }
|
||||
${!this.isImageLoaded && this.chatInfo.name ? html`<div style="width:30px; height:30px; float: left; border-radius:50%; background: ${this.activeChatHeadUrl === this.chatInfo.url ? 'var(--chatHeadBgActive)' : 'var(--chatHeadBg)' }; color: ${this.activeChatHeadUrl === this.chatInfo.url ? 'var(--chatHeadTextActive)' : 'var(--chatHeadText)' }; font-weight:bold; display: flex; justify-content: center; align-items: center; text-transform: capitalize">${this.chatInfo.name.charAt(0)}</div>`: ''}
|
||||
|
@ -10,6 +10,7 @@ export const wrapperModalStyles = css`
|
||||
background: rgb(186 186 186 / 26%);
|
||||
overflow: hidden;
|
||||
animation: backdrop_blur cubic-bezier(0.22, 1, 0.36, 1) 1s forwards;
|
||||
z-index: 50
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
@ -29,6 +30,7 @@ export const wrapperModalStyles = css`
|
||||
overflow-y: auto;
|
||||
animation: 1s cubic-bezier(0.22, 1, 0.36, 1) 0s 1 normal forwards running modal_transition;
|
||||
max-height: 80%;
|
||||
z-index: 51
|
||||
}
|
||||
|
||||
@keyframes backdrop_blur {
|
||||
|
@ -6,6 +6,7 @@ export class WrapperModal extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
removeImage: { type: Function },
|
||||
customStyle: {type: String}
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +18,7 @@ export class WrapperModal extends LitElement {
|
||||
<div class="backdrop" @click=${() => {
|
||||
this.removeImage()
|
||||
}}></div>
|
||||
<div class="modal-body">
|
||||
<div class="modal-body" style=${this.customStyle ? this.customStyle : ""}>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -523,6 +523,7 @@ class GroupManagement extends LitElement {
|
||||
setTimeout(getOpen_JoinedGroups, 1)
|
||||
configLoaded = true
|
||||
}
|
||||
console.log('parse', JSON.parse(c))
|
||||
this.config = JSON.parse(c)
|
||||
})
|
||||
parentEpml.subscribe('copy_menu_switch', async value => {
|
||||
|
@ -10,6 +10,7 @@ registerTranslateConfig({
|
||||
import '../../components/ChatWelcomePage.js'
|
||||
import '../../components/ChatHead.js'
|
||||
import '../../components/ChatPage.js'
|
||||
import '../../components/ChatGroupsManagement.js'
|
||||
import snackbar from '../../components/snackbar.js'
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js'
|
||||
import '@material/mwc-button'
|
||||
@ -342,6 +343,7 @@ class Chat extends LitElement {
|
||||
<div class="people-list" id="people-list">
|
||||
<div class="search">
|
||||
<div class="create-chat" @click=${() => this.shadowRoot.querySelector('#startChatDialog').show()}>${translate("chatpage.cchange1")}</div>
|
||||
<chat-groups-management></chat-groups-management>
|
||||
</div>
|
||||
<ul class="list">
|
||||
${this.isEmptyArray(this.chatHeads) ? this.renderLoadingText() : this.renderChatHead(this.chatHeads)}
|
||||
|
Loading…
x
Reference in New Issue
Block a user