mirror of
https://github.com/Qortal/qortal-ui.git
synced 2025-04-28 13:57:50 +00:00
Compare commits
No commits in common. "master" and "v4.6.1" have entirely different histories.
299
plugins/plugins/core/components/ChatGroupInvites.js
Normal file
299
plugins/plugins/core/components/ChatGroupInvites.js
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
import { html, LitElement } from 'lit'
|
||||||
|
import { Epml } from '../../../epml'
|
||||||
|
import { chatGroupStyles } from './plugins-css'
|
||||||
|
import './WrapperModal'
|
||||||
|
import '@material/mwc-button'
|
||||||
|
import '@material/mwc-dialog'
|
||||||
|
import '@material/mwc-icon'
|
||||||
|
import '@polymer/paper-spinner/paper-spinner-lite.js'
|
||||||
|
|
||||||
|
// Multi language support
|
||||||
|
import { translate } from '../../../../core/translate'
|
||||||
|
|
||||||
|
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 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles() {
|
||||||
|
return [chatGroupStyles]
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = []
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
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>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
||||||
|
return await parentEpml.request("apiCall", {
|
||||||
|
type: "api",
|
||||||
|
url: `/addresses/lastreference/${this.selectedAddress.address}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
return await parentEpml.request("apiCall", {
|
||||||
|
type: "api",
|
||||||
|
method: "POST",
|
||||||
|
url: `/transactions/convert`,
|
||||||
|
body: `${transactionBytesBase58}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
return await this.process(signTransaction)
|
||||||
|
}
|
||||||
|
|
||||||
|
await 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)
|
||||||
|
|
||||||
|
return await this.process(signTransaction)
|
||||||
|
}
|
||||||
|
|
||||||
|
await validateReceiver()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Standard functions
|
||||||
|
getApiKey() {
|
||||||
|
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||||
|
return myNode.apiKey
|
||||||
|
}
|
||||||
|
|
||||||
|
isEmptyArray(arr) {
|
||||||
|
if (!arr) { return true }
|
||||||
|
return arr.length === 0
|
||||||
|
}
|
||||||
|
|
||||||
|
round(number) {
|
||||||
|
return (Math.round(parseFloat(number) * 1e8) / 1e8).toFixed(8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.customElements.define('chat-group-invites', ChatGroupInvites)
|
@ -185,7 +185,6 @@ class WebBrowser extends LitElement {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const render = () => {
|
const render = () => {
|
||||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
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 nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
|
||||||
@ -266,7 +265,7 @@ class WebBrowser extends LitElement {
|
|||||||
${this.renderFollowUnfollowButton()}
|
${this.renderFollowUnfollowButton()}
|
||||||
</div>
|
</div>
|
||||||
<div class="iframe-container">
|
<div class="iframe-container">
|
||||||
<iframe id="browser-iframe" src="${this.url}" sandbox="allow-scripts allow-same-origin allow-forms allow-downloads allow-modals" allow="fullscreen; clipboard-read; clipboard-write;">
|
<iframe id="browser-iframe" src="${this.url}" sandbox="allow-scripts allow-same-origin allow-forms allow-downloads allow-modals" allow="fullscreen">
|
||||||
<span style="color: var(--black);">${translate('browserpage.bchange6')}</span>
|
<span style="color: var(--black);">${translate('browserpage.bchange6')}</span>
|
||||||
</iframe>
|
</iframe>
|
||||||
</div>
|
</div>
|
||||||
@ -1418,7 +1417,7 @@ class WebBrowser extends LitElement {
|
|||||||
|
|
||||||
case actions.PUBLISH_QDN_RESOURCE: {
|
case actions.PUBLISH_QDN_RESOURCE: {
|
||||||
// optional fields: encrypt:boolean recipientPublicKey:string
|
// optional fields: encrypt:boolean recipientPublicKey:string
|
||||||
const requiredFields = ['service']
|
const requiredFields = ['service', 'name']
|
||||||
const missingFields = []
|
const missingFields = []
|
||||||
let dataSentBack = {}
|
let dataSentBack = {}
|
||||||
requiredFields.forEach((field) => {
|
requiredFields.forEach((field) => {
|
||||||
@ -1440,7 +1439,7 @@ class WebBrowser extends LitElement {
|
|||||||
response = JSON.stringify(dataSentBack)
|
response = JSON.stringify(dataSentBack)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if (!data.file && !data.data64 && !data.base64) {
|
if (!data.file && !data.data64) {
|
||||||
let myMsg1 = get("modals.mpchange22")
|
let myMsg1 = get("modals.mpchange22")
|
||||||
let myMsg2 = get("walletpage.wchange44")
|
let myMsg2 = get("walletpage.wchange44")
|
||||||
await showErrorAndWait("ACTION_FAILED", { id1: myMsg1, id2: myMsg2 })
|
await showErrorAndWait("ACTION_FAILED", { id1: myMsg1, id2: myMsg2 })
|
||||||
@ -1451,13 +1450,9 @@ class WebBrowser extends LitElement {
|
|||||||
}
|
}
|
||||||
// Use "default" if user hasn't specified an identifer
|
// Use "default" if user hasn't specified an identifer
|
||||||
const service = data.service
|
const service = data.service
|
||||||
const name = data.name || this.getMyName()
|
const name = data.name
|
||||||
if(!name){
|
|
||||||
dataSentBack['error'] = `Missing name`
|
|
||||||
break
|
|
||||||
}
|
|
||||||
let identifier = data.identifier
|
let identifier = data.identifier
|
||||||
let data64 = data.data64 || data.base64
|
let data64 = data.data64
|
||||||
const filename = data.filename
|
const filename = data.filename
|
||||||
const title = data.title
|
const title = data.title
|
||||||
const description = data.description
|
const description = data.description
|
||||||
@ -1634,16 +1629,10 @@ class WebBrowser extends LitElement {
|
|||||||
}
|
}
|
||||||
const getArbitraryFee = await this.getArbitraryFee()
|
const getArbitraryFee = await this.getArbitraryFee()
|
||||||
feeAmount = getArbitraryFee.fee
|
feeAmount = getArbitraryFee.fee
|
||||||
const reformatResources = resources.map((resource)=> {
|
|
||||||
return {
|
|
||||||
...resource,
|
|
||||||
name: resource.name || this.getMyName()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const res2 = await showModalAndWait(
|
const res2 = await showModalAndWait(
|
||||||
actions.PUBLISH_MULTIPLE_QDN_RESOURCES,
|
actions.PUBLISH_MULTIPLE_QDN_RESOURCES,
|
||||||
{
|
{
|
||||||
resources: reformatResources,
|
resources,
|
||||||
encrypt: data.encrypt,
|
encrypt: data.encrypt,
|
||||||
feeAmount: getArbitraryFee.feeToShow
|
feeAmount: getArbitraryFee.feeToShow
|
||||||
}
|
}
|
||||||
@ -1658,9 +1647,9 @@ class WebBrowser extends LitElement {
|
|||||||
}
|
}
|
||||||
let failedPublishesIdentifiers = []
|
let failedPublishesIdentifiers = []
|
||||||
this.loader.show()
|
this.loader.show()
|
||||||
for (const resource of reformatResources) {
|
for (const resource of resources) {
|
||||||
try {
|
try {
|
||||||
const requiredFields = ['service']
|
const requiredFields = ['service', 'name']
|
||||||
const missingFields = []
|
const missingFields = []
|
||||||
requiredFields.forEach((field) => {
|
requiredFields.forEach((field) => {
|
||||||
if (!resource[field]) {
|
if (!resource[field]) {
|
||||||
@ -1676,7 +1665,7 @@ class WebBrowser extends LitElement {
|
|||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (!resource.file && !resource.data64 && !resource.base64) {
|
if (!resource.file && !resource.data64) {
|
||||||
const errorMsg = 'No data or file was submitted'
|
const errorMsg = 'No data or file was submitted'
|
||||||
failedPublishesIdentifiers.push({
|
failedPublishesIdentifiers.push({
|
||||||
reason: errorMsg,
|
reason: errorMsg,
|
||||||
@ -1686,16 +1675,8 @@ class WebBrowser extends LitElement {
|
|||||||
}
|
}
|
||||||
const service = resource.service
|
const service = resource.service
|
||||||
const name = resource.name
|
const name = resource.name
|
||||||
if(!name){
|
|
||||||
const errorMsg = `Missing name`
|
|
||||||
failedPublishesIdentifiers.push({
|
|
||||||
reason: errorMsg,
|
|
||||||
identifier: resource.identifier
|
|
||||||
})
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
let identifier = resource.identifier
|
let identifier = resource.identifier
|
||||||
let data64 = resource.data64 || resource.base64
|
let data64 = resource.data64
|
||||||
const filename = resource.filename
|
const filename = resource.filename
|
||||||
const title = resource.title
|
const title = resource.title
|
||||||
const description = resource.description
|
const description = resource.description
|
||||||
@ -4426,11 +4407,6 @@ class WebBrowser extends LitElement {
|
|||||||
}, 60000)
|
}, 60000)
|
||||||
}
|
}
|
||||||
|
|
||||||
getMyName(){
|
|
||||||
const names = window.parent.reduxStore.getState().app.accountInfo.names
|
|
||||||
if(names.length === 0) return null
|
|
||||||
return names[0].name
|
|
||||||
}
|
|
||||||
renderFullScreen() {
|
renderFullScreen() {
|
||||||
if (window.innerHeight === screen.height) {
|
if (window.innerHeight === screen.height) {
|
||||||
return html`
|
return html`
|
||||||
|
Loading…
x
Reference in New Issue
Block a user