commit
516804cf70
@ -7,24 +7,16 @@
|
||||
"version": 1,
|
||||
"updated": 1696646223261,
|
||||
"title": "Q-Blog Post creations",
|
||||
"description": "blablabla",
|
||||
"description": "Get your friends Q-Blog posts on your feed",
|
||||
"search": {
|
||||
"query": "-post-",
|
||||
"identifier": "q-blog-",
|
||||
"service": "BLOG_POST",
|
||||
"exactmatchnames": true
|
||||
},
|
||||
"click": "qortal://APP/Q-Blog/$${resource.name}$$/$${customParams.blogId}$$/$${customParams.shortIdentifier}$$",
|
||||
"click": "qortal://APP/Q-Blog/$${resource.name}$$/blog/$${resource.identifier}$$",
|
||||
"display": {
|
||||
"title": "$${rawdata.title}$$"
|
||||
},
|
||||
"customParams": {
|
||||
"blogId": "**methods.getBlogId(resource)**",
|
||||
"shortIdentifier": "**methods.getShortId(resource)**"
|
||||
},
|
||||
"methods": {
|
||||
"getShortId": "return resource.identifier.split('-post-')[1];",
|
||||
"getBlogId": "const arr = resource.identifier.split('-post-'); const id = arr[0]; return id.startsWith('q-blog-') ? id.substring(7) : id;"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -729,7 +729,10 @@
|
||||
"bchange46": "Do you give this application permission to save the following file",
|
||||
"bchange47": "Instant publish - requires",
|
||||
"bchange48": "Do you give this application permission to send you notifications",
|
||||
"bchange49": "Do you give this application permission to get your wallet information?"
|
||||
"bchange49": "Do you grant this application permission to access the following private information from your profile?",
|
||||
"bchange50": "This app has requested a change to your public profile. Property: ",
|
||||
"bchange51": "To submit the changes don't forget to click on 'Update profile'",
|
||||
"bchange52": "Do you give this application permission to get your wallet information?"
|
||||
},
|
||||
"datapage": {
|
||||
"dchange1": "Data Management",
|
||||
@ -1214,5 +1217,28 @@
|
||||
"saving2": "Nothing to save",
|
||||
"saving3": "Save unsaved changes",
|
||||
"saving4": "Undo changes"
|
||||
},
|
||||
"profile": {
|
||||
"profile1": "You do not have a name",
|
||||
"profile2": "Go to name registration",
|
||||
"profile3": "Update profile",
|
||||
"profile4": "Tagline",
|
||||
"profile5": "Bio",
|
||||
"profile6": "Wallet Addresses",
|
||||
"profile7": "Fill from UI",
|
||||
"profile8": "Add custom property",
|
||||
"profile9": "Property name",
|
||||
"profile10": "Fields",
|
||||
"profile11": "Add new field",
|
||||
"profile12": "Field name",
|
||||
"profile13": "Fill out",
|
||||
"profile14": "Activity",
|
||||
"profile15": "No value",
|
||||
"profile16": "This name has no profile",
|
||||
"profile17": "Unable to fetch profile",
|
||||
"profile18": "Open profile",
|
||||
"profile19": "Cannot fetch profile",
|
||||
"profile20": "Register name",
|
||||
"profile21": "Insert address from UI"
|
||||
}
|
||||
}
|
5
core/src/components/WebWorkerFile.js
Normal file
5
core/src/components/WebWorkerFile.js
Normal file
@ -0,0 +1,5 @@
|
||||
import WebWorker from 'web-worker:./computePowWorkerFile.js';
|
||||
|
||||
// You can add any initialization or configuration for the Web Worker here
|
||||
|
||||
export default WebWorker;
|
@ -1,12 +1,12 @@
|
||||
import {css, html, LitElement} from 'lit'
|
||||
import {connect} from 'pwa-helpers'
|
||||
import {store} from '../store.js'
|
||||
import {Epml} from '../epml.js'
|
||||
import {addTradeBotRoutes} from '../tradebot/addTradeBotRoutes.js'
|
||||
import {get, translate} from 'lit-translate'
|
||||
import { css, html, LitElement } from 'lit'
|
||||
import { connect } from 'pwa-helpers'
|
||||
import { store } from '../store.js'
|
||||
import { Epml } from '../epml.js'
|
||||
import { addTradeBotRoutes } from '../tradebot/addTradeBotRoutes.js'
|
||||
import { get, translate } from 'lit-translate'
|
||||
import localForage from 'localforage'
|
||||
import {decryptData, encryptData} from '../lockScreen.js'
|
||||
import {setChatLastSeen} from '../redux/app/app-actions.js'
|
||||
import { decryptData, encryptData } from '../lockScreen.js'
|
||||
import { setChatLastSeen } from '../redux/app/app-actions.js'
|
||||
import isElectron from 'is-electron'
|
||||
import '@material/mwc-button'
|
||||
import '@material/mwc-icon'
|
||||
@ -41,6 +41,7 @@ import './notification-view/notification-bell-general.js'
|
||||
import './friends-view/friends-side-panel-parent.js'
|
||||
import './friends-view/save-settings-qdn.js'
|
||||
import './friends-view/core-sync-status.js'
|
||||
import './friends-view/profile.js'
|
||||
import './controllers/coin-balances-controller.js'
|
||||
|
||||
const chatLastSeen = localForage.createInstance({
|
||||
@ -564,7 +565,8 @@ class AppView extends connect(store)(LitElement) {
|
||||
<img src="${this.config.coin.logo}" style="height:32px; padding-left:12px;">
|
||||
</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 20px">
|
||||
<div style="display:flex;align-items:center;gap:20px">
|
||||
<profile-qdn></profile-qdn>
|
||||
<friends-side-panel-parent></friends-side-panel-parent>
|
||||
<notification-bell></notification-bell>
|
||||
<notification-bell-general></notification-bell-general>
|
||||
@ -705,11 +707,11 @@ class AppView extends connect(store)(LitElement) {
|
||||
var drawerTog = this.shadowRoot.getElementById("mb")
|
||||
var drawerOut = this.shadowRoot.getElementById("appsidebar")
|
||||
|
||||
drawerTog.addEventListener('mouseover', function() {
|
||||
drawerTog.addEventListener('mouseover', function () {
|
||||
drawerTog.click()
|
||||
})
|
||||
|
||||
drawerOut.addEventListener('mouseleave', function() {
|
||||
drawerOut.addEventListener('mouseleave', function () {
|
||||
drawerTog.click()
|
||||
})
|
||||
|
||||
|
92
core/src/components/computePowWorkerFile.js
Normal file
92
core/src/components/computePowWorkerFile.js
Normal file
@ -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
|
||||
}
|
310
core/src/components/friends-view/avatar.js
Normal file
310
core/src/components/friends-view/avatar.js
Normal file
@ -0,0 +1,310 @@
|
||||
import { LitElement, html, css } from 'lit';
|
||||
import { get, translate } from 'lit-translate';
|
||||
import axios from 'axios';
|
||||
import '@material/mwc-menu';
|
||||
import '@material/mwc-list/mwc-list-item.js';
|
||||
import { RequestQueueWithPromise } from '../../../../plugins/plugins/utils/queue';
|
||||
import '../../../../plugins/plugins/core/components/TimeAgo';
|
||||
import { connect } from 'pwa-helpers';
|
||||
import { store } from '../../store';
|
||||
import { setNewTab } from '../../redux/app/app-actions';
|
||||
import ShortUniqueId from 'short-unique-id';
|
||||
|
||||
const requestQueue = new RequestQueueWithPromise(3);
|
||||
const requestQueueRawData = new RequestQueueWithPromise(3);
|
||||
const requestQueueStatus = new RequestQueueWithPromise(3);
|
||||
|
||||
export class AvatarComponent extends connect(store)(LitElement) {
|
||||
static get properties() {
|
||||
return {
|
||||
resource: { type: Object },
|
||||
isReady: { type: Boolean },
|
||||
status: { type: Object },
|
||||
name: { type: String },
|
||||
};
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return css`
|
||||
* {
|
||||
--mdc-theme-text-primary-on-background: var(--black);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
:host {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
img {
|
||||
width: 100%;
|
||||
max-height: 30vh;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
.smallLoading,
|
||||
.smallLoading:after {
|
||||
border-radius: 50%;
|
||||
width: 2px;
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
.defaultSize {
|
||||
width: 100%;
|
||||
height: 160px;
|
||||
}
|
||||
.parent-feed-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
background-color: var(--chat-bubble-bg);
|
||||
flex-grow: 0;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
border-radius: 5px;
|
||||
padding: 12px 15px 4px 15px;
|
||||
min-width: 150px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
}
|
||||
.avatar {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.avatarApp {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.feed-item-name {
|
||||
user-select: none;
|
||||
color: #03a9f4;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.app-name {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
mwc-menu {
|
||||
position: absolute;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.resource = {
|
||||
identifier: '',
|
||||
name: '',
|
||||
service: '',
|
||||
};
|
||||
this.status = {
|
||||
status: '',
|
||||
};
|
||||
this.isReady = false;
|
||||
this.nodeUrl = this.getNodeUrl();
|
||||
this.myNode = this.getMyNode();
|
||||
this.isFetching = false;
|
||||
this.uid = new ShortUniqueId();
|
||||
}
|
||||
getNodeUrl() {
|
||||
const myNode =
|
||||
window.parent.reduxStore.getState().app.nodeConfig.knownNodes[
|
||||
window.parent.reduxStore.getState().app.nodeConfig.node
|
||||
];
|
||||
|
||||
const nodeUrl =
|
||||
myNode.protocol + '://' + myNode.domain + ':' + myNode.port;
|
||||
return nodeUrl;
|
||||
}
|
||||
getMyNode() {
|
||||
const myNode =
|
||||
window.parent.reduxStore.getState().app.nodeConfig.knownNodes[
|
||||
window.parent.reduxStore.getState().app.nodeConfig.node
|
||||
];
|
||||
|
||||
return myNode;
|
||||
}
|
||||
|
||||
getApiKey() {
|
||||
const myNode =
|
||||
window.parent.reduxStore.getState().app.nodeConfig.knownNodes[
|
||||
window.parent.reduxStore.getState().app.nodeConfig.node
|
||||
];
|
||||
let apiKey = myNode.apiKey;
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
async fetchResource() {
|
||||
try {
|
||||
if (this.isFetching) return;
|
||||
this.isFetching = true;
|
||||
await axios.get(
|
||||
`${this.nodeUrl}/arbitrary/resource/properties/${this.resource.service}/${this.resource.name}/${this.resource.identifier}?apiKey=${this.myNode.apiKey}`
|
||||
);
|
||||
this.isFetching = false;
|
||||
} catch (error) {
|
||||
this.isFetching = false;
|
||||
}
|
||||
}
|
||||
|
||||
async fetchVideoUrl() {
|
||||
this.fetchResource();
|
||||
}
|
||||
|
||||
async getRawData() {
|
||||
const url = `${this.nodeUrl}/arbitrary/${this.resource.service}/${this.resource.name}/${this.resource.identifier}?apiKey=${this.myNode.apiKey}`;
|
||||
return await requestQueueRawData.enqueue(() => {
|
||||
return axios.get(url);
|
||||
});
|
||||
// const response2 = await fetch(url, {
|
||||
// method: 'GET',
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/json'
|
||||
// }
|
||||
// })
|
||||
|
||||
// const responseData2 = await response2.json()
|
||||
// return responseData2
|
||||
}
|
||||
|
||||
updateDisplayWithPlaceholders(display, resource, rawdata) {
|
||||
const pattern = /\$\$\{([a-zA-Z0-9_\.]+)\}\$\$/g;
|
||||
|
||||
for (const key in display) {
|
||||
const value = display[key];
|
||||
|
||||
display[key] = value.replace(pattern, (match, p1) => {
|
||||
if (p1.startsWith('rawdata.')) {
|
||||
const dataKey = p1.split('.')[1];
|
||||
if (rawdata[dataKey] === undefined) {
|
||||
console.error('rawdata key not found:', dataKey);
|
||||
}
|
||||
return rawdata[dataKey] || match;
|
||||
} else if (p1.startsWith('resource.')) {
|
||||
const resourceKey = p1.split('.')[1];
|
||||
if (resource[resourceKey] === undefined) {
|
||||
console.error('resource key not found:', resourceKey);
|
||||
}
|
||||
return resource[resourceKey] || match;
|
||||
}
|
||||
return match;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async fetchStatus() {
|
||||
let isCalling = false;
|
||||
let percentLoaded = 0;
|
||||
let timer = 24;
|
||||
const response = await requestQueueStatus.enqueue(() => {
|
||||
return axios.get(
|
||||
`${this.nodeUrl}/arbitrary/resource/status/${this.resource.service}/${this.resource.name}/${this.resource.identifier}?apiKey=${this.myNode.apiKey}`
|
||||
);
|
||||
});
|
||||
if (response && response.data && response.data.status === 'READY') {
|
||||
this.status = response.data;
|
||||
|
||||
return;
|
||||
}
|
||||
const intervalId = setInterval(async () => {
|
||||
if (isCalling) return;
|
||||
isCalling = true;
|
||||
|
||||
const data = await requestQueue.enqueue(() => {
|
||||
return axios.get(
|
||||
`${this.nodeUrl}/arbitrary/resource/status/${this.resource.service}/${this.resource.name}/${this.resource.identifier}?apiKey=${this.myNode.apiKey}`
|
||||
);
|
||||
});
|
||||
const res = data.data;
|
||||
|
||||
isCalling = false;
|
||||
if (res.localChunkCount) {
|
||||
if (res.percentLoaded) {
|
||||
if (
|
||||
res.percentLoaded === percentLoaded &&
|
||||
res.percentLoaded !== 100
|
||||
) {
|
||||
timer = timer - 5;
|
||||
} else {
|
||||
timer = 24;
|
||||
}
|
||||
if (timer < 0) {
|
||||
clearInterval(intervalId);
|
||||
}
|
||||
percentLoaded = res.percentLoaded;
|
||||
}
|
||||
|
||||
this.status = res;
|
||||
if (this.status.status === 'DOWNLOADED') {
|
||||
this.fetchResource();
|
||||
}
|
||||
}
|
||||
|
||||
// check if progress is 100% and clear interval if true
|
||||
if (res.status === 'READY') {
|
||||
clearInterval(intervalId);
|
||||
this.status = res;
|
||||
this.isReady = true;
|
||||
}
|
||||
}, 5000); // 1 second interval
|
||||
}
|
||||
|
||||
async _fetchImage() {
|
||||
try {
|
||||
this.fetchVideoUrl();
|
||||
this.fetchStatus();
|
||||
} catch (error) {
|
||||
/* empty */
|
||||
}
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
this._fetchImage();
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log('hello', this.name, this.resource, this.status);
|
||||
return html`
|
||||
<div>
|
||||
${this.status.status !== 'READY'
|
||||
? html`
|
||||
<mwc-icon style="user-select:none;"
|
||||
>account_circle</mwc-icon
|
||||
>
|
||||
`
|
||||
: ''}
|
||||
${this.status.status === 'READY'
|
||||
? html`
|
||||
<div
|
||||
style="height: 24px;width: 24px;overflow: hidden;"
|
||||
>
|
||||
<img
|
||||
src="${this
|
||||
.nodeUrl}/arbitrary/THUMBNAIL/${this
|
||||
.name}/qortal_avatar?async=true&apiKey=${this
|
||||
.myNode.apiKey}"
|
||||
style="width:100%; height:100%;border-radius:50%"
|
||||
onerror="this.onerror=null; this.src='/img/incognito.png';"
|
||||
/>
|
||||
</div>
|
||||
`
|
||||
: ''}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('avatar-component', AvatarComponent);
|
@ -134,7 +134,7 @@ class FriendsFeed extends connect(store)(LitElement) {
|
||||
this.endpointOffsets = Array(this.endpoints.length).fill(0);
|
||||
return
|
||||
}
|
||||
const baseurl = `${this.nodeUrl}/arbitrary/resources/search?reverse=true&exactmatchnames=true&${names}`
|
||||
const baseurl = `${this.nodeUrl}/arbitrary/resources/search?reverse=true&mode=ALL&exactmatchnames=true&${names}`
|
||||
let formEndpoints = []
|
||||
schemas.forEach((schema)=> {
|
||||
const feedData = schema.feed[0]
|
||||
@ -350,7 +350,7 @@ this.getFeedOnInterval()
|
||||
|
||||
// Merge new data with old data immutably
|
||||
this.feed = [...enhancedNewData, ...this.feed];
|
||||
|
||||
this.feed = this.removeDuplicates(this.feed)
|
||||
this.feed.sort((a, b) => new Date(b.created) - new Date(a.created)); // Sort by timestamp, most recent first
|
||||
this.feed = this.trimDataToLimit(this.feed, maxResultsInMemory); // Trim to the maximum allowed in memory
|
||||
this.feedToRender = this.feed.slice(0, 20);
|
||||
@ -365,6 +365,17 @@ this.getFeedOnInterval()
|
||||
}
|
||||
|
||||
|
||||
removeDuplicates(array) {
|
||||
const seenIds = new Set();
|
||||
return array.filter(item => {
|
||||
if (!seenIds.has(item.identifier)) {
|
||||
seenIds.add(item.identifier);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
async loadAndMergeData() {
|
||||
let allData = this.feed
|
||||
@ -373,6 +384,7 @@ this.getFeedOnInterval()
|
||||
allData = this.mergeData(newData, allData);
|
||||
allData.sort((a, b) => new Date(b.created) - new Date(a.created)); // Sort by timestamp, most recent first
|
||||
allData = this.trimDataToLimit(allData, maxResultsInMemory); // Trim to the maximum allowed in memory
|
||||
allData = this.removeDuplicates(allData)
|
||||
this.feed = [...allData]
|
||||
this.feedToRender = this.feed.slice(0,20)
|
||||
this.hasInitialFetch = true
|
||||
|
725
core/src/components/friends-view/profile-modal-update.js
Normal file
725
core/src/components/friends-view/profile-modal-update.js
Normal file
@ -0,0 +1,725 @@
|
||||
import { LitElement, html, css } from 'lit';
|
||||
import { render } from 'lit/html.js';
|
||||
import {
|
||||
use,
|
||||
get,
|
||||
translate,
|
||||
translateUnsafeHTML,
|
||||
registerTranslateConfig,
|
||||
} from 'lit-translate';
|
||||
import '@material/mwc-button';
|
||||
import '@material/mwc-icon';
|
||||
import '@vaadin/tooltip';
|
||||
import '@material/mwc-dialog';
|
||||
import '@material/mwc-checkbox';
|
||||
import { connect } from 'pwa-helpers';
|
||||
import { store } from '../../store';
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js';
|
||||
import { parentEpml } from '../show-plugin';
|
||||
|
||||
class ProfileModalUpdate extends connect(store)(LitElement) {
|
||||
static get properties() {
|
||||
return {
|
||||
isOpen: { type: Boolean },
|
||||
setIsOpen: { attribute: false },
|
||||
isLoading: { type: Boolean },
|
||||
onSubmit: { attribute: false },
|
||||
editContent: { type: Object },
|
||||
onClose: { attribute: false },
|
||||
tagline: { type: String },
|
||||
bio: { type: String },
|
||||
wallets: { type: Array },
|
||||
hasFetchedArrr: { type: Boolean },
|
||||
isOpenCustomDataModal: { type: Boolean },
|
||||
customData: { type: Object },
|
||||
newCustomDataField: {type: Object},
|
||||
newFieldName: {type: String},
|
||||
qortalRequestCustomData: {type: Object},
|
||||
newCustomDataKey: {type: String},
|
||||
isSaving: {type: Boolean}
|
||||
};
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.isOpen = false;
|
||||
this.isLoading = false;
|
||||
this.nodeUrl = this.getNodeUrl();
|
||||
this.myNode = this.getMyNode();
|
||||
this.tagline = '';
|
||||
this.bio = '';
|
||||
this.walletList = ['btc', 'ltc', 'doge', 'dgb', 'rvn', 'arrr'];
|
||||
let wallets = {};
|
||||
this.walletList.forEach((item) => {
|
||||
wallets[item] = '';
|
||||
});
|
||||
this.wallets = wallets;
|
||||
this.walletsUi = new Map();
|
||||
let coinProp = {
|
||||
wallet: null,
|
||||
};
|
||||
|
||||
this.walletList.forEach((c, i) => {
|
||||
this.walletsUi.set(c, { ...coinProp });
|
||||
});
|
||||
this.walletsUi.get('btc').wallet =
|
||||
window.parent.reduxStore.getState().app.selectedAddress.btcWallet;
|
||||
this.walletsUi.get('ltc').wallet =
|
||||
window.parent.reduxStore.getState().app.selectedAddress.ltcWallet;
|
||||
this.walletsUi.get('doge').wallet =
|
||||
window.parent.reduxStore.getState().app.selectedAddress.dogeWallet;
|
||||
this.walletsUi.get('dgb').wallet =
|
||||
window.parent.reduxStore.getState().app.selectedAddress.dgbWallet;
|
||||
this.walletsUi.get('rvn').wallet =
|
||||
window.parent.reduxStore.getState().app.selectedAddress.rvnWallet;
|
||||
this.hasFetchedArrr = false;
|
||||
this.isOpenCustomDataModal = false;
|
||||
this.customData = {};
|
||||
this.newCustomDataKey = ""
|
||||
this.newCustomDataField = {};
|
||||
this.newFieldName = '';
|
||||
this.isSaving = false
|
||||
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return css`
|
||||
* {
|
||||
--mdc-theme-primary: rgb(3, 169, 244);
|
||||
--mdc-theme-secondary: var(--mdc-theme-primary);
|
||||
--mdc-theme-surface: var(--white);
|
||||
--mdc-dialog-content-ink-color: var(--black);
|
||||
--mdc-dialog-min-width: 400px;
|
||||
--mdc-dialog-max-width: 1024px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.input {
|
||||
width: 90%;
|
||||
outline: 0;
|
||||
border-width: 0 0 2px;
|
||||
border-color: var(--mdc-theme-primary);
|
||||
background-color: transparent;
|
||||
padding: 10px;
|
||||
font-family: Roboto, sans-serif;
|
||||
font-size: 15px;
|
||||
color: var(--chat-bubble-msg-color);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.input::selection {
|
||||
background-color: var(--mdc-theme-primary);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.input::placeholder {
|
||||
opacity: 0.6;
|
||||
color: var(--black);
|
||||
}
|
||||
|
||||
.modal-button {
|
||||
font-family: Roboto, sans-serif;
|
||||
font-size: 16px;
|
||||
color: var(--mdc-theme-primary);
|
||||
background-color: transparent;
|
||||
padding: 8px 10px;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.modal-button-red {
|
||||
font-family: Roboto, sans-serif;
|
||||
font-size: 16px;
|
||||
color: #f44336;
|
||||
background-color: transparent;
|
||||
padding: 8px 10px;
|
||||
border-radius: 5px;
|
||||
border: none;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.modal-button-red:hover {
|
||||
cursor: pointer;
|
||||
background-color: #f4433663;
|
||||
}
|
||||
|
||||
.modal-button:hover {
|
||||
cursor: pointer;
|
||||
background-color: #03a8f475;
|
||||
}
|
||||
.checkbox-row {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
font-family: Montserrat, sans-serif;
|
||||
font-weight: 600;
|
||||
color: var(--black);
|
||||
}
|
||||
.modal-overlay {
|
||||
display: block;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-color: rgba(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0.5
|
||||
); /* Semi-transparent backdrop */
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
position: fixed;
|
||||
top: 50vh;
|
||||
left: 50vw;
|
||||
transform: translate(-50%, -50%);
|
||||
background-color: var(--mdc-theme-surface);
|
||||
width: 80vw;
|
||||
max-width: 600px;
|
||||
padding: 20px;
|
||||
box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 6px;
|
||||
z-index: 1001;
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.modal-overlay.hidden {
|
||||
display: none;
|
||||
}
|
||||
.avatar {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.app-name {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.inner-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: 75vh;
|
||||
flex-grow: 1;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.inner-content::-webkit-scrollbar-track {
|
||||
background-color: whitesmoke;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
.inner-content::-webkit-scrollbar {
|
||||
width: 12px;
|
||||
border-radius: 7px;
|
||||
background-color: whitesmoke;
|
||||
}
|
||||
|
||||
.inner-content::-webkit-scrollbar-thumb {
|
||||
background-color: rgb(180, 176, 176);
|
||||
border-radius: 7px;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
async updated(changedProperties) {
|
||||
if (
|
||||
changedProperties &&
|
||||
changedProperties.has('editContent') &&
|
||||
this.editContent
|
||||
) {
|
||||
const {bio, tagline, wallets, customData} = this.editContent
|
||||
this.bio = bio ?? '';
|
||||
this.tagline = tagline ?? '';
|
||||
let formWallets = {...this.wallets}
|
||||
if(wallets && Object.keys(wallets).length){
|
||||
Object.keys(formWallets).forEach((key)=> {
|
||||
if(wallets[key]){
|
||||
formWallets[key] = wallets[key]
|
||||
}
|
||||
})
|
||||
}
|
||||
this.wallets = formWallets
|
||||
|
||||
this.customData = {...customData}
|
||||
this.requestUpdate();
|
||||
}
|
||||
if (
|
||||
changedProperties &&
|
||||
changedProperties.has('qortalRequestCustomData') &&
|
||||
this.qortalRequestCustomData
|
||||
) {
|
||||
this.isOpenCustomDataModal = true
|
||||
this.newCustomDataField = {...this.qortalRequestCustomData.payload.customData}
|
||||
this.newCustomDataKey = this.qortalRequestCustomData.property
|
||||
this.requestUpdate();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
async firstUpdated() {
|
||||
try {
|
||||
await this.fetchWalletAddress('arrr');
|
||||
} catch (error) {
|
||||
console.log({ error });
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
|
||||
async fetchWalletAddress(coin) {
|
||||
switch (coin) {
|
||||
case 'arrr':
|
||||
const arrrWalletName = `${coin}Wallet`;
|
||||
|
||||
let res = await parentEpml.request('apiCall', {
|
||||
url: `/crosschain/${coin}/walletaddress?apiKey=${this.myNode.apiKey}`,
|
||||
method: 'POST',
|
||||
body: `${
|
||||
window.parent.reduxStore.getState().app.selectedAddress[
|
||||
arrrWalletName
|
||||
].seed58
|
||||
}`,
|
||||
});
|
||||
if (res != null && res.error != 1201 && res.length === 78) {
|
||||
this.arrrWalletAddress = res;
|
||||
this.hasFetchedArrr = true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// Not used for other coins yet
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
async getSelectedWalletAddress(wallet) {
|
||||
switch (wallet) {
|
||||
case 'arrr':
|
||||
if(!this.arrrWalletAddress){
|
||||
try {
|
||||
await this.fetchWalletAddress('arrr');
|
||||
} catch (error) {
|
||||
console.log({error})
|
||||
}
|
||||
}
|
||||
// Use address returned by core API
|
||||
return this.arrrWalletAddress;
|
||||
|
||||
default:
|
||||
// Use locally derived address
|
||||
return this.walletsUi.get(wallet).wallet.address;
|
||||
}
|
||||
}
|
||||
|
||||
getNodeUrl() {
|
||||
const myNode =
|
||||
store.getState().app.nodeConfig.knownNodes[
|
||||
window.parent.reduxStore.getState().app.nodeConfig.node
|
||||
];
|
||||
|
||||
const nodeUrl =
|
||||
myNode.protocol + '://' + myNode.domain + ':' + myNode.port;
|
||||
return nodeUrl;
|
||||
}
|
||||
getMyNode() {
|
||||
const myNode =
|
||||
store.getState().app.nodeConfig.knownNodes[
|
||||
window.parent.reduxStore.getState().app.nodeConfig.node
|
||||
];
|
||||
|
||||
return myNode;
|
||||
}
|
||||
|
||||
clearFields() {
|
||||
this.bio = '';
|
||||
this.tagline = '';
|
||||
}
|
||||
|
||||
fillAddress(coin) {
|
||||
const address = this.getSelectedWalletAddress(coin);
|
||||
if (address) {
|
||||
this.wallets = {
|
||||
...this.wallets,
|
||||
[coin]: address,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async saveProfile() {
|
||||
try {
|
||||
const data = {
|
||||
version: 1,
|
||||
tagline: this.tagline,
|
||||
bio: this.bio,
|
||||
wallets: this.wallets,
|
||||
customData: this.customData
|
||||
};
|
||||
this.isSaving = true
|
||||
await this.onSubmit(data);
|
||||
this.setIsOpen(false);
|
||||
this.clearFields();
|
||||
this.onClose('success');
|
||||
} catch (error) {} finally {
|
||||
this.isSaving = false
|
||||
}
|
||||
}
|
||||
|
||||
removeField(key){
|
||||
const copyObj = {...this.newCustomDataField}
|
||||
delete copyObj[key]
|
||||
this.newCustomDataField = copyObj
|
||||
}
|
||||
|
||||
addField(){
|
||||
const copyObj = {...this.newCustomDataField}
|
||||
copyObj[this.newFieldName] = ''
|
||||
this.newCustomDataField = copyObj
|
||||
this.newFieldName = ""
|
||||
}
|
||||
|
||||
addCustomData(){
|
||||
const copyObj = {...this.customData}
|
||||
copyObj[this.newCustomDataKey] = this.newCustomDataField
|
||||
this.customData = copyObj
|
||||
this.newCustomDataKey = ""
|
||||
this.newCustomDataField = {};
|
||||
this.newFieldName = ''
|
||||
this.isOpenCustomDataModal = false;
|
||||
}
|
||||
|
||||
updateCustomData(key, data){
|
||||
this.isOpenCustomDataModal = true
|
||||
this.newCustomDataField = data
|
||||
this.newCustomDataKey = key
|
||||
|
||||
}
|
||||
removeCustomData(key){
|
||||
const copyObj = {...this.customData}
|
||||
delete copyObj[key]
|
||||
this.customData = copyObj
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div class="modal-overlay ${this.isOpen ? '' : 'hidden'}">
|
||||
<div class="modal-content">
|
||||
<div class="inner-content">
|
||||
<div style="height:15px"></div>
|
||||
<div style="display: flex;flex-direction: column;">
|
||||
<label
|
||||
for="tagline"
|
||||
id="taglineLabel"
|
||||
style="color: var(--black);"
|
||||
>
|
||||
${translate('profile.profile4')}
|
||||
</label>
|
||||
<textarea
|
||||
class="input"
|
||||
@change=${(e) => {
|
||||
this.tagline = e.target.value;
|
||||
}}
|
||||
.value=${this.tagline}
|
||||
?disabled=${this.isLoading}
|
||||
id="tagline"
|
||||
placeholder="${translate('profile.profile4')}"
|
||||
rows="3"
|
||||
></textarea>
|
||||
</div>
|
||||
<div style="height:15px"></div>
|
||||
<div style="display: flex;flex-direction: column;">
|
||||
<label
|
||||
for="bio"
|
||||
id="bioLabel"
|
||||
style="color: var(--black);"
|
||||
>
|
||||
${translate('profile.profile5')}
|
||||
</label>
|
||||
<textarea
|
||||
class="input"
|
||||
@change=${(e) => {
|
||||
this.bio = e.target.value;
|
||||
}}
|
||||
.value=${this.bio}
|
||||
?disabled=${this.isLoading}
|
||||
id="bio"
|
||||
placeholder="${translate('profile.profile5')}"
|
||||
rows="3"
|
||||
></textarea>
|
||||
</div>
|
||||
<div style="height:15px"></div>
|
||||
<p>${translate('profile.profile6')}</p>
|
||||
<div style="display: flex;flex-direction: column;">
|
||||
${Object.keys(this.wallets).map((key) => {
|
||||
return html`
|
||||
<div
|
||||
style="display:flex;justify-content:center;flex-direction:column"
|
||||
>
|
||||
<label
|
||||
for=${key}
|
||||
id="taglineLabel"
|
||||
style="color: var(--black);font-size:16px"
|
||||
>
|
||||
${key}
|
||||
</label>
|
||||
<div
|
||||
style="display:flex;gap:15px;align-items:center"
|
||||
>
|
||||
<input
|
||||
id=${key}
|
||||
placeholder=${key + ' ' + get('settings.address')}
|
||||
class="input"
|
||||
.value=${this.wallets[key]}
|
||||
@change=${(e) => {
|
||||
this.wallets = {
|
||||
...this.wallets,
|
||||
[key]: e.target.value,
|
||||
};
|
||||
}}
|
||||
/>
|
||||
|
||||
<mwc-icon
|
||||
id=${`${key}-upload`}
|
||||
@click=${() =>
|
||||
this.fillAddress(key)}
|
||||
style="color:var(--black);cursor:pointer"
|
||||
>upload_2</mwc-icon
|
||||
>
|
||||
<vaadin-tooltip
|
||||
for=${`${key}-upload`}
|
||||
position="bottom"
|
||||
hover-delay=${200}
|
||||
hide-delay=${1}
|
||||
text=${translate('profile.profile21')}
|
||||
>
|
||||
</vaadin-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
})}
|
||||
</div>
|
||||
<div style="display: flex;flex-direction: column;">
|
||||
${Object.keys(this.customData).map((key) => {
|
||||
return html`
|
||||
<div
|
||||
style="display:flex;justify-content:center;flex-direction:column;gap:25px"
|
||||
>
|
||||
|
||||
<div
|
||||
style="display:flex;gap:15px;align-items:center"
|
||||
>
|
||||
<p
|
||||
|
||||
style="color: var(--black);font-size:16px"
|
||||
>
|
||||
${key}
|
||||
</p>
|
||||
|
||||
<mwc-icon
|
||||
@click=${() =>
|
||||
this.updateCustomData(key,this.customData[key])}
|
||||
style="color:var(--black);cursor:pointer"
|
||||
>edit</mwc-icon
|
||||
>
|
||||
<mwc-icon
|
||||
@click=${() =>
|
||||
this.removeCustomData(key)}
|
||||
style="color:var(--black);cursor:pointer"
|
||||
>remove</mwc-icon
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style="display:flex;justify-content:space-between;align-items:center;margin-top:20px"
|
||||
>
|
||||
<button
|
||||
class="modal-button-red"
|
||||
?disabled="${this.isLoading}"
|
||||
@click="${() => {
|
||||
this.setIsOpen(false);
|
||||
this.clearFields();
|
||||
this.onClose();
|
||||
}}"
|
||||
>
|
||||
${translate('general.close')}
|
||||
</button>
|
||||
|
||||
<div style="display:flex;gap:10px;align-items:center">
|
||||
|
||||
<button
|
||||
?disabled="${this.isLoading}"
|
||||
class="modal-button"
|
||||
@click=${() => {
|
||||
this.isOpenCustomDataModal = true;
|
||||
}}
|
||||
>
|
||||
${translate('profile.profile8')}
|
||||
</button>
|
||||
<button
|
||||
?disabled="${this.isLoading}"
|
||||
class="modal-button"
|
||||
@click=${() => {
|
||||
if(this.isSaving) return
|
||||
this.saveProfile();
|
||||
}}
|
||||
>
|
||||
${this.isSaving ? html`
|
||||
<paper-spinner-lite active></paper-spinner-lite>
|
||||
` : ''}
|
||||
${this.isSaving ? '' : translate('profile.profile3') }
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- add custom vars -->
|
||||
<div
|
||||
class="modal-overlay ${this.isOpenCustomDataModal
|
||||
? ''
|
||||
: 'hidden'}"
|
||||
style="z-index:1001"
|
||||
>
|
||||
<div class="modal-content">
|
||||
<div class="inner-content">
|
||||
<div style="height:15px"></div>
|
||||
<div
|
||||
style="display:flex;justify-content:center;flex-direction:column"
|
||||
>
|
||||
<label
|
||||
for="key-name"
|
||||
id="taglineLabel"
|
||||
style="color: var(--black);font-size:16px"
|
||||
>
|
||||
${translate('profile.profile9')}
|
||||
</label>
|
||||
<div
|
||||
style="display:flex;gap:15px;align-items:center"
|
||||
>
|
||||
<input
|
||||
id="key-name"
|
||||
placeholder=${translate(
|
||||
'profile.profile9'
|
||||
)}
|
||||
?disabled=${!!this.qortalRequestCustomData}
|
||||
class="input"
|
||||
.value=${this.newCustomDataKey}
|
||||
@change=${(e) => {
|
||||
this.newCustomDataKey = e.target.value
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div style="height:15px"></div>
|
||||
<p>${translate('profile.profile10')}</p>
|
||||
<div style="display: flex;flex-direction: column;">
|
||||
${Object.keys(this.newCustomDataField).map((key) => {
|
||||
return html`
|
||||
<div
|
||||
style="display:flex;justify-content:center;flex-direction:column"
|
||||
>
|
||||
<label
|
||||
for=${key}
|
||||
id="taglineLabel"
|
||||
style="color: var(--black);font-size:16px"
|
||||
>
|
||||
${key}
|
||||
</label>
|
||||
<div
|
||||
style="display:flex;gap:15px;align-items:center"
|
||||
>
|
||||
|
||||
<input
|
||||
id=${key}
|
||||
placeholder=${translate('profile.profile13')}
|
||||
class="input"
|
||||
.value=${this.newCustomDataField[key]}
|
||||
@change=${(e) => {
|
||||
this.newCustomDataField = {
|
||||
...this.newCustomDataField,
|
||||
[key]: e.target.value,
|
||||
};
|
||||
}}
|
||||
/>
|
||||
|
||||
<mwc-icon
|
||||
@click=${() =>
|
||||
this.removeField(key)}
|
||||
style="color:var(--black);cursor:pointer"
|
||||
>remove</mwc-icon
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
})}
|
||||
</div>
|
||||
<div style="height:15px"></div>
|
||||
<div style="width:100%;display:flex;justify-content:center;gap:10px;margin-top:30px">
|
||||
<input
|
||||
|
||||
placeholder=${translate('profile.profile12')}
|
||||
class="input"
|
||||
.value=${this.newFieldName}
|
||||
@change=${(e) => {
|
||||
this.newFieldName = e.target.value
|
||||
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
class="modal-button"
|
||||
@click=${() => {
|
||||
this.addField();
|
||||
}}
|
||||
>
|
||||
${translate('profile.profile11')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style="display:flex;justify-content:space-between;align-items:center;margin-top:20px"
|
||||
>
|
||||
<button
|
||||
class="modal-button-red"
|
||||
?disabled="${this.isLoading}"
|
||||
@click="${() => {
|
||||
this.isOpenCustomDataModal = false
|
||||
this.newCustomDataKey = ""
|
||||
this.newCustomDataField = {};
|
||||
}}"
|
||||
>
|
||||
${translate('general.close')}
|
||||
</button>
|
||||
|
||||
<button
|
||||
?disabled="${this.isSaving}"
|
||||
class="modal-button"
|
||||
@click=${() => {
|
||||
this.addCustomData();
|
||||
}}
|
||||
>
|
||||
${translate('profile.profile8')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('profile-modal-update', ProfileModalUpdate);
|
1023
core/src/components/friends-view/profile.js
Normal file
1023
core/src/components/friends-view/profile.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,14 +1,17 @@
|
||||
import {css, html, LitElement} from 'lit';
|
||||
import '@material/mwc-icon';
|
||||
import './friends-side-panel.js';
|
||||
import {connect} from 'pwa-helpers';
|
||||
import {store} from '../../store.js';
|
||||
import WebWorker from 'web-worker:./computePowWorkerFile.src.js';
|
||||
import { connect } from 'pwa-helpers';
|
||||
import { store } from '../../store.js';
|
||||
import WebWorker from '../WebWorkerFile.js';
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js';
|
||||
import '@vaadin/tooltip';
|
||||
import {translate} from 'lit-translate';
|
||||
import { get, translate } from 'lit-translate';
|
||||
import ShortUniqueId from 'short-unique-id';
|
||||
|
||||
import {
|
||||
decryptGroupData,
|
||||
|
||||
encryptDataGroup,
|
||||
objectToBase64,
|
||||
uint8ArrayToObject,
|
||||
@ -16,6 +19,7 @@ import {
|
||||
import {publishData} from '../../../../plugins/plugins/utils/publish-image.js';
|
||||
import {parentEpml} from '../show-plugin.js';
|
||||
import '../notification-view/popover.js';
|
||||
import { setNewTab } from '../../redux/app/app-actions.js';
|
||||
|
||||
class SaveSettingsQdn extends connect(store)(LitElement) {
|
||||
static get properties() {
|
||||
@ -27,6 +31,9 @@ class SaveSettingsQdn extends connect(store)(LitElement) {
|
||||
resourceExists: { type: Boolean },
|
||||
isSaving: { type: Boolean },
|
||||
fee: { type: Object },
|
||||
hasName: {type: Boolean},
|
||||
error: {type: String},
|
||||
name: {type: String}
|
||||
};
|
||||
}
|
||||
|
||||
@ -47,6 +54,11 @@ class SaveSettingsQdn extends connect(store)(LitElement) {
|
||||
this.valuesToBeSavedOnQdn = {};
|
||||
this.isSaving = false;
|
||||
this.fee = null;
|
||||
this.hasName = false;
|
||||
this.error = "";
|
||||
this.uid = new ShortUniqueId();
|
||||
this.name = undefined;
|
||||
|
||||
}
|
||||
static styles = css`
|
||||
:host {
|
||||
@ -309,13 +321,26 @@ class SaveSettingsQdn extends connect(store)(LitElement) {
|
||||
|
||||
async getGeneralSettingsQdn() {
|
||||
try {
|
||||
this.error = ""
|
||||
const arbFee = await this.getArbitraryFee();
|
||||
this.fee = arbFee;
|
||||
this.hasAttemptedToFetchResource = true;
|
||||
let resource;
|
||||
const nameObject = store.getState().app.accountInfo.names[0];
|
||||
if (!nameObject) throw new Error('no name');
|
||||
let nameObject
|
||||
try {
|
||||
nameObject = store.getState().app.accountInfo.names[0];
|
||||
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
if (!nameObject) {
|
||||
this.name = null;
|
||||
this.error = 'no name'
|
||||
throw new Error('no name');
|
||||
}
|
||||
const name = nameObject.name;
|
||||
this.name = name;
|
||||
this.hasName = true
|
||||
this.error = '';
|
||||
const url = `${this.nodeUrl}/arbitrary/resources/search?service=DOCUMENT_PRIVATE&identifier=qortal_general_settings&name=${name}&prefix=true&exactmatchnames=true&excludeblocked=true&limit=20`;
|
||||
const res = await fetch(url);
|
||||
@ -363,8 +388,6 @@ class SaveSettingsQdn extends connect(store)(LitElement) {
|
||||
|
||||
stateChanged(state) {
|
||||
if (
|
||||
state.app.accountInfo &&
|
||||
state.app.accountInfo.names.length &&
|
||||
state.app.nodeStatus &&
|
||||
state.app.nodeStatus.syncPercent !== this.syncPercentage
|
||||
) {
|
||||
@ -377,6 +400,15 @@ class SaveSettingsQdn extends connect(store)(LitElement) {
|
||||
this.getGeneralSettingsQdn();
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
state.app.accountInfo &&
|
||||
state.app.accountInfo.names.length &&
|
||||
state.app.nodeStatus &&
|
||||
state.app.nodeStatus.syncPercent === 100 && this.hasName === false && this.hasAttemptedToFetchResource && state.app.accountInfo && state.app.accountInfo.names && state.app.accountInfo.names.length > 0
|
||||
) {
|
||||
this.getGeneralSettingsQdn();
|
||||
}
|
||||
}
|
||||
|
||||
async getArbitraryFee() {
|
||||
@ -529,7 +561,78 @@ class SaveSettingsQdn extends connect(store)(LitElement) {
|
||||
style="display: block; margin: 0 auto;"
|
||||
></paper-spinner-lite>
|
||||
`
|
||||
: html`
|
||||
: !this.name ? html`
|
||||
<mwc-icon
|
||||
id="profile-icon"
|
||||
class=${'notActive'}
|
||||
@click=${() => {
|
||||
const target = this.shadowRoot.getElementById(
|
||||
'popover-notification'
|
||||
);
|
||||
const popover =
|
||||
this.shadowRoot.querySelector(
|
||||
'popover-component'
|
||||
);
|
||||
if (popover) {
|
||||
popover.openPopover(target);
|
||||
}
|
||||
}}
|
||||
style="user-select:none;cursor:pointer"
|
||||
>save</mwc-icon
|
||||
>
|
||||
<vaadin-tooltip
|
||||
for="profile-icon"
|
||||
position="bottom"
|
||||
hover-delay=${300}
|
||||
hide-delay=${1}
|
||||
text=${translate('profile.profile20')}
|
||||
>
|
||||
</vaadin-tooltip>
|
||||
<popover-component for="profile-icon" message="">
|
||||
<div style="margin-bottom:20px">
|
||||
<p style="margin:10px 0px; font-size:16px">
|
||||
${translate('profile.profile1')}
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
style="display:flex;justify-content:center;gap:10px"
|
||||
>
|
||||
<div
|
||||
class="accept-button"
|
||||
@click="${() => {
|
||||
store.dispatch(
|
||||
setNewTab({
|
||||
url: `group-management`,
|
||||
id: this.uid.rnd(),
|
||||
myPlugObj: {
|
||||
url: 'name-registration',
|
||||
domain: 'core',
|
||||
page: 'name-registration/index.html',
|
||||
title: 'Name Registration',
|
||||
icon: 'vaadin:user-check',
|
||||
mwcicon: 'manage_accounts',
|
||||
pluginNumber:
|
||||
'plugin-qCmtXAQmtu',
|
||||
menus: [],
|
||||
parent: false,
|
||||
},
|
||||
openExisting: true,
|
||||
})
|
||||
);
|
||||
const popover =
|
||||
this.shadowRoot.querySelector(
|
||||
'popover-component'
|
||||
);
|
||||
if (popover) {
|
||||
popover.closePopover();
|
||||
}
|
||||
}}"
|
||||
>
|
||||
${translate('profile.profile2')}
|
||||
</div>
|
||||
</div>
|
||||
</popover-component>
|
||||
` : html`
|
||||
<mwc-icon
|
||||
id="save-icon"
|
||||
class=${Object.values(this.valuesToBeSavedOnQdn)
|
||||
|
@ -9,6 +9,7 @@ const CHAT_HEADS_STREAM_NAME = 'chat_heads'
|
||||
const NODE_CONFIG_STREAM_NAME = 'node_config'
|
||||
const CHAT_LAST_SEEN = 'chat_last_seen'
|
||||
const SIDE_EFFECT_ACTION = 'side_effect_action'
|
||||
const PROFILE_DATA_ACTION = 'profile_data_action'
|
||||
const COIN_BALANCES_ACTION = 'coin_balances'
|
||||
|
||||
export const loggedInStream = new EpmlStream(LOGIN_STREAM_NAME, () => store.getState().app.loggedIn)
|
||||
@ -19,6 +20,7 @@ export const chatHeadsStateStream = new EpmlStream(CHAT_HEADS_STREAM_NAME, () =>
|
||||
export const nodeConfigStream = new EpmlStream(NODE_CONFIG_STREAM_NAME, () => store.getState().app.nodeConfig)
|
||||
export const chatLastSeenStream = new EpmlStream(CHAT_LAST_SEEN, () => store.getState().app.chatLastSeen)
|
||||
export const sideEffectActionStream = new EpmlStream(SIDE_EFFECT_ACTION, () => store.getState().app.sideEffectAction)
|
||||
export const profileDataActionStream = new EpmlStream(SIDE_EFFECT_ACTION, () => store.getState().app.profileData)
|
||||
export const coinBalancesActionStream = new EpmlStream(COIN_BALANCES_ACTION, () => store.getState().app.coinBalances)
|
||||
|
||||
|
||||
@ -65,6 +67,9 @@ store.subscribe(() => {
|
||||
if (oldState.app.sideEffectAction !== state.app.sideEffectAction) {
|
||||
sideEffectActionStream.emit(state.app.sideEffectAction)
|
||||
}
|
||||
if(oldState.app.profileDataActionStream !== state.app.profileDataActionStream){
|
||||
profileDataActionStream.emit(state.app.profileData)
|
||||
}
|
||||
if (oldState.app.coinBalances !== state.app.coinBalances) {
|
||||
coinBalancesActionStream.emit(state.app.coinBalances)
|
||||
}
|
||||
|
@ -19,7 +19,8 @@ import {
|
||||
SET_TAB_NOTIFICATIONS,
|
||||
UPDATE_BLOCK_INFO,
|
||||
UPDATE_NODE_INFO,
|
||||
UPDATE_NODE_STATUS
|
||||
UPDATE_NODE_STATUS,
|
||||
SET_PROFILE_DATA
|
||||
} from '../app-action-types.js'
|
||||
|
||||
export const doUpdateBlockInfo = (blockObj) => {
|
||||
@ -179,6 +180,12 @@ export const setSideEffectAction = (payload)=> {
|
||||
payload
|
||||
}
|
||||
}
|
||||
export const setProfileData = (payload)=> {
|
||||
return {
|
||||
type: SET_PROFILE_DATA,
|
||||
payload
|
||||
}
|
||||
}
|
||||
|
||||
export const setCoinBalances = (payload)=> {
|
||||
return {
|
||||
|
@ -33,4 +33,5 @@ export const SET_TAB_NOTIFICATIONS = 'SET_TAB_NOTIFICATIONS'
|
||||
export const IS_OPEN_DEV_DIALOG = 'IS_OPEN_DEV_DIALOG'
|
||||
export const SET_NEW_NOTIFICATION = 'SET_NEW_NOTIFICATION'
|
||||
export const SET_SIDE_EFFECT= 'SET_SIDE_EFFECT'
|
||||
export const SET_PROFILE_DATA = 'SET_PROFILE_DATA'
|
||||
export const SET_COIN_BALANCES= 'SET_COIN_BALANCES'
|
||||
|
@ -35,7 +35,8 @@ import {
|
||||
SET_TAB_NOTIFICATIONS,
|
||||
UPDATE_BLOCK_INFO,
|
||||
UPDATE_NODE_INFO,
|
||||
UPDATE_NODE_STATUS
|
||||
UPDATE_NODE_STATUS,
|
||||
SET_PROFILE_DATA
|
||||
} from './app-action-types.js'
|
||||
import {initWorkersReducer} from './reducers/init-workers.js'
|
||||
import {loginReducer} from './reducers/login-reducer.js'
|
||||
@ -90,6 +91,7 @@ const INITIAL_STATE = {
|
||||
isOpenDevDialog: false,
|
||||
newNotification: null,
|
||||
sideEffectAction: null,
|
||||
profileData: null,
|
||||
coinBalances: {}
|
||||
}
|
||||
|
||||
@ -331,6 +333,12 @@ export default (state = INITIAL_STATE, action) => {
|
||||
sideEffectAction: action.payload
|
||||
}
|
||||
}
|
||||
case SET_PROFILE_DATA: {
|
||||
return {
|
||||
...state,
|
||||
profileData: action.payload
|
||||
}
|
||||
}
|
||||
case SET_COIN_BALANCES: {
|
||||
const copyBalances = {...state.coinBalances}
|
||||
copyBalances[action.payload.type] = {
|
||||
|
@ -65,7 +65,6 @@ export class ChatGroupsModal extends LitElement {
|
||||
|
||||
|
||||
render() {
|
||||
console.log('hello')
|
||||
return html`
|
||||
|
||||
<mwc-dialog
|
||||
|
@ -363,9 +363,7 @@ class ChatPage extends LitElement {
|
||||
|
||||
}
|
||||
this.processMessages(getInitialMessages, true, false)
|
||||
} catch (error) {
|
||||
console.log
|
||||
}
|
||||
} catch (error) { /* empty */ }
|
||||
}
|
||||
|
||||
async copyJoinGroupLinkToClipboard() {
|
||||
@ -681,7 +679,10 @@ class ChatPage extends LitElement {
|
||||
<br>
|
||||
<h3 style="color: var(--black);">${translate("chatpage.cchange42")}</h3>
|
||||
<div class="buttons">
|
||||
<mwc-button @click=${() => this.sendMessage(this.myTrimmedMeassage)} dialog-confirm>${translate("transpage.tchange3")}</mwc-button>
|
||||
<mwc-button @click=${() => {
|
||||
this.sendMessage(this.myMessageUnder4Qort)
|
||||
|
||||
}} dialog-confirm>${translate("transpage.tchange3")}</mwc-button>
|
||||
</div>
|
||||
</paper-dialog>
|
||||
<wrapper-modal
|
||||
@ -1345,6 +1346,7 @@ class ChatPage extends LitElement {
|
||||
const isRecipient = this.chatId.includes('direct') === true ? true : false
|
||||
this.chatId.includes('direct') === true ? this.isReceipient = true : this.isReceipient = false
|
||||
this._chatId = this.chatId.split('/')[1]
|
||||
|
||||
const mstring = get("chatpage.cchange8")
|
||||
const placeholder = isRecipient === true ? `Message ${this._chatId}` : `${mstring}`
|
||||
this.chatEditorPlaceholder = placeholder
|
||||
@ -3113,8 +3115,8 @@ class ChatPage extends LitElement {
|
||||
const stringifyMessageObject = JSON.stringify(messageObject)
|
||||
|
||||
if (this.balance < 4) {
|
||||
this.myTrimmedMeassage = ''
|
||||
this.myTrimmedMeassage = stringifyMessageObject
|
||||
this.myMessageUnder4Qort = null
|
||||
this.myMessageUnder4Qort = {messageText: stringifyMessageObject, typeMessage, chatReference: undefined, isForward: false, isReceipient, _chatId, _publicKey, messageQueue}
|
||||
this.shadowRoot.getElementById('confirmDialog').open()
|
||||
} else {
|
||||
return this.sendMessage({messageText: stringifyMessageObject, typeMessage, chatReference: undefined, isForward: false, isReceipient, _chatId, _publicKey, messageQueue})
|
||||
@ -3164,23 +3166,23 @@ class ChatPage extends LitElement {
|
||||
})
|
||||
return _computePow(chatResponse)
|
||||
} else {
|
||||
let groupResponse = await parentEpml.request('chat', {
|
||||
type: 181,
|
||||
nonce: this.selectedAddress.nonce,
|
||||
params: {
|
||||
timestamp: Date.now(),
|
||||
groupID: Number(_chatId),
|
||||
hasReceipient: 0,
|
||||
hasChatReference: typeMessage === 'edit' ? 1 : 0,
|
||||
chatReference: chatReference,
|
||||
message: messageText,
|
||||
lastReference: reference,
|
||||
proofOfWorkNonce: 0,
|
||||
isEncrypted: 0, // Set default to not encrypted for groups
|
||||
isText: 1
|
||||
}
|
||||
})
|
||||
return _computePow(groupResponse)
|
||||
let groupResponse = await parentEpml.request('chat', {
|
||||
type: 181,
|
||||
nonce: this.selectedAddress.nonce,
|
||||
params: {
|
||||
timestamp: Date.now(),
|
||||
groupID: Number(_chatId),
|
||||
hasReceipient: 0,
|
||||
hasChatReference: typeMessage === 'edit' ? 1 : 0,
|
||||
chatReference: chatReference,
|
||||
message: messageText,
|
||||
lastReference: reference,
|
||||
proofOfWorkNonce: 0,
|
||||
isEncrypted: 0, // Set default to not encrypted for groups
|
||||
isText: 1
|
||||
}
|
||||
})
|
||||
return _computePow(groupResponse)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,16 @@ export class UserInfo extends LitElement {
|
||||
return imageHTMLRes
|
||||
}
|
||||
|
||||
openProfile(){
|
||||
try {
|
||||
const customEvent = new CustomEvent('open-visiting-profile', {
|
||||
detail: this.userName
|
||||
});
|
||||
window.parent.dispatchEvent(customEvent);
|
||||
|
||||
} catch (error) { /* empty */ }
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
let avatarImg = ""
|
||||
@ -84,7 +94,7 @@ export class UserInfo extends LitElement {
|
||||
<img src="/img/incognito.png" alt="avatar" />
|
||||
</div>`
|
||||
: ""}
|
||||
<div class="user-info-header">
|
||||
<div class="user-info-header">
|
||||
${this.selectedHead && this.selectedHead.name ? this.selectedHead.name : this.selectedHead ? cropAddress(this.selectedHead.address) : null}
|
||||
</div>
|
||||
<div class="send-message-button" @click="${() => {
|
||||
@ -102,6 +112,19 @@ export class UserInfo extends LitElement {
|
||||
}}>
|
||||
${translate("chatpage.cchange59")}
|
||||
</div>
|
||||
${this.userName ? html`
|
||||
<div style="margin-top: 5px;text-transform: uppercase;" class="send-message-button" @click=${() => {
|
||||
setTimeout(() => {
|
||||
this.openProfile()
|
||||
}, 250);
|
||||
this.setOpenUserInfo(false)
|
||||
|
||||
|
||||
}}>
|
||||
${translate("profile.profile18")}
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
@ -70,5 +70,11 @@ export const VOTE_ON_POLL= 'VOTE_ON_POLL'
|
||||
//CREATE_POLL
|
||||
export const CREATE_POLL= 'CREATE_POLL'
|
||||
|
||||
//GET_PROFILE_DATA
|
||||
export const GET_PROFILE_DATA = 'GET_PROFILE_DATA'
|
||||
|
||||
|
||||
// SET_PROFILE_DATA
|
||||
export const SET_PROFILE_DATA= 'SET_PROFILE_DATA'
|
||||
//GET_DAY_SUMMARY
|
||||
export const GET_DAY_SUMMARY = 'GET_DAY_SUMMARY'
|
||||
|
@ -481,11 +481,10 @@ class WebBrowser extends LitElement {
|
||||
const arbitraryFee = (Number(data) / 1e8).toFixed(8)
|
||||
return {
|
||||
timestamp,
|
||||
fee : Number(data),
|
||||
fee: Number(data),
|
||||
feeToShow: arbitraryFee
|
||||
}
|
||||
}
|
||||
|
||||
async sendQortFee() {
|
||||
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
|
||||
@ -660,9 +659,9 @@ class WebBrowser extends LitElement {
|
||||
}
|
||||
|
||||
const makeTransactionRequest = async (lastRef) => {
|
||||
let votedialog1 = get("transactions.votedialog1")
|
||||
let votedialog2 = get("transactions.votedialog2")
|
||||
let feeDialog = get("walletpage.wchange12")
|
||||
let votedialog1 = get("transactions.votedialog1")
|
||||
let votedialog2 = get("transactions.votedialog2")
|
||||
let feeDialog = get("walletpage.wchange12")
|
||||
|
||||
let myTxnrequest = await parentEpml.request('transaction', {
|
||||
type: 9,
|
||||
@ -1622,7 +1621,7 @@ class WebBrowser extends LitElement {
|
||||
}
|
||||
|
||||
case actions.SEND_LOCAL_NOTIFICATION: {
|
||||
const {title, url, icon, message} = data
|
||||
const { title, url, icon, message } = data
|
||||
try {
|
||||
const id = `appNotificationList-${this.selectedAddress.address}`
|
||||
const checkData = localStorage.getItem(id) ? JSON.parse(localStorage.getItem(id)) : null
|
||||
@ -1641,7 +1640,7 @@ class WebBrowser extends LitElement {
|
||||
this.updateLastNotification(id, this.name)
|
||||
break
|
||||
} else {
|
||||
throw new Error(`duration until another notification can be sent: ${interval - timeDifference}`)
|
||||
throw new Error(`invalid data`)
|
||||
}
|
||||
} else if(!lastNotification){
|
||||
parentEpml.request('showNotification', {
|
||||
@ -2064,6 +2063,199 @@ class WebBrowser extends LitElement {
|
||||
break
|
||||
}
|
||||
|
||||
case 'GET_PROFILE_DATA': {
|
||||
const defaultProperties = ['tagline', 'bio', 'wallets']
|
||||
const requiredFields = ['property'];
|
||||
const missingFields = [];
|
||||
|
||||
requiredFields.forEach((field) => {
|
||||
if (!data[field] && data[field] !== 0) {
|
||||
missingFields.push(field);
|
||||
}
|
||||
});
|
||||
|
||||
if (missingFields.length > 0) {
|
||||
const missingFieldsString = missingFields.join(', ');
|
||||
const errorMsg = `Missing fields: ${missingFieldsString}`
|
||||
let data = {};
|
||||
data['error'] = errorMsg;
|
||||
response = JSON.stringify(data);
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const profileData = window.parent.reduxStore.getState().app.profileData
|
||||
if (!profileData) {
|
||||
throw new Error('User does not have a profile')
|
||||
}
|
||||
const property = data.property
|
||||
const propertyIndex = defaultProperties.indexOf(property)
|
||||
if (propertyIndex !== -1) {
|
||||
const requestedData = profileData[property]
|
||||
if (requestedData) {
|
||||
response = JSON.stringify(requestedData);
|
||||
break
|
||||
} else {
|
||||
throw new Error('Cannot find requested data')
|
||||
}
|
||||
}
|
||||
|
||||
if (property.includes('-private')) {
|
||||
const resPrivateProperty = await showModalAndWait(
|
||||
actions.GET_PROFILE_DATA, {
|
||||
property
|
||||
}
|
||||
);
|
||||
|
||||
if (resPrivateProperty.action === 'accept') {
|
||||
|
||||
const requestedData = profileData.customData[property]
|
||||
if (requestedData) {
|
||||
response = JSON.stringify(requestedData);
|
||||
break
|
||||
} else {
|
||||
throw new Error('Cannot find requested data')
|
||||
}
|
||||
} else {
|
||||
throw new Error('User denied permission for private property')
|
||||
}
|
||||
} else {
|
||||
const requestedData = profileData.customData[property]
|
||||
if (requestedData) {
|
||||
response = JSON.stringify(requestedData);
|
||||
break
|
||||
} else {
|
||||
throw new Error('Cannot find requested data')
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
const obj = {};
|
||||
const errorMsg = error.message || 'Failed to join the group.';
|
||||
obj['error'] = errorMsg;
|
||||
response = JSON.stringify(obj);
|
||||
} finally {
|
||||
this.loader.hide();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'SET_PROFILE_DATA': {
|
||||
const requiredFields = ['property', 'data'];
|
||||
const missingFields = [];
|
||||
|
||||
requiredFields.forEach((field) => {
|
||||
if (!data[field] && data[field] !== 0) {
|
||||
missingFields.push(field);
|
||||
}
|
||||
});
|
||||
|
||||
if (missingFields.length > 0) {
|
||||
const missingFieldsString = missingFields.join(', ');
|
||||
const errorMsg = `Missing fields: ${missingFieldsString}`
|
||||
let data = {};
|
||||
data['error'] = errorMsg;
|
||||
response = JSON.stringify(data);
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const property = data.property
|
||||
const payload = data.data
|
||||
const uniqueId = this.uid.rnd()
|
||||
const fee = await this.getArbitraryFee()
|
||||
const resSetPrivateProperty = await showModalAndWait(
|
||||
actions.SET_PROFILE_DATA, {
|
||||
property,
|
||||
fee: fee.feeToShow
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
if (resSetPrivateProperty.action !== 'accept') throw new Error('User declined permission')
|
||||
|
||||
//dispatch event and wait until I get a response to continue
|
||||
|
||||
// Create and dispatch custom event
|
||||
const customEvent = new CustomEvent('qortal-request-set-profile-data', {
|
||||
detail: {
|
||||
property,
|
||||
payload,
|
||||
uniqueId
|
||||
}
|
||||
});
|
||||
window.parent.dispatchEvent(customEvent);
|
||||
|
||||
// Wait for response event
|
||||
const res = await new Promise((resolve, reject) => {
|
||||
function handleResponseEvent(event) {
|
||||
// Handle the data from the event, if any
|
||||
const responseData = event.detail;
|
||||
if(responseData && responseData.uniqueId !== uniqueId) return
|
||||
// Clean up by removing the event listener once we've received the response
|
||||
window.removeEventListener('qortal-request-set-profile-data-response', handleResponseEvent);
|
||||
|
||||
if (responseData.response === 'saved') {
|
||||
resolve(responseData);
|
||||
} else {
|
||||
reject(new Error('not saved'));
|
||||
}
|
||||
}
|
||||
|
||||
// Set up an event listener to wait for the response
|
||||
window.addEventListener('qortal-request-set-profile-data-response', handleResponseEvent);
|
||||
});
|
||||
if(!res.response) throw new Error('Failed to set property')
|
||||
response = JSON.stringify(res.response);
|
||||
|
||||
} catch (error) {
|
||||
const obj = {};
|
||||
const errorMsg = error.message || 'Failed to set property.';
|
||||
obj['error'] = errorMsg;
|
||||
response = JSON.stringify(obj);
|
||||
} finally {
|
||||
this.loader.hide();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'OPEN_PROFILE': {
|
||||
const requiredFields = ['name'];
|
||||
const missingFields = [];
|
||||
|
||||
requiredFields.forEach((field) => {
|
||||
if (!data[field] && data[field] !== 0) {
|
||||
missingFields.push(field);
|
||||
}
|
||||
});
|
||||
|
||||
if (missingFields.length > 0) {
|
||||
const missingFieldsString = missingFields.join(', ');
|
||||
const errorMsg = `Missing fields: ${missingFieldsString}`
|
||||
let data = {};
|
||||
data['error'] = errorMsg;
|
||||
response = JSON.stringify(data);
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const customEvent = new CustomEvent('open-visiting-profile', {
|
||||
detail: data.name
|
||||
});
|
||||
window.parent.dispatchEvent(customEvent);
|
||||
response = JSON.stringify(true);
|
||||
} catch (error) {
|
||||
const obj = {};
|
||||
const errorMsg = error.message || 'Failed to open profile';
|
||||
obj['error'] = errorMsg;
|
||||
response = JSON.stringify(obj);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case actions.GET_USER_WALLET: {
|
||||
const requiredFields = ['coin'];
|
||||
const missingFields = [];
|
||||
@ -3561,7 +3753,7 @@ async function showModalAndWait(type, data) {
|
||||
|
||||
${type === actions.GET_USER_WALLET ? `
|
||||
<div class="modal-subcontainer">
|
||||
<p class="modal-paragraph">${get("browserpage.bchange49")}</p>
|
||||
<p class="modal-paragraph">${get("browserpage.bchange52")}</p>
|
||||
</div>
|
||||
` : ''}
|
||||
${type === actions.GET_WALLET_BALANCE ? `
|
||||
@ -3593,6 +3785,21 @@ async function showModalAndWait(type, data) {
|
||||
<p class="modal-paragraph">${get("browserpage.bchange46")}: <span> ${data.filename}</span></p>
|
||||
</div>
|
||||
` : ''}
|
||||
${type === actions.GET_PROFILE_DATA ? `
|
||||
<div class="modal-subcontainer">
|
||||
<p class="modal-paragraph">${get("browserpage.bchange49")}: <span style="font-weight: bold"> ${data.property}</span></p>
|
||||
|
||||
</div>
|
||||
` : ''}
|
||||
${type === actions.SET_PROFILE_DATA ? `
|
||||
<div class="modal-subcontainer">
|
||||
<p class="modal-paragraph">${get("browserpage.bchange50")} <span style="font-weight: bold"> ${data.property}</span></p>
|
||||
<br>
|
||||
<p style="font-size: 16px;overflow-wrap: anywhere;" class="modal-paragraph">${get('browserpage.bchange47')} <span style="font-weight: bold">${data.fee} QORT fee</span></p>
|
||||
<br>
|
||||
<p style="font-size: 16px;overflow-wrap: anywhere;" class="modal-paragraph">${get('browserpage.bchange51')} </p>
|
||||
</div>
|
||||
` : ''}
|
||||
${type === actions.NOTIFICATIONS_PERMISSION ? `
|
||||
<div class="modal-subcontainer">
|
||||
<p class="modal-paragraph">${get("browserpage.bchange48")}</p>
|
||||
|
Loading…
x
Reference in New Issue
Block a user