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?",
|
"bchange35": "Do you give this application permission to send coins?",
|
||||||
"bchange36": "Do you want to publish instant to QDN without computing proof-of-work?",
|
"bchange36": "Do you want to publish instant to QDN without computing proof-of-work?",
|
||||||
"bchange37": "Enter Fullscreen",
|
"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": {
|
"datapage": {
|
||||||
"dchange1": "Data Management",
|
"dchange1": "Data Management",
|
||||||
|
@ -1528,8 +1528,16 @@ class AppView extends connect(store)(LitElement) {
|
|||||||
</side-menu-item>
|
</side-menu-item>
|
||||||
</side-menu-item>
|
</side-menu-item>
|
||||||
|
|
||||||
<side-menu-item drawer-toggle label="${translate('sidemenu.websites')}" href="/app/websites">
|
<side-menu-item label="QDN" expanded>
|
||||||
<vaadin-icon icon="vaadin:desktop" slot="icon" ></vaadin-icon>
|
<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>
|
||||||
|
|
||||||
<side-menu-item drawer-toggle label="${translate('sidemenu.groups')}" href="/app/group-management">
|
<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 '../qort-theme-toggle.js'
|
||||||
|
|
||||||
import settings from '../../functional-components/settings-page.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.reduxStore = store
|
||||||
window.reduxAction = {
|
window.reduxAction = {
|
||||||
addAutoLoadImageChat: addAutoLoadImageChat,
|
addAutoLoadImageChat: addAutoLoadImageChat,
|
||||||
removeAutoLoadImageChat: removeAutoLoadImageChat,
|
removeAutoLoadImageChat: removeAutoLoadImageChat,
|
||||||
addChatLastSeen: addChatLastSeen
|
addChatLastSeen: addChatLastSeen,
|
||||||
|
allowQAPPAutoAuth: allowQAPPAutoAuth,
|
||||||
|
removeQAPPAutoAuth: removeQAPPAutoAuth,
|
||||||
|
allowQAPPAutoLists: allowQAPPAutoLists,
|
||||||
|
removeQAPPAutoLists: removeQAPPAutoLists
|
||||||
}
|
}
|
||||||
|
|
||||||
const animationDuration = 0.7 // Seconds
|
const animationDuration = 0.7 // Seconds
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { LitElement, html, css } from 'lit'
|
import { LitElement, html, css } from 'lit'
|
||||||
import { connect } from 'pwa-helpers'
|
import { connect } from 'pwa-helpers'
|
||||||
import { store } from '../../store.js'
|
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 { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||||
|
|
||||||
|
import '@material/mwc-checkbox'
|
||||||
import '@material/mwc-textfield'
|
import '@material/mwc-textfield'
|
||||||
import '@material/mwc-icon'
|
import '@material/mwc-icon'
|
||||||
import '@vaadin/password-field/vaadin-password-field.js'
|
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-body-text-color: var(--black);
|
||||||
--lumo-secondary-text-color: var(--sectxt);
|
--lumo-secondary-text-color: var(--sectxt);
|
||||||
--lumo-contrast-60pct: var(--vdicon);
|
--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 {
|
.center-box {
|
||||||
@ -37,6 +43,16 @@ class SecurityView extends connect(store)(LitElement) {
|
|||||||
text-align: center;
|
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 {
|
.q-button {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
flex-direction: column;
|
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 @click=${() => this.checkForDownload()} class="q-button"> ${translate("settings.download")} </div>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
@ -99,6 +128,21 @@ class SecurityView extends connect(store)(LitElement) {
|
|||||||
stateChanged(state) {
|
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() {
|
checkForDownload() {
|
||||||
const checkPass = this.shadowRoot.getElementById('downloadBackupPassword').value
|
const checkPass = this.shadowRoot.getElementById('downloadBackupPassword').value
|
||||||
if (checkPass === '') {
|
if (checkPass === '') {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Core App Actions here...
|
// 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) => {
|
export const doUpdateBlockInfo = (blockObj) => {
|
||||||
return (dispatch, getState) => {
|
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) => {
|
export const setChatLastSeen = (payload) => {
|
||||||
return {
|
return {
|
||||||
type: SET_CHAT_LAST_SEEN,
|
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 FRAME_PASTE_MENU_SWITCH = 'FRAME_PASTE_MENU_SWITCH'
|
||||||
export const ADD_AUTO_LOAD_IMAGES_CHAT = 'ADD_AUTO_LOAD_IMAGES_CHAT'
|
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 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 SET_CHAT_LAST_SEEN = 'SET_CHAT_LAST_SEEN'
|
||||||
export const ADD_CHAT_LAST_SEEN = 'ADD_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.
|
// Loading state, login state, isNavDrawOpen state etc. None of this needs to be saved to localstorage.
|
||||||
import { loadStateFromLocalStorage, saveStateToLocalStorage } from '../../localStorageHelpers.js'
|
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 { initWorkersReducer } from './reducers/init-workers.js'
|
||||||
import { loginReducer } from './reducers/login-reducer.js'
|
import { loginReducer } from './reducers/login-reducer.js'
|
||||||
import { setNode, addNode } from './reducers/manage-node.js'
|
import { setNode, addNode } from './reducers/manage-node.js'
|
||||||
@ -50,6 +50,8 @@ const INITIAL_STATE = {
|
|||||||
elementId: ''
|
elementId: ''
|
||||||
},
|
},
|
||||||
autoLoadImageChats: loadStateFromLocalStorage('autoLoadImageChats') || [],
|
autoLoadImageChats: loadStateFromLocalStorage('autoLoadImageChats') || [],
|
||||||
|
qAPPAutoAuth: loadStateFromLocalStorage('qAPPAutoAuth') || false,
|
||||||
|
qAPPAutoLists: loadStateFromLocalStorage('qAPPAutoLists') || false,
|
||||||
chatLastSeen: []
|
chatLastSeen: []
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,6 +177,38 @@ export default (state = INITIAL_STATE, action) => {
|
|||||||
autoLoadImageChats: updatedState
|
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: {
|
case SET_CHAT_LAST_SEEN: {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
@ -144,6 +144,10 @@ const generateForPlugins = () => {
|
|||||||
in: 'plugins/core/puzzles/puzzles.src.js',
|
in: 'plugins/core/puzzles/puzzles.src.js',
|
||||||
out: 'plugins/core/puzzles/puzzles.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) => {
|
].map((file) => {
|
||||||
return generateRollupConfig(
|
return generateRollupConfig(
|
||||||
path.join(__dirname, file.in),
|
path.join(__dirname, file.in),
|
||||||
|
@ -520,7 +520,7 @@ setOpenGifModal: { attribute: false }
|
|||||||
service: 'GIF_REPOSITORY',
|
service: 'GIF_REPOSITORY',
|
||||||
identifier: this.newCollectionName,
|
identifier: this.newCollectionName,
|
||||||
parentEpml,
|
parentEpml,
|
||||||
metaData: `title=${this.newCollectionName}`,
|
title: this.newCollectionName,
|
||||||
uploadType: 'zip',
|
uploadType: 'zip',
|
||||||
selectedAddress: this.selectedAddress,
|
selectedAddress: this.selectedAddress,
|
||||||
worker: this.webWorkerImage,
|
worker: this.webWorkerImage,
|
||||||
|
@ -3426,7 +3426,7 @@ class ChatPage extends LitElement {
|
|||||||
}],
|
}],
|
||||||
isImageDeleted: false,
|
isImageDeleted: false,
|
||||||
repliedTo: '',
|
repliedTo: '',
|
||||||
version: 2
|
version: 3
|
||||||
};
|
};
|
||||||
const stringifyMessageObject = JSON.stringify(messageObject);
|
const stringifyMessageObject = JSON.stringify(messageObject);
|
||||||
this.sendMessage(stringifyMessageObject, typeMessage);
|
this.sendMessage(stringifyMessageObject, typeMessage);
|
||||||
@ -3447,7 +3447,7 @@ class ChatPage extends LitElement {
|
|||||||
filePath: outSideMsg.filePath
|
filePath: outSideMsg.filePath
|
||||||
}],
|
}],
|
||||||
repliedTo: '',
|
repliedTo: '',
|
||||||
version: 2
|
version: 3
|
||||||
};
|
};
|
||||||
const stringifyMessageObject = JSON.stringify(messageObject);
|
const stringifyMessageObject = JSON.stringify(messageObject);
|
||||||
this.sendMessage(stringifyMessageObject, typeMessage);
|
this.sendMessage(stringifyMessageObject, typeMessage);
|
||||||
@ -3509,7 +3509,7 @@ class ChatPage extends LitElement {
|
|||||||
}],
|
}],
|
||||||
isAttachmentDeleted: false,
|
isAttachmentDeleted: false,
|
||||||
repliedTo: '',
|
repliedTo: '',
|
||||||
version: 2
|
version: 3
|
||||||
};
|
};
|
||||||
const stringifyMessageObject = JSON.stringify(messageObject);
|
const stringifyMessageObject = JSON.stringify(messageObject);
|
||||||
this.sendMessage(stringifyMessageObject, typeMessage);
|
this.sendMessage(stringifyMessageObject, typeMessage);
|
||||||
|
@ -412,7 +412,7 @@ class ChatWelcomePage extends LitElement {
|
|||||||
messageText,
|
messageText,
|
||||||
images: [''],
|
images: [''],
|
||||||
repliedTo: '',
|
repliedTo: '',
|
||||||
version: 1
|
version: 3
|
||||||
};
|
};
|
||||||
const stringifyMessageObject = JSON.stringify(messageObject);
|
const stringifyMessageObject = JSON.stringify(messageObject);
|
||||||
let chatResponse = await parentEpml.request('chat', {
|
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: [],
|
menus: [],
|
||||||
parent: false,
|
parent: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
url: 'qapps',
|
||||||
|
domain: 'core',
|
||||||
|
page: 'q-app/index.html',
|
||||||
|
title: 'Q-Apps',
|
||||||
|
icon: 'vaadin:desktop',
|
||||||
|
menus: [],
|
||||||
|
parent: false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
url: 'data-management',
|
url: 'data-management',
|
||||||
domain: 'core',
|
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.errorMessage = ''
|
||||||
this.successMessage = ''
|
this.successMessage = ''
|
||||||
let nonce = window.parent.computePow(hashPtr, workBufferPtr, workBufferLength, difficulty)
|
|
||||||
let response = false
|
let response = false
|
||||||
|
|
||||||
if (fee) {
|
if (fee) {
|
||||||
@ -657,6 +656,8 @@ class PublishData extends LitElement {
|
|||||||
arbitraryBytesForSigningBase58: convertedBytesBase58
|
arbitraryBytesForSigningBase58: convertedBytesBase58
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
const nonce = window.parent.computePow(hashPtr, workBufferPtr, workBufferLength, difficulty)
|
||||||
|
|
||||||
response = await parentEpml.request('sign_arbitrary', {
|
response = await parentEpml.request('sign_arbitrary', {
|
||||||
nonce: this.selectedAddress.nonce,
|
nonce: this.selectedAddress.nonce,
|
||||||
arbitraryBytesBase58: transactionBytesBase58,
|
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,
|
selectedAddress,
|
||||||
worker,
|
worker,
|
||||||
isBase64,
|
isBase64,
|
||||||
metaData
|
filename,
|
||||||
|
apiVersion,
|
||||||
|
withFee,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
category,
|
||||||
|
tag1,
|
||||||
|
tag2,
|
||||||
|
tag3,
|
||||||
|
tag4,
|
||||||
|
tag5
|
||||||
}) => {
|
}) => {
|
||||||
const validateName = async (receiverName) => {
|
const validateName = async (receiverName) => {
|
||||||
let nameRes = await parentEpml.request("apiCall", {
|
let nameRes = await parentEpml.request("apiCall", {
|
||||||
@ -44,7 +54,7 @@ export const publishData = async ({
|
|||||||
transactionBytesBase58
|
transactionBytesBase58
|
||||||
)
|
)
|
||||||
if (convertedBytesBase58.error) {
|
if (convertedBytesBase58.error) {
|
||||||
return
|
throw new Error('Error when signing');
|
||||||
}
|
}
|
||||||
|
|
||||||
const convertedBytes =
|
const convertedBytes =
|
||||||
@ -71,10 +81,38 @@ export const publishData = async ({
|
|||||||
arbitraryBytesBase58: transactionBytesBase58,
|
arbitraryBytesBase58: transactionBytesBase58,
|
||||||
arbitraryBytesForSigningBase58: convertedBytesBase58,
|
arbitraryBytesForSigningBase58: convertedBytesBase58,
|
||||||
arbitraryNonce: nonce,
|
arbitraryNonce: nonce,
|
||||||
|
apiVersion: apiVersion ? apiVersion : null
|
||||||
})
|
})
|
||||||
let myResponse = { error: "" }
|
let myResponse = { error: "" }
|
||||||
if (response === false) {
|
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 {
|
} else {
|
||||||
myResponse = response
|
myResponse = response
|
||||||
}
|
}
|
||||||
@ -85,21 +123,30 @@ export const publishData = async ({
|
|||||||
const validate = async () => {
|
const validate = async () => {
|
||||||
let validNameRes = await validateName(registeredName)
|
let validNameRes = await validateName(registeredName)
|
||||||
if (validNameRes.error) {
|
if (validNameRes.error) {
|
||||||
return
|
throw new Error('Name not found');
|
||||||
}
|
}
|
||||||
let transactionBytes = await uploadData(registeredName, path, file)
|
let transactionBytes = await uploadData(registeredName, path, file)
|
||||||
if (transactionBytes.error) {
|
if (transactionBytes.error) {
|
||||||
return
|
throw new Error(transactionBytes.message || 'Error when uploading');
|
||||||
} else if (
|
} else if (
|
||||||
transactionBytes.includes("Error 500 Internal Server Error")
|
transactionBytes.includes("Error 500 Internal Server Error")
|
||||||
) {
|
) {
|
||||||
return
|
throw new Error('Error when uploading');
|
||||||
}
|
}
|
||||||
|
|
||||||
let signAndProcessRes = await signAndProcess(transactionBytes)
|
let signAndProcessRes
|
||||||
if (signAndProcessRes.error) {
|
if(withFee){
|
||||||
return
|
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) => {
|
const uploadData = async (registeredName, path, file) => {
|
||||||
@ -131,10 +178,38 @@ export const publishData = async ({
|
|||||||
if (identifier != null && identifier.trim().length > 0) {
|
if (identifier != null && identifier.trim().length > 0) {
|
||||||
uploadDataUrl = `/arbitrary/${service}/${registeredName}/${identifier}${urlSuffix}?apiKey=${getApiKey()}`
|
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", {
|
let uploadDataRes = await parentEpml.request("apiCall", {
|
||||||
@ -147,7 +222,8 @@ export const publishData = async ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await validate()
|
const validateRes = await validate()
|
||||||
|
return validateRes
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new Error(error.message)
|
throw new Error(error.message)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user