Browse Source

Merge branch 'feature/implement-logic-edit-reply-messages' of https://github.com/PhillipLangMartinez/qortal-ui into feature/implement-UI-edit-reply-messages

q-apps
Justin Ferrari 2 years ago
parent
commit
831492301a
  1. 3
      qortal-ui-core/language/us.json
  2. 3
      qortal-ui-core/package.json
  3. 106
      qortal-ui-core/src/components/app-info.js
  4. 82
      qortal-ui-core/src/components/computePowWorker.js
  5. 3
      qortal-ui-core/tooling/generateBuildConfig.js
  6. 2
      qortal-ui-core/tooling/generateES5BuildConfig.js
  7. 7
      qortal-ui-crypto/api/transactions/PublicizeTransaction.js
  8. 43
      qortal-ui-plugins/plugins/core/components/ChatPage.js
  9. 15
      qortal-ui-plugins/plugins/core/messaging/q-chat/q-chat.src.js

3
qortal-ui-core/language/us.json

@ -496,7 +496,8 @@
"cchange35": "Error when trying to fetch the user's name. Please try again!",
"cchange36": "Search Results",
"cchange37": "No Results Found",
"cchange38": "User Verified"
"cchange38": "User Verified",
"cchange39": "Cannot send an encrypted message to this user since they do not have their publickey on chain."
},
"welcomepage": {
"wcchange1": "Welcome to Q-Chat",

3
qortal-ui-core/package.json

@ -77,7 +77,8 @@
"rollup-plugin-postcss": "4.0.2",
"rollup-plugin-progress": "1.1.2",
"rollup-plugin-scss": "3.0.0",
"rollup-plugin-terser": "7.0.2"
"rollup-plugin-terser": "7.0.2",
"rollup-plugin-web-worker-loader": "^1.6.1"
},
"engines": {
"node": ">=16.15.0"

106
qortal-ui-core/src/components/app-info.js

@ -3,6 +3,8 @@ import { connect } from 'pwa-helpers'
import { store } from '../store.js'
import { doPageUrl } from '../redux/app/app-actions.js'
import { translate, translateUnsafeHTML } from 'lit-translate'
import WebWorker from 'web-worker:./computePowWorker.js';
import { routes } from '../plugins/routes.js';
import '@material/mwc-icon'
import '@material/mwc-button'
@ -94,6 +96,8 @@ class AppInfo extends connect(store)(LitElement) {
this.nodeStatus = {}
this.pageUrl = ''
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
this.publicKeyisOnChainConfirmation = false
this.interval
}
render() {
@ -107,10 +111,110 @@ class AppInfo extends connect(store)(LitElement) {
`
}
async confirmPublicKeyOnChain(address) {
const _computePow2 = async (chatBytes) => {
const difficulty = 15;
const path = window.parent.location.origin + '/memory-pow/memory-pow.wasm.full'
const worker = new WebWorker();
let nonce = null
let chatBytesArray = null
await new Promise((res, rej) => {
worker.postMessage({chatBytes, path, difficulty});
worker.onmessage = e => {
worker.terminate()
chatBytesArray = e.data.chatBytesArray
nonce = e.data.nonce
res()
}
})
let _response = await routes.sign_chat({
data: {
nonce: store.getState().app.selectedAddress.nonce,
chatBytesArray: chatBytesArray,
chatNonce: nonce
},
});
return _response
};
let stop = false
const checkPublicKey = async () => {
if (!stop) {
stop = true;
try {
const myNode = store.getState().app.nodeConfig.knownNodes[store.getState().app.nodeConfig.node];
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port;
const url = `${nodeUrl}/addresses/publickey/${address}`;
const res = await fetch(url)
let data = ''
try {
data = await res.text();
} catch (error) {
data = {
error: 'error'
}
}
if(data === 'false' && this.nodeInfo.isSynchronizing !== true){
let _reference = new Uint8Array(64);
window.crypto.getRandomValues(_reference);
let reference = window.parent.Base58.encode(_reference);
const chatRes = await routes.chat({
data: {
type: 19,
nonce: store.getState().app.selectedAddress.nonce,
params: {
lastReference: reference,
proofOfWorkNonce: 0,
fee: 0,
timestamp: Date.now(),
},
disableModal: true
},
disableModal: true,
});
try {
const powRes = await _computePow2(chatRes)
if(powRes === true){
clearInterval(this.interval)
this.publicKeyisOnChainConfirmation = true
}
} catch (error) {
console.error(error)
}
}
if (!data.error && data !== 'false' && data) {
clearInterval(this.interval)
this.publicKeyisOnChainConfirmation = true
}
} catch (error) {
}
stop = false
}
};
this.interval = setInterval(checkPublicKey, 5000);
}
firstUpdated() {
this.getNodeInfo()
this.getCoreInfo()
try {
this.confirmPublicKeyOnChain(store.getState().app.selectedAddress.address)
} catch (error) {
console.error(error)
}
setInterval(() => {
this.getNodeInfo()
this.getCoreInfo()

82
qortal-ui-core/src/components/computePowWorker.js

@ -0,0 +1,82 @@
import { Sha256 } from 'asmcrypto.js'
function sbrk(size, heap){
let brk = 512 * 1024 // stack top
let old = brk
brk += size
if (brk > heap.length)
throw new Error('heap exhausted')
return old
}
self.addEventListener('message', async e => {
const response = await computePow(e.data.chatBytes, e.data.path, e.data.difficulty)
postMessage(response)
})
const memory = new WebAssembly.Memory({ initial: 256, maximum: 256 })
const heap = new Uint8Array(memory.buffer)
const computePow = async (chatBytes, path, difficulty) => {
let response = null
await new Promise((resolve, reject)=> {
const _chatBytesArray = Object.keys(chatBytes).map(function (key) { return chatBytes[key]; });
const chatBytesArray = new Uint8Array(_chatBytesArray);
const chatBytesHash = new Sha256().process(chatBytesArray).finish().result;
const hashPtr = sbrk(32, heap);
const hashAry = new Uint8Array(memory.buffer, hashPtr, 32);
hashAry.set(chatBytesHash);
const workBufferLength = 8 * 1024 * 1024;
const workBufferPtr = sbrk(workBufferLength, heap);
const importObject = {
env: {
memory: memory
},
};
function loadWebAssembly(filename, imports) {
// Fetch the file and compile it
return fetch(filename)
.then(response => response.arrayBuffer())
.then(buffer => WebAssembly.compile(buffer))
.then(module => {
// Create the instance.
return new WebAssembly.Instance(module, importObject);
});
}
loadWebAssembly(path)
.then(wasmModule => {
response = {
nonce : wasmModule.exports.compute2(hashPtr, workBufferPtr, workBufferLength, difficulty),
chatBytesArray
}
resolve()
});
})
return response
}

3
qortal-ui-core/tooling/generateBuildConfig.js

@ -7,6 +7,8 @@ const commonjs = require('@rollup/plugin-commonjs')
const alias = require('@rollup/plugin-alias')
const { terser } = require('rollup-plugin-terser')
const scss = require('rollup-plugin-scss')
const webWorkerLoader = require('rollup-plugin-web-worker-loader');
const generateES5BuildConfig = require('./generateES5BuildConfig')
@ -61,6 +63,7 @@ const generateBuildConfig = ({ elementComponents, functionalComponents, otherOut
commonjs(),
globals(),
progress(),
webWorkerLoader(),
scss({
output: options.sassOutputDir
}),

2
qortal-ui-core/tooling/generateES5BuildConfig.js

@ -6,6 +6,7 @@ const progress = require('rollup-plugin-progress');
const { terser } = require("rollup-plugin-terser");
const path = require('path');
const alias = require('@rollup/plugin-alias');
const webWorkerLoader = require('rollup-plugin-web-worker-loader');
const generateRollupConfig = (file, { outputDir, aliases }) => {
@ -36,6 +37,7 @@ const generateRollupConfig = (file, { outputDir, aliases }) => {
}),
commonjs(),
progress(),
webWorkerLoader(),
babel.babel({
babelHelpers: 'bundled',
exclude: 'node_modules/**'

7
qortal-ui-crypto/api/transactions/PublicizeTransaction.js

@ -1,5 +1,6 @@
"use strict";
import ChatBase from "./chat/ChatBase.js"
import { QORT_DECIMALS } from "../constants.js"
export default class PublicizeTransaction extends ChatBase {
constructor() {
@ -11,13 +12,17 @@ export default class PublicizeTransaction extends ChatBase {
set proofOfWorkNonce(proofOfWorkNonce) {
this._proofOfWorkNonce = this.constructor.utils.int32ToBytes(proofOfWorkNonce)
}
set fee(fee) {
this._fee = fee * QORT_DECIMALS
this._feeBytes = this.constructor.utils.int64ToBytes(this._fee)
}
get params() {
const params = super.params;
params.push(
this._proofOfWorkNonce,
this._feeBytes
)
console.log({params})
return params;
}
}

43
qortal-ui-plugins/plugins/core/components/ChatPage.js

@ -1688,6 +1688,39 @@ class ChatPage extends LitElement {
}
async _sendMessage(outSideMsg) {
if(this.isReceipient){
let hasPublicKey = true
if(!this._publicKey.hasPubKey){
hasPublicKey = false
try {
const res = await parentEpml.request('apiCall', {
type: 'api',
url: `/addresses/publickey/${this.selectedAddress.address}`
})
if (res.error === 102) {
this._publicKey.key = ''
this._publicKey.hasPubKey = false
} else if (res !== false) {
this._publicKey.key = res
this._publicKey.hasPubKey = true
hasPublicKey = true
} else {
this._publicKey.key = ''
this._publicKey.hasPubKey = false
}
} catch (error) {
console.error(error);
}
if(!hasPublicKey || !this._publicKey.hasPubKey){
let err4string = get("chatpage.cchange39");
parentEpml.request('showSnackBar', `${err4string}`)
return
}
}
}
console.log(outSideMsg);
// have params to determine if it's a reply or not
// have variable to determine if it's a response, holds signature in constructor
// need original message signature
@ -2024,7 +2057,7 @@ class ChatPage extends LitElement {
message: messageText,
lastReference: reference,
proofOfWorkNonce: 0,
isEncrypted: this._publicKey.hasPubKey === false ? 0 : 1,
isEncrypted: 1,
isText: 1
}
});
@ -2108,6 +2141,12 @@ class ChatPage extends LitElement {
this.openForwardOpen = false;
this.chatEditor.enable();
if (isRecipient === true) {
if(!publicKey.hasPubKey){
let err4string = get("chatpage.cchange39");
parentEpml.request('showSnackBar', `${err4string}`)
getSendChatResponse(false)
return
}
let chatResponse = await parentEpml.request('chat', {
type: 18,
nonce: this.selectedAddress.nonce,
@ -2120,7 +2159,7 @@ class ChatPage extends LitElement {
message: messageText,
lastReference: reference,
proofOfWorkNonce: 0,
isEncrypted: publicKey.hasPubKey === false ? 0 : 1,
isEncrypted: 1,
isText: 1
}
});

15
qortal-ui-plugins/plugins/core/messaging/q-chat/q-chat.src.js

@ -200,7 +200,11 @@ class Chat extends LitElement {
</button>
<button
class="modal-button"
@click=${this._sendMessage}
@click=${()=> {
this.chatEditor.updateMirror()
this._sendMessage()
}}
?disabled="${this.isLoading}">
${this.isLoading === false
? this.renderSendText()
@ -507,9 +511,10 @@ class Chat extends LitElement {
_publicKey = addressPublicKey;
sendMessageRequest(isEncrypted, _publicKey);
} else {
isEncrypted = 0;
_publicKey = this.selectedAddress.address;
sendMessageRequest(isEncrypted, _publicKey);
let err4string = get("chatpage.cchange39");
parentEpml.request('showSnackBar', `${err4string}`);
this.chatEditor.enable();
this.isLoading = false;
}
};
let _reference = new Uint8Array(64);
@ -527,7 +532,7 @@ class Chat extends LitElement {
message: messageText,
lastReference: reference,
proofOfWorkNonce: 0,
isEncrypted: isEncrypted,
isEncrypted: 1,
isText: 1
}
});

Loading…
Cancel
Save