mirror of
https://github.com/Qortal/qortal-ui.git
synced 2025-02-11 17:55:51 +00:00
Merge branch 'q-apps'
# Conflicts: # qortal-ui-core/language/us.json # qortal-ui-plugins/plugins/core/qdn/publish/publish.src.js
This commit is contained in:
commit
f1cb942816
@ -638,7 +638,13 @@
|
||||
"bchange35": "Do you give this application permission to send coins?",
|
||||
"bchange36": "Do you want to publish instant to QDN without computing proof-of-work?",
|
||||
"bchange37": "Enter Fullscreen",
|
||||
"bchange38": "Exit Fullscreen"
|
||||
"bchange38": "Exit Fullscreen",
|
||||
"bchange39": "Always allow lists to be retrieved automatically",
|
||||
"bchange40": "List",
|
||||
"bchange41": "Do you give this application permission to access this list?",
|
||||
"bchange42": "Items",
|
||||
"bchange43": "Do you give this application permission to add to this list?",
|
||||
"bchange44": "Do you give this application permission to delete from this list?"
|
||||
},
|
||||
"datapage": {
|
||||
"dchange1": "Data Management",
|
||||
|
@ -1528,8 +1528,16 @@ class AppView extends connect(store)(LitElement) {
|
||||
</side-menu-item>
|
||||
</side-menu-item>
|
||||
|
||||
<side-menu-item drawer-toggle label="${translate('sidemenu.websites')}" href="/app/websites">
|
||||
<vaadin-icon icon="vaadin:desktop" slot="icon" ></vaadin-icon>
|
||||
<side-menu-item label="QDN" expanded>
|
||||
<vaadin-icon icon="vaadin:cluster" slot="icon"></vaadin-icon>
|
||||
|
||||
<side-menu-item drawer-toggle label="${translate('sidemenu.websites')}" href="/app/websites">
|
||||
<vaadin-icon icon="vaadin:desktop" slot="icon" ></vaadin-icon>
|
||||
</side-menu-item>
|
||||
|
||||
<side-menu-item drawer-toggle label="Q-Apps" href="/app/qapps">
|
||||
<vaadin-icon icon="vaadin:external-browser" slot="icon" ></vaadin-icon>
|
||||
</side-menu-item>
|
||||
</side-menu-item>
|
||||
|
||||
<side-menu-item drawer-toggle label="${translate('sidemenu.groups')}" href="/app/group-management">
|
||||
|
@ -15,14 +15,17 @@ import './login-section.js'
|
||||
import '../qort-theme-toggle.js'
|
||||
|
||||
import settings from '../../functional-components/settings-page.js'
|
||||
import { addAutoLoadImageChat, removeAutoLoadImageChat, addChatLastSeen } from '../../redux/app/app-actions.js'
|
||||
import { addAutoLoadImageChat, removeAutoLoadImageChat, addChatLastSeen, allowQAPPAutoAuth, removeQAPPAutoAuth, removeQAPPAutoLists, allowQAPPAutoLists } from '../../redux/app/app-actions.js'
|
||||
|
||||
window.reduxStore = store
|
||||
window.reduxAction = {
|
||||
addAutoLoadImageChat: addAutoLoadImageChat,
|
||||
removeAutoLoadImageChat: removeAutoLoadImageChat,
|
||||
addChatLastSeen: addChatLastSeen
|
||||
|
||||
addChatLastSeen: addChatLastSeen,
|
||||
allowQAPPAutoAuth: allowQAPPAutoAuth,
|
||||
removeQAPPAutoAuth: removeQAPPAutoAuth,
|
||||
allowQAPPAutoLists: allowQAPPAutoLists,
|
||||
removeQAPPAutoLists: removeQAPPAutoLists
|
||||
}
|
||||
|
||||
const animationDuration = 0.7 // Seconds
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { LitElement, html, css } from 'lit'
|
||||
import { connect } from 'pwa-helpers'
|
||||
import { store } from '../../store.js'
|
||||
import { allowQAPPAutoAuth, removeQAPPAutoAuth, removeQAPPAutoLists, allowQAPPAutoLists } from '../../redux/app/app-actions.js'
|
||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||
|
||||
import '@material/mwc-checkbox'
|
||||
import '@material/mwc-textfield'
|
||||
import '@material/mwc-icon'
|
||||
import '@vaadin/password-field/vaadin-password-field.js'
|
||||
@ -27,6 +29,10 @@ class SecurityView extends connect(store)(LitElement) {
|
||||
--lumo-body-text-color: var(--black);
|
||||
--lumo-secondary-text-color: var(--sectxt);
|
||||
--lumo-contrast-60pct: var(--vdicon);
|
||||
--mdc-checkbox-unchecked-color: var(--black);
|
||||
--mdc-theme-on-surface: var(--black);
|
||||
--mdc-checkbox-disabled-color: var(--black);
|
||||
--mdc-checkbox-ink-color: var(--black);
|
||||
}
|
||||
|
||||
.center-box {
|
||||
@ -37,6 +43,16 @@ class SecurityView extends connect(store)(LitElement) {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.checkbox-row {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
font-family: Montserrat, sans-serif;
|
||||
font-weight: 600;
|
||||
color: var(--black);
|
||||
}
|
||||
|
||||
.q-button {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
@ -92,6 +108,19 @@ class SecurityView extends connect(store)(LitElement) {
|
||||
<div @click=${() => this.checkForDownload()} class="q-button"> ${translate("settings.download")} </div>
|
||||
</div>
|
||||
</div>
|
||||
<hr style="margin-top: 20px;">
|
||||
<div class="checkbox-row">
|
||||
<label for="authButton" id="authButtonLabel" style="color: var(--black);">
|
||||
${get('browserpage.bchange26')}
|
||||
</label>
|
||||
<mwc-checkbox style="margin-right: -15px;" id="authButton" @click=${(e) => this.checkForAuth(e)} ?checked=${store.getState().app.qAPPAutoAuth}></mwc-checkbox>
|
||||
</div>
|
||||
<div class="checkbox-row">
|
||||
<label for="authButton" id="authButtonLabel" style="color: var(--black);">
|
||||
${get('browserpage.bchange39')}
|
||||
</label>
|
||||
<mwc-checkbox style="margin-right: -15px;" id="authButton" @click=${(e) => this.checkForLists(e)} ?checked=${store.getState().app.qAPPAutoLists}></mwc-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
@ -99,6 +128,21 @@ class SecurityView extends connect(store)(LitElement) {
|
||||
stateChanged(state) {
|
||||
}
|
||||
|
||||
checkForAuth(e) {
|
||||
if (e.target.checked) {
|
||||
store.dispatch(removeQAPPAutoAuth(false))
|
||||
} else {
|
||||
store.dispatch(allowQAPPAutoAuth(true))
|
||||
}
|
||||
}
|
||||
checkForLists(e) {
|
||||
if (e.target.checked) {
|
||||
store.dispatch(removeQAPPAutoLists(false))
|
||||
} else {
|
||||
store.dispatch(allowQAPPAutoLists(true))
|
||||
}
|
||||
}
|
||||
|
||||
checkForDownload() {
|
||||
const checkPass = this.shadowRoot.getElementById('downloadBackupPassword').value
|
||||
if (checkPass === '') {
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Core App Actions here...
|
||||
import { UPDATE_BLOCK_INFO, UPDATE_NODE_STATUS, UPDATE_NODE_INFO, CHAT_HEADS, ACCOUNT_INFO, COPY_MENU_SWITCH, PASTE_MENU_SWITCH, FRAME_PASTE_MENU_SWITCH, ADD_AUTO_LOAD_IMAGES_CHAT, REMOVE_AUTO_LOAD_IMAGES_CHAT, SET_CHAT_LAST_SEEN, ADD_CHAT_LAST_SEEN } from '../app-action-types.js'
|
||||
import { UPDATE_BLOCK_INFO, UPDATE_NODE_STATUS, UPDATE_NODE_INFO, CHAT_HEADS, ACCOUNT_INFO, COPY_MENU_SWITCH, PASTE_MENU_SWITCH, FRAME_PASTE_MENU_SWITCH, ADD_AUTO_LOAD_IMAGES_CHAT, REMOVE_AUTO_LOAD_IMAGES_CHAT, ALLOW_QAPP_AUTO_AUTH, REMOVE_QAPP_AUTO_AUTH, SET_CHAT_LAST_SEEN, ADD_CHAT_LAST_SEEN, ALLOW_QAPP_AUTO_LISTS, REMOVE_QAPP_AUTO_LISTS } from '../app-action-types.js'
|
||||
|
||||
export const doUpdateBlockInfo = (blockObj) => {
|
||||
return (dispatch, getState) => {
|
||||
@ -120,6 +120,33 @@ export const removeAutoLoadImageChat = (payload) => {
|
||||
}
|
||||
}
|
||||
|
||||
export const allowQAPPAutoAuth = (payload) => {
|
||||
return {
|
||||
type: ALLOW_QAPP_AUTO_AUTH,
|
||||
payload
|
||||
}
|
||||
}
|
||||
|
||||
export const removeQAPPAutoAuth = (payload) => {
|
||||
return {
|
||||
type: REMOVE_QAPP_AUTO_AUTH,
|
||||
payload
|
||||
}
|
||||
}
|
||||
export const allowQAPPAutoLists = (payload) => {
|
||||
return {
|
||||
type: ALLOW_QAPP_AUTO_LISTS,
|
||||
payload
|
||||
}
|
||||
}
|
||||
|
||||
export const removeQAPPAutoLists = (payload) => {
|
||||
return {
|
||||
type: REMOVE_QAPP_AUTO_LISTS,
|
||||
payload
|
||||
}
|
||||
}
|
||||
|
||||
export const setChatLastSeen = (payload) => {
|
||||
return {
|
||||
type: SET_CHAT_LAST_SEEN,
|
||||
|
@ -22,5 +22,9 @@ export const PASTE_MENU_SWITCH = 'PASTE_MENU_SWITCH'
|
||||
export const FRAME_PASTE_MENU_SWITCH = 'FRAME_PASTE_MENU_SWITCH'
|
||||
export const ADD_AUTO_LOAD_IMAGES_CHAT = 'ADD_AUTO_LOAD_IMAGES_CHAT'
|
||||
export const REMOVE_AUTO_LOAD_IMAGES_CHAT = 'REMOVE_AUTO_LOAD_IMAGES_CHAT'
|
||||
export const ALLOW_QAPP_AUTO_AUTH = 'ALLOW_QAPP_AUTO_AUTH'
|
||||
export const REMOVE_QAPP_AUTO_AUTH = 'REMOVE_QAPP_AUTO_AUTH'
|
||||
export const ALLOW_QAPP_AUTO_LISTS = 'ALLOW_QAPP_AUTO_LISTS'
|
||||
export const REMOVE_QAPP_AUTO_LISTS = 'REMOVE_QAPP_AUTO_LISTS'
|
||||
export const SET_CHAT_LAST_SEEN = 'SET_CHAT_LAST_SEEN'
|
||||
export const ADD_CHAT_LAST_SEEN = 'ADD_CHAT_LAST_SEEN'
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Loading state, login state, isNavDrawOpen state etc. None of this needs to be saved to localstorage.
|
||||
import { loadStateFromLocalStorage, saveStateToLocalStorage } from '../../localStorageHelpers.js'
|
||||
import { LOG_IN, LOG_OUT, NETWORK_CONNECTION_STATUS, INIT_WORKERS, ADD_PLUGIN_URL, ADD_PLUGIN, ADD_NEW_PLUGIN_URL, NAVIGATE, SELECT_ADDRESS, ACCOUNT_INFO, CHAT_HEADS, UPDATE_BLOCK_INFO, UPDATE_NODE_STATUS, UPDATE_NODE_INFO, LOAD_NODE_CONFIG, SET_NODE, ADD_NODE, PAGE_URL, COPY_MENU_SWITCH, PASTE_MENU_SWITCH, FRAME_PASTE_MENU_SWITCH, ADD_AUTO_LOAD_IMAGES_CHAT, REMOVE_AUTO_LOAD_IMAGES_CHAT, SET_CHAT_LAST_SEEN, ADD_CHAT_LAST_SEEN } from './app-action-types.js'
|
||||
import { LOG_IN, LOG_OUT, NETWORK_CONNECTION_STATUS, INIT_WORKERS, ADD_PLUGIN_URL, ADD_PLUGIN, ADD_NEW_PLUGIN_URL, NAVIGATE, SELECT_ADDRESS, ACCOUNT_INFO, CHAT_HEADS, UPDATE_BLOCK_INFO, UPDATE_NODE_STATUS, UPDATE_NODE_INFO, LOAD_NODE_CONFIG, SET_NODE, ADD_NODE, PAGE_URL, COPY_MENU_SWITCH, PASTE_MENU_SWITCH, FRAME_PASTE_MENU_SWITCH, ADD_AUTO_LOAD_IMAGES_CHAT, REMOVE_AUTO_LOAD_IMAGES_CHAT, ALLOW_QAPP_AUTO_AUTH, REMOVE_QAPP_AUTO_AUTH, SET_CHAT_LAST_SEEN, ADD_CHAT_LAST_SEEN, ALLOW_QAPP_AUTO_LISTS, REMOVE_QAPP_AUTO_LISTS } from './app-action-types.js'
|
||||
import { initWorkersReducer } from './reducers/init-workers.js'
|
||||
import { loginReducer } from './reducers/login-reducer.js'
|
||||
import { setNode, addNode } from './reducers/manage-node.js'
|
||||
@ -50,6 +50,8 @@ const INITIAL_STATE = {
|
||||
elementId: ''
|
||||
},
|
||||
autoLoadImageChats: loadStateFromLocalStorage('autoLoadImageChats') || [],
|
||||
qAPPAutoAuth: loadStateFromLocalStorage('qAPPAutoAuth') || false,
|
||||
qAPPAutoLists: loadStateFromLocalStorage('qAPPAutoLists') || false,
|
||||
chatLastSeen: []
|
||||
}
|
||||
|
||||
@ -175,6 +177,38 @@ export default (state = INITIAL_STATE, action) => {
|
||||
autoLoadImageChats: updatedState
|
||||
}
|
||||
}
|
||||
|
||||
case ALLOW_QAPP_AUTO_AUTH: {
|
||||
saveStateToLocalStorage("qAPPAutoAuth", true)
|
||||
return {
|
||||
...state,
|
||||
qAPPAutoAuth: action.payload
|
||||
}
|
||||
}
|
||||
|
||||
case REMOVE_QAPP_AUTO_AUTH: {
|
||||
saveStateToLocalStorage("qAPPAutoAuth", false)
|
||||
return {
|
||||
...state,
|
||||
qAPPAutoAuth: action.payload
|
||||
}
|
||||
}
|
||||
case ALLOW_QAPP_AUTO_LISTS: {
|
||||
saveStateToLocalStorage("qAPPAutoLists", true)
|
||||
return {
|
||||
...state,
|
||||
qAPPAutoLists: action.payload
|
||||
}
|
||||
}
|
||||
|
||||
case REMOVE_QAPP_AUTO_LISTS: {
|
||||
saveStateToLocalStorage("qAPPAutoLists", false)
|
||||
return {
|
||||
...state,
|
||||
qAPPAutoLists: action.payload
|
||||
}
|
||||
}
|
||||
|
||||
case SET_CHAT_LAST_SEEN: {
|
||||
return {
|
||||
...state,
|
||||
|
@ -144,6 +144,10 @@ const generateForPlugins = () => {
|
||||
in: 'plugins/core/puzzles/puzzles.src.js',
|
||||
out: 'plugins/core/puzzles/puzzles.js',
|
||||
},
|
||||
{
|
||||
in: 'plugins/core/q-app/q-apps.src.js',
|
||||
out: 'plugins/core/q-app/q-apps.js',
|
||||
},
|
||||
].map((file) => {
|
||||
return generateRollupConfig(
|
||||
path.join(__dirname, file.in),
|
||||
|
@ -520,7 +520,7 @@ setOpenGifModal: { attribute: false }
|
||||
service: 'GIF_REPOSITORY',
|
||||
identifier: this.newCollectionName,
|
||||
parentEpml,
|
||||
metaData: `title=${this.newCollectionName}`,
|
||||
title: this.newCollectionName,
|
||||
uploadType: 'zip',
|
||||
selectedAddress: this.selectedAddress,
|
||||
worker: this.webWorkerImage,
|
||||
|
@ -3426,7 +3426,7 @@ class ChatPage extends LitElement {
|
||||
}],
|
||||
isImageDeleted: false,
|
||||
repliedTo: '',
|
||||
version: 2
|
||||
version: 3
|
||||
};
|
||||
const stringifyMessageObject = JSON.stringify(messageObject);
|
||||
this.sendMessage(stringifyMessageObject, typeMessage);
|
||||
@ -3447,7 +3447,7 @@ class ChatPage extends LitElement {
|
||||
filePath: outSideMsg.filePath
|
||||
}],
|
||||
repliedTo: '',
|
||||
version: 2
|
||||
version: 3
|
||||
};
|
||||
const stringifyMessageObject = JSON.stringify(messageObject);
|
||||
this.sendMessage(stringifyMessageObject, typeMessage);
|
||||
@ -3509,7 +3509,7 @@ class ChatPage extends LitElement {
|
||||
}],
|
||||
isAttachmentDeleted: false,
|
||||
repliedTo: '',
|
||||
version: 2
|
||||
version: 3
|
||||
};
|
||||
const stringifyMessageObject = JSON.stringify(messageObject);
|
||||
this.sendMessage(stringifyMessageObject, typeMessage);
|
||||
|
@ -412,7 +412,7 @@ class ChatWelcomePage extends LitElement {
|
||||
messageText,
|
||||
images: [''],
|
||||
repliedTo: '',
|
||||
version: 1
|
||||
version: 3
|
||||
};
|
||||
const stringifyMessageObject = JSON.stringify(messageObject);
|
||||
let chatResponse = await parentEpml.request('chat', {
|
||||
|
@ -0,0 +1,38 @@
|
||||
// GET_USER_ACCOUNT action
|
||||
export const GET_USER_ACCOUNT = 'GET_USER_ACCOUNT';
|
||||
|
||||
// LINK_TO_QDN_RESOURCE action
|
||||
export const LINK_TO_QDN_RESOURCE = 'LINK_TO_QDN_RESOURCE';
|
||||
|
||||
// QDN_RESOURCE_DISPLAYED action
|
||||
export const QDN_RESOURCE_DISPLAYED = 'QDN_RESOURCE_DISPLAYED';
|
||||
|
||||
// PUBLISH_QDN_RESOURCE action
|
||||
export const PUBLISH_QDN_RESOURCE = 'PUBLISH_QDN_RESOURCE';
|
||||
|
||||
// SEND_CHAT_MESSAGE action
|
||||
export const SEND_CHAT_MESSAGE = 'SEND_CHAT_MESSAGE';
|
||||
|
||||
// JOIN_GROUP action
|
||||
export const JOIN_GROUP = 'JOIN_GROUP';
|
||||
|
||||
// DEPLOY_AT action
|
||||
export const DEPLOY_AT = 'DEPLOY_AT';
|
||||
|
||||
// GET_WALLET_BALANCE action
|
||||
export const GET_WALLET_BALANCE = 'GET_WALLET_BALANCE';
|
||||
|
||||
// SEND_COIN action
|
||||
export const SEND_COIN = 'SEND_COIN';
|
||||
|
||||
// PUBLISH_MULTIPLE_QDN_RESOURCES
|
||||
export const PUBLISH_MULTIPLE_QDN_RESOURCES = 'PUBLISH_MULTIPLE_QDN_RESOURCES'
|
||||
|
||||
// GET_LIST_ITEMS
|
||||
export const GET_LIST_ITEMS = 'GET_LIST_ITEMS'
|
||||
|
||||
// ADD_LIST_ITEMS
|
||||
export const ADD_LIST_ITEMS = 'ADD_LIST_ITEMS'
|
||||
|
||||
// DELETE_LIST_ITEM
|
||||
export const DELETE_LIST_ITEM = 'DELETE_LIST_ITEM'
|
@ -97,6 +97,15 @@ parentEpml.ready().then(() => {
|
||||
menus: [],
|
||||
parent: false,
|
||||
},
|
||||
{
|
||||
url: 'qapps',
|
||||
domain: 'core',
|
||||
page: 'q-app/index.html',
|
||||
title: 'Q-Apps',
|
||||
icon: 'vaadin:desktop',
|
||||
menus: [],
|
||||
parent: false,
|
||||
},
|
||||
{
|
||||
url: 'data-management',
|
||||
domain: 'core',
|
||||
|
55
qortal-ui-plugins/plugins/core/q-app/index.html
Normal file
55
qortal-ui-plugins/plugins/core/q-app/index.html
Normal file
@ -0,0 +1,55 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<link rel="stylesheet" href="/font/material-icons.css">
|
||||
<link rel="stylesheet" href="/font/switch-theme.css">
|
||||
<script>
|
||||
const checkBack = localStorage.getItem('qortalTheme')
|
||||
if (checkBack === 'dark') {
|
||||
newtheme = 'dark';
|
||||
} else {
|
||||
newtheme = 'light';
|
||||
}
|
||||
document.querySelector('html').setAttribute('theme', newtheme);
|
||||
</script>
|
||||
<style>
|
||||
html {
|
||||
--scrollbarBG: #a1a1a1;
|
||||
--thumbBG: #6a6c75;
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar {
|
||||
width: 11px;
|
||||
}
|
||||
|
||||
* {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: var(--thumbBG) var(--scrollbarBG);
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar-track {
|
||||
background: var(--scrollbarBG);
|
||||
}
|
||||
|
||||
*::-webkit-scrollbar-thumb {
|
||||
background-color: var(--thumbBG);
|
||||
border-radius: 6px;
|
||||
border: 3px solid var(--scrollbarBG);
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: "Roboto", sans-serif;
|
||||
background: var(--plugback);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<q-apps></q-apps>
|
||||
<script src="q-apps.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
1233
qortal-ui-plugins/plugins/core/q-app/q-apps.src.js
Normal file
1233
qortal-ui-plugins/plugins/core/q-app/q-apps.src.js
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
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.convertedBytes, e.data.path)
|
||||
postMessage(response)
|
||||
|
||||
})
|
||||
|
||||
|
||||
const memory = new WebAssembly.Memory({ initial: 256, maximum: 256 })
|
||||
const heap = new Uint8Array(memory.buffer)
|
||||
|
||||
|
||||
|
||||
const computePow = async (convertedBytes, path) => {
|
||||
|
||||
|
||||
let response = null
|
||||
|
||||
await new Promise((resolve, reject)=> {
|
||||
|
||||
const _convertedBytesArray = Object.keys(convertedBytes).map(
|
||||
function (key) {
|
||||
return convertedBytes[key]
|
||||
}
|
||||
)
|
||||
const convertedBytesArray = new Uint8Array(_convertedBytesArray)
|
||||
const convertedBytesHash = new Sha256()
|
||||
.process(convertedBytesArray)
|
||||
.finish().result
|
||||
const hashPtr = sbrk(32, heap)
|
||||
const hashAry = new Uint8Array(
|
||||
memory.buffer,
|
||||
hashPtr,
|
||||
32
|
||||
)
|
||||
|
||||
hashAry.set(convertedBytesHash)
|
||||
const difficulty = 14
|
||||
const workBufferLength = 8 * 1024 * 1024
|
||||
const workBufferPtr = sbrk(
|
||||
workBufferLength,
|
||||
heap
|
||||
)
|
||||
|
||||
const importObject = {
|
||||
env: {
|
||||
memory: memory
|
||||
},
|
||||
};
|
||||
|
||||
function loadWebAssembly(filename, imports) {
|
||||
return fetch(filename)
|
||||
.then(response => response.arrayBuffer())
|
||||
.then(buffer => WebAssembly.compile(buffer))
|
||||
.then(module => {
|
||||
return new WebAssembly.Instance(module, importObject);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
loadWebAssembly(path)
|
||||
.then(wasmModule => {
|
||||
response = {
|
||||
nonce : wasmModule.exports.compute2(hashPtr, workBufferPtr, workBufferLength, difficulty),
|
||||
|
||||
}
|
||||
resolve()
|
||||
|
||||
});
|
||||
|
||||
|
||||
})
|
||||
|
||||
return response
|
||||
}
|
@ -647,7 +647,6 @@ class PublishData extends LitElement {
|
||||
|
||||
this.errorMessage = ''
|
||||
this.successMessage = ''
|
||||
let nonce = window.parent.computePow(hashPtr, workBufferPtr, workBufferLength, difficulty)
|
||||
let response = false
|
||||
|
||||
if (fee) {
|
||||
@ -657,6 +656,8 @@ class PublishData extends LitElement {
|
||||
arbitraryBytesForSigningBase58: convertedBytesBase58
|
||||
})
|
||||
} else {
|
||||
const nonce = window.parent.computePow(hashPtr, workBufferPtr, workBufferLength, difficulty)
|
||||
|
||||
response = await parentEpml.request('sign_arbitrary', {
|
||||
nonce: this.selectedAddress.nonce,
|
||||
arbitraryBytesBase58: transactionBytesBase58,
|
||||
|
52
qortal-ui-plugins/plugins/utils/loader.js
Normal file
52
qortal-ui-plugins/plugins/utils/loader.js
Normal file
@ -0,0 +1,52 @@
|
||||
export class Loader {
|
||||
constructor() {
|
||||
this.loader = document.createElement("div");
|
||||
this.loader.className = "loader";
|
||||
this.loader.innerHTML = `
|
||||
<div class="loader-spinner"></div>
|
||||
`;
|
||||
this.styles = document.createElement("style");
|
||||
this.styles.innerHTML = `
|
||||
.loader {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 1000001
|
||||
}
|
||||
|
||||
.loader-spinner {
|
||||
border: 4px solid #f3f3f3;
|
||||
border-top: 4px solid #3498db;
|
||||
border-radius: 50%;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
show() {
|
||||
document.head.appendChild(this.styles);
|
||||
document.body.appendChild(this.loader);
|
||||
}
|
||||
|
||||
hide() {
|
||||
if (this.loader.parentNode) {
|
||||
this.loader.parentNode.removeChild(this.loader);
|
||||
}
|
||||
if (this.styles.parentNode) {
|
||||
this.styles.parentNode.removeChild(this.styles);
|
||||
}
|
||||
}
|
||||
}
|
@ -18,7 +18,17 @@ export const publishData = async ({
|
||||
selectedAddress,
|
||||
worker,
|
||||
isBase64,
|
||||
metaData
|
||||
filename,
|
||||
apiVersion,
|
||||
withFee,
|
||||
title,
|
||||
description,
|
||||
category,
|
||||
tag1,
|
||||
tag2,
|
||||
tag3,
|
||||
tag4,
|
||||
tag5
|
||||
}) => {
|
||||
const validateName = async (receiverName) => {
|
||||
let nameRes = await parentEpml.request("apiCall", {
|
||||
@ -44,7 +54,7 @@ export const publishData = async ({
|
||||
transactionBytesBase58
|
||||
)
|
||||
if (convertedBytesBase58.error) {
|
||||
return
|
||||
throw new Error('Error when signing');
|
||||
}
|
||||
|
||||
const convertedBytes =
|
||||
@ -71,10 +81,38 @@ export const publishData = async ({
|
||||
arbitraryBytesBase58: transactionBytesBase58,
|
||||
arbitraryBytesForSigningBase58: convertedBytesBase58,
|
||||
arbitraryNonce: nonce,
|
||||
apiVersion: apiVersion ? apiVersion : null
|
||||
})
|
||||
let myResponse = { error: "" }
|
||||
if (response === false) {
|
||||
return
|
||||
throw new Error('Error when signing');
|
||||
} else {
|
||||
myResponse = response
|
||||
}
|
||||
|
||||
return myResponse
|
||||
}
|
||||
|
||||
const signAndProcessWithFee = async (transactionBytesBase58) => {
|
||||
let convertedBytesBase58 = await convertBytesForSigning(
|
||||
transactionBytesBase58
|
||||
)
|
||||
if (convertedBytesBase58.error) {
|
||||
throw new Error('Error when signing');
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
let response = await parentEpml.request("sign_arbitrary_with_fee", {
|
||||
nonce: selectedAddress.nonce,
|
||||
arbitraryBytesBase58: transactionBytesBase58,
|
||||
arbitraryBytesForSigningBase58: convertedBytesBase58,
|
||||
apiVersion: apiVersion ? apiVersion : null
|
||||
})
|
||||
let myResponse = { error: "" }
|
||||
if (response === false) {
|
||||
throw new Error('Error when signing');
|
||||
} else {
|
||||
myResponse = response
|
||||
}
|
||||
@ -85,21 +123,30 @@ export const publishData = async ({
|
||||
const validate = async () => {
|
||||
let validNameRes = await validateName(registeredName)
|
||||
if (validNameRes.error) {
|
||||
return
|
||||
throw new Error('Name not found');
|
||||
}
|
||||
let transactionBytes = await uploadData(registeredName, path, file)
|
||||
if (transactionBytes.error) {
|
||||
return
|
||||
throw new Error(transactionBytes.message || 'Error when uploading');
|
||||
} else if (
|
||||
transactionBytes.includes("Error 500 Internal Server Error")
|
||||
) {
|
||||
return
|
||||
throw new Error('Error when uploading');
|
||||
}
|
||||
|
||||
let signAndProcessRes = await signAndProcess(transactionBytes)
|
||||
if (signAndProcessRes.error) {
|
||||
return
|
||||
let signAndProcessRes
|
||||
if(withFee){
|
||||
signAndProcessRes = await signAndProcessWithFee(transactionBytes)
|
||||
|
||||
}
|
||||
if(!withFee){
|
||||
signAndProcessRes = await signAndProcess(transactionBytes)
|
||||
|
||||
}
|
||||
if (signAndProcessRes.error) {
|
||||
throw new Error('Error when signing');
|
||||
}
|
||||
return signAndProcessRes
|
||||
}
|
||||
|
||||
const uploadData = async (registeredName, path, file) => {
|
||||
@ -131,10 +178,38 @@ export const publishData = async ({
|
||||
if (identifier != null && identifier.trim().length > 0) {
|
||||
uploadDataUrl = `/arbitrary/${service}/${registeredName}/${identifier}${urlSuffix}?apiKey=${getApiKey()}`
|
||||
|
||||
if(metaData){
|
||||
uploadDataUrl = `/arbitrary/${service}/${registeredName}/${identifier}${urlSuffix}?${metaData}&apiKey=${getApiKey()}`
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(withFee){
|
||||
uploadDataUrl = uploadDataUrl + '&fee=100000'
|
||||
}
|
||||
|
||||
if(filename != null && filename != "undefined"){
|
||||
uploadDataUrl = uploadDataUrl + '&filename=' + encodeURIComponent(filename)
|
||||
}
|
||||
if(title != null && title != "undefined"){
|
||||
uploadDataUrl = uploadDataUrl + '&title=' + encodeURIComponent(title)
|
||||
}
|
||||
if(description != null && description != "undefined"){
|
||||
uploadDataUrl = uploadDataUrl + '&description=' + encodeURIComponent(description)
|
||||
}
|
||||
if(category != null && category != "undefined"){
|
||||
uploadDataUrl = uploadDataUrl + '&category=' + encodeURIComponent(category)
|
||||
}
|
||||
if(tag1 != null && tag1 != "undefined"){
|
||||
uploadDataUrl = uploadDataUrl + '&tags=' + encodeURIComponent(tag1)
|
||||
}
|
||||
if(tag2 != null && tag2 != "undefined"){
|
||||
uploadDataUrl = uploadDataUrl + '&tags=' + encodeURIComponent(tag2)
|
||||
}
|
||||
if(tag3 != null && tag3 != "undefined"){
|
||||
uploadDataUrl = uploadDataUrl + '&tags=' + encodeURIComponent(tag3)
|
||||
}
|
||||
if(tag4 != null && tag4 != "undefined"){
|
||||
uploadDataUrl = uploadDataUrl + '&tags=' + encodeURIComponent(tag4)
|
||||
}
|
||||
if(tag5 != null && tag5 != "undefined"){
|
||||
uploadDataUrl = uploadDataUrl + '&tags=' + encodeURIComponent(tag5)
|
||||
}
|
||||
|
||||
let uploadDataRes = await parentEpml.request("apiCall", {
|
||||
@ -147,7 +222,8 @@ export const publishData = async ({
|
||||
}
|
||||
}
|
||||
try {
|
||||
await validate()
|
||||
const validateRes = await validate()
|
||||
return validateRes
|
||||
} catch (error) {
|
||||
throw new Error(error.message)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user