mirror of
https://github.com/Qortal/qortal-ui.git
synced 2025-02-11 09:45:52 +00:00
started profile
This commit is contained in:
parent
b2a5b13a22
commit
ed5253d6d0
@ -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;"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -1212,5 +1212,12 @@
|
||||
"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"
|
||||
}
|
||||
}
|
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;
|
@ -46,6 +46,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'
|
||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||
|
||||
class AppView extends connect(store)(LitElement) {
|
||||
@ -584,6 +585,7 @@ class AppView extends connect(store)(LitElement) {
|
||||
</span>
|
||||
</div>
|
||||
<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>
|
||||
|
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);
|
301
core/src/components/friends-view/profile-modal-update.js
Normal file
301
core/src/components/friends-view/profile-modal-update.js
Normal file
@ -0,0 +1,301 @@
|
||||
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-dialog';
|
||||
import '@material/mwc-checkbox';
|
||||
import { connect } from 'pwa-helpers';
|
||||
import { store } from '../../store';
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js';
|
||||
|
||||
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}
|
||||
};
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.isOpen = false;
|
||||
this.isLoading = false;
|
||||
this.nodeUrl = this.getNodeUrl();
|
||||
this.myNode = this.getMyNode();
|
||||
this.tagline = "";
|
||||
this.bio = "",
|
||||
this.walletList = [
|
||||
"btcWallet", "ltcWallet", "dogeWallet","dgbWallet", "rvnWallet", "arrrWallet"
|
||||
]
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
firstUpdated() {}
|
||||
|
||||
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() {}
|
||||
|
||||
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);"
|
||||
>
|
||||
${get('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);"
|
||||
>
|
||||
${get('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>
|
||||
<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>
|
||||
|
||||
<button
|
||||
?disabled="${this.isLoading}"
|
||||
class="modal-button"
|
||||
@click=${() => {
|
||||
this.addFriend();
|
||||
}}
|
||||
>
|
||||
${translate('profile.profile3')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('profile-modal-update', ProfileModalUpdate);
|
672
core/src/components/friends-view/profile.js
Normal file
672
core/src/components/friends-view/profile.js
Normal file
@ -0,0 +1,672 @@
|
||||
import { LitElement, html, css } from 'lit';
|
||||
import '@material/mwc-icon';
|
||||
import './friends-side-panel.js';
|
||||
import { connect } from 'pwa-helpers';
|
||||
import { store } from '../../store.js';
|
||||
import WebWorker2 from '../WebWorkerFile.js';
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js';
|
||||
import '@vaadin/tooltip';
|
||||
import { get, translate } from 'lit-translate';
|
||||
import ShortUniqueId from 'short-unique-id';
|
||||
|
||||
import {
|
||||
decryptGroupData,
|
||||
encryptDataGroup,
|
||||
objectToBase64,
|
||||
uint8ArrayToBase64,
|
||||
uint8ArrayToObject,
|
||||
} from '../../../../plugins/plugins/core/components/qdn-action-encryption.js';
|
||||
import { publishData } from '../../../../plugins/plugins/utils/publish-image.js';
|
||||
import { parentEpml } from '../show-plugin.js';
|
||||
import '../notification-view/popover.js';
|
||||
import './avatar.js';
|
||||
import { setNewTab } from '../../redux/app/app-actions.js';
|
||||
import './profile-modal-update.js'
|
||||
|
||||
class ProfileQdn extends connect(store)(LitElement) {
|
||||
static get properties() {
|
||||
return {
|
||||
isOpen: { type: Boolean },
|
||||
syncPercentage: { type: Number },
|
||||
settingsRawData: { type: Object },
|
||||
valuesToBeSavedOnQdn: { type: Object },
|
||||
resourceExists: { type: Boolean },
|
||||
isSaving: { type: Boolean },
|
||||
fee: { type: Object },
|
||||
name: { type: String },
|
||||
isOpenProfileModalUpdate: {type: Boolean},
|
||||
editContent: {type: Object}
|
||||
};
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.isOpen = false;
|
||||
this.getProfile = this.getProfile.bind(this);
|
||||
this._updateTempSettingsData = this._updateTempSettingsData.bind(this);
|
||||
this.setValues = this.setValues.bind(this);
|
||||
this.saveToQdn = this.saveToQdn.bind(this);
|
||||
this.syncPercentage = 0;
|
||||
this.hasRetrievedResource = false;
|
||||
this.hasAttemptedToFetchResource = false;
|
||||
this.resourceExists = undefined;
|
||||
this.settingsRawData = null;
|
||||
this.nodeUrl = this.getNodeUrl();
|
||||
this.myNode = this.getMyNode();
|
||||
this.valuesToBeSavedOnQdn = {};
|
||||
this.isSaving = false;
|
||||
this.fee = null;
|
||||
this.name = undefined;
|
||||
this.uid = new ShortUniqueId();
|
||||
this.isOpenProfileModalUpdate = false
|
||||
this.editContent = null
|
||||
}
|
||||
static styles = css`
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16px;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 16px;
|
||||
}
|
||||
.close {
|
||||
visibility: hidden;
|
||||
position: fixed;
|
||||
z-index: -100;
|
||||
right: -1000px;
|
||||
}
|
||||
|
||||
.parent-side-panel {
|
||||
transform: translateX(100%); /* start from outside the right edge */
|
||||
transition: transform 0.3s ease-in-out;
|
||||
}
|
||||
.parent-side-panel.open {
|
||||
transform: translateX(0); /* slide in to its original position */
|
||||
}
|
||||
.notActive {
|
||||
opacity: 0.5;
|
||||
cursor: default;
|
||||
color: var(--black);
|
||||
}
|
||||
.active {
|
||||
opacity: 1;
|
||||
cursor: pointer;
|
||||
color: green;
|
||||
}
|
||||
.accept-button {
|
||||
font-family: Roboto, sans-serif;
|
||||
letter-spacing: 0.3px;
|
||||
font-weight: 300;
|
||||
padding: 8px 5px;
|
||||
border-radius: 3px;
|
||||
text-align: center;
|
||||
color: var(--mdc-theme-primary);
|
||||
transition: all 0.3s ease-in-out;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.accept-button:hover {
|
||||
cursor: pointer;
|
||||
background-color: #03a8f485;
|
||||
}
|
||||
|
||||
.undo-button {
|
||||
font-family: Roboto, sans-serif;
|
||||
letter-spacing: 0.3px;
|
||||
font-weight: 300;
|
||||
padding: 8px 5px;
|
||||
border-radius: 3px;
|
||||
text-align: center;
|
||||
color: #f44336;
|
||||
transition: all 0.3s ease-in-out;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.undo-button:hover {
|
||||
cursor: pointer;
|
||||
background-color: #f4433663;
|
||||
}
|
||||
`;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
async getAvatar(dataItem) {
|
||||
const url = `${this.nodeUrl}/arbitrary/${dataItem.service}/${dataItem.name}/${dataItem.identifier}?encoding=base64`;
|
||||
const res = await fetch(url);
|
||||
const data = await res.text();
|
||||
if (data.error) throw new Error('Cannot retrieve your data from qdn');
|
||||
const decryptedData = decryptGroupData(data);
|
||||
const decryptedDataToBase64 = uint8ArrayToObject(decryptedData);
|
||||
return decryptedDataToBase64;
|
||||
}
|
||||
|
||||
async getRawData(dataItem) {
|
||||
const url = `${this.nodeUrl}/arbitrary/${dataItem.service}/${dataItem.name}/${dataItem.identifier}?encoding=base64`;
|
||||
const res = await fetch(url);
|
||||
const data = await res.text();
|
||||
if (data.error) throw new Error('Cannot retrieve your data from qdn');
|
||||
const decryptedData = decryptGroupData(data);
|
||||
const decryptedDataToBase64 = uint8ArrayToObject(decryptedData);
|
||||
return decryptedDataToBase64;
|
||||
}
|
||||
|
||||
async getMyFollowedNames() {
|
||||
let myFollowedNames = [];
|
||||
try {
|
||||
myFollowedNames = await parentEpml.request('apiCall', {
|
||||
url: `/lists/followedNames?apiKey=${this.myNode.apiKey}`,
|
||||
});
|
||||
} catch (error) {}
|
||||
|
||||
return myFollowedNames;
|
||||
}
|
||||
|
||||
async followNames(names) {
|
||||
let items = names;
|
||||
let namesJsonString = JSON.stringify({ items: items });
|
||||
|
||||
let ret = await parentEpml.request('apiCall', {
|
||||
url: `/lists/followedNames?apiKey=${this.myNode.apiKey}`,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: `${namesJsonString}`,
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
async setValues(response, resource) {
|
||||
this.settingsRawData = response;
|
||||
const rawDataTimestamp = resource.updated;
|
||||
|
||||
const tempSettingsData = JSON.parse(
|
||||
localStorage.getItem('temp-settings-data') || '{}'
|
||||
);
|
||||
|
||||
const userLists = response.userLists || [];
|
||||
const friendsFeed = response.friendsFeed;
|
||||
const myMenuPlugs = response.myMenuPlugs;
|
||||
|
||||
this.valuesToBeSavedOnQdn = {};
|
||||
if (
|
||||
userLists.length > 0 &&
|
||||
(!tempSettingsData.userLists ||
|
||||
(tempSettingsData.userLists &&
|
||||
tempSettingsData.userLists.timestamp < rawDataTimestamp))
|
||||
) {
|
||||
const friendList = userLists[0];
|
||||
const copyPayload = [...friendList];
|
||||
const onlyNames = copyPayload.map((item) => item.name);
|
||||
const followedList = await this.getMyFollowedNames();
|
||||
|
||||
const namesNotInFollowedList = onlyNames.filter(
|
||||
(name) => !followedList.includes(name)
|
||||
);
|
||||
if (namesNotInFollowedList.length > 0) {
|
||||
await this.followNames(namesNotInFollowedList);
|
||||
}
|
||||
|
||||
localStorage.setItem(
|
||||
'friends-my-friend-list',
|
||||
JSON.stringify(friendList)
|
||||
);
|
||||
this.dispatchEvent(
|
||||
new CustomEvent('friends-my-friend-list-event', {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
detail: copyPayload,
|
||||
})
|
||||
);
|
||||
} else if (
|
||||
tempSettingsData.userLists &&
|
||||
tempSettingsData.userLists.timestamp > rawDataTimestamp
|
||||
) {
|
||||
this.valuesToBeSavedOnQdn = {
|
||||
...this.valuesToBeSavedOnQdn,
|
||||
userLists: {
|
||||
data: tempSettingsData.userLists.data,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
friendsFeed &&
|
||||
(!tempSettingsData.friendsFeed ||
|
||||
(tempSettingsData.friendsFeed &&
|
||||
tempSettingsData.friendsFeed.timestamp < rawDataTimestamp))
|
||||
) {
|
||||
const copyPayload = [...friendsFeed];
|
||||
|
||||
localStorage.setItem(
|
||||
'friends-my-selected-feeds',
|
||||
JSON.stringify(friendsFeed)
|
||||
);
|
||||
this.dispatchEvent(
|
||||
new CustomEvent('friends-my-selected-feeds-event', {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
detail: copyPayload,
|
||||
})
|
||||
);
|
||||
} else if (
|
||||
tempSettingsData.friendsFeed &&
|
||||
tempSettingsData.friendsFeed.timestamp > rawDataTimestamp
|
||||
) {
|
||||
this.valuesToBeSavedOnQdn = {
|
||||
...this.valuesToBeSavedOnQdn,
|
||||
friendsFeed: {
|
||||
data: tempSettingsData.friendsFeed.data,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
myMenuPlugs &&
|
||||
(!tempSettingsData.myMenuPlugs ||
|
||||
(tempSettingsData.myMenuPlugs &&
|
||||
tempSettingsData.myMenuPlugs.timestamp < rawDataTimestamp))
|
||||
) {
|
||||
if (Array.isArray(myMenuPlugs)) {
|
||||
const copyPayload = [...myMenuPlugs];
|
||||
|
||||
localStorage.setItem(
|
||||
'myMenuPlugs',
|
||||
JSON.stringify(myMenuPlugs)
|
||||
);
|
||||
|
||||
this.dispatchEvent(
|
||||
new CustomEvent('myMenuPlugs-event', {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
detail: copyPayload,
|
||||
})
|
||||
);
|
||||
}
|
||||
} else if (
|
||||
tempSettingsData.myMenuPlugs &&
|
||||
tempSettingsData.myMenuPlugs.timestamp > rawDataTimestamp
|
||||
) {
|
||||
this.valuesToBeSavedOnQdn = {
|
||||
...this.valuesToBeSavedOnQdn,
|
||||
myMenuPlugs: {
|
||||
data: tempSettingsData.myMenuPlugs.data,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async getProfile() {
|
||||
try {
|
||||
const arbFee = await this.getArbitraryFee();
|
||||
this.fee = arbFee;
|
||||
this.hasAttemptedToFetchResource = true;
|
||||
let resource;
|
||||
const nameObject = store.getState().app.accountInfo.names[0];
|
||||
if (!nameObject) {
|
||||
this.name = null;
|
||||
throw new Error('no name');
|
||||
}
|
||||
const name = nameObject.name;
|
||||
this.name = name;
|
||||
this.error = '';
|
||||
const url = `${this.nodeUrl}/arbitrary/resources/search?service=DOCUMENT&identifier=qortal_profile&name=${name}&prefix=true&exactmatchnames=true&excludeblocked=true&limit=20`;
|
||||
const res = await fetch(url);
|
||||
let data = '';
|
||||
try {
|
||||
data = await res.json();
|
||||
if (Array.isArray(data)) {
|
||||
data = data.filter(
|
||||
(item) => item.identifier === 'qortal_profile'
|
||||
);
|
||||
|
||||
if (data.length > 0) {
|
||||
this.resourceExists = true;
|
||||
const dataItem = data[0];
|
||||
try {
|
||||
const response = await this.getRawData(dataItem);
|
||||
if (response.version) {
|
||||
// this.setValues(response, dataItem);
|
||||
} else {
|
||||
this.error = 'Cannot get saved user settings';
|
||||
}
|
||||
} catch (error) {
|
||||
console.log({ error });
|
||||
this.error = 'Cannot get saved user settings';
|
||||
}
|
||||
} else {
|
||||
this.resourceExists = false;
|
||||
}
|
||||
} else {
|
||||
this.error = 'Unable to perform query';
|
||||
}
|
||||
} catch (error) {
|
||||
data = {
|
||||
error: 'No resource found',
|
||||
};
|
||||
}
|
||||
|
||||
if (resource) {
|
||||
this.hasRetrievedResource = true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log({ error });
|
||||
}
|
||||
}
|
||||
|
||||
stateChanged(state) {
|
||||
if (
|
||||
state.app.accountInfo &&
|
||||
state.app.accountInfo.names.length &&
|
||||
state.app.nodeStatus &&
|
||||
state.app.nodeStatus.syncPercent !== this.syncPercentage
|
||||
) {
|
||||
this.syncPercentage = state.app.nodeStatus.syncPercent;
|
||||
|
||||
if (
|
||||
!this.hasAttemptedToFetchResource &&
|
||||
state.app.nodeStatus.syncPercent === 100
|
||||
) {
|
||||
this.getProfile();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async getArbitraryFee() {
|
||||
const timestamp = Date.now();
|
||||
const url = `${this.nodeUrl}/transactions/unitfee?txType=ARBITRARY×tamp=${timestamp}`;
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
throw new Error('Error when fetching arbitrary fee');
|
||||
}
|
||||
const data = await response.json();
|
||||
const arbitraryFee = (Number(data) / 1e8).toFixed(8);
|
||||
return {
|
||||
timestamp,
|
||||
fee: Number(data),
|
||||
feeToShow: arbitraryFee,
|
||||
};
|
||||
}
|
||||
|
||||
async saveToQdn() {
|
||||
try {
|
||||
this.isSaving = true;
|
||||
if (this.resourceExists === true && this.error)
|
||||
throw new Error('Unable to save');
|
||||
|
||||
const nameObject = store.getState().app.accountInfo.names[0];
|
||||
if (!nameObject) throw new Error('no name');
|
||||
const name = nameObject.name;
|
||||
const identifer = 'qortal_general_settings';
|
||||
const filename = 'qortal_general_settings.json';
|
||||
const selectedAddress = store.getState().app.selectedAddress;
|
||||
const getArbitraryFee = await this.getArbitraryFee();
|
||||
const feeAmount = getArbitraryFee.fee;
|
||||
const friendsList = JSON.parse(
|
||||
localStorage.getItem('friends-my-friend-list') || '[]'
|
||||
);
|
||||
const friendsFeed = JSON.parse(
|
||||
localStorage.getItem('friends-my-selected-feeds') || '[]'
|
||||
);
|
||||
const myMenuPlugs = JSON.parse(
|
||||
localStorage.getItem('myMenuPlugs') || '[]'
|
||||
);
|
||||
|
||||
let newObject;
|
||||
|
||||
if (this.resourceExists === false) {
|
||||
newObject = {
|
||||
version: 1,
|
||||
userLists: [friendsList],
|
||||
friendsFeed,
|
||||
myMenuPlugs,
|
||||
};
|
||||
} else if (this.settingsRawData) {
|
||||
const tempSettingsData = JSON.parse(
|
||||
localStorage.getItem('temp-settings-data') || '{}'
|
||||
);
|
||||
newObject = {
|
||||
...this.settingsRawData,
|
||||
};
|
||||
for (const key in tempSettingsData) {
|
||||
if (tempSettingsData[key].hasOwnProperty('data')) {
|
||||
if (
|
||||
key === 'userLists' &&
|
||||
!Array.isArray(tempSettingsData[key].data)
|
||||
)
|
||||
continue;
|
||||
if (
|
||||
key === 'friendsFeed' &&
|
||||
!Array.isArray(tempSettingsData[key].data)
|
||||
)
|
||||
continue;
|
||||
if (
|
||||
key === 'myMenuPlugs' &&
|
||||
!Array.isArray(tempSettingsData[key].data)
|
||||
)
|
||||
continue;
|
||||
newObject[key] = tempSettingsData[key].data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const newObjectToBase64 = await objectToBase64(newObject);
|
||||
const encryptedData = encryptDataGroup({
|
||||
data64: newObjectToBase64,
|
||||
publicKeys: [],
|
||||
});
|
||||
|
||||
const worker = new WebWorker2();
|
||||
try {
|
||||
const resPublish = await publishData({
|
||||
registeredName: encodeURIComponent(name),
|
||||
file: encryptedData,
|
||||
service: 'DOCUMENT_PRIVATE',
|
||||
identifier: encodeURIComponent(identifer),
|
||||
parentEpml: parentEpml,
|
||||
uploadType: 'file',
|
||||
selectedAddress: selectedAddress,
|
||||
worker: worker,
|
||||
isBase64: true,
|
||||
filename: filename,
|
||||
apiVersion: 2,
|
||||
withFee: true,
|
||||
feeAmount: feeAmount,
|
||||
});
|
||||
|
||||
this.resourceExists = true;
|
||||
this.setValues(newObject, {
|
||||
updated: Date.now(),
|
||||
});
|
||||
localStorage.setItem('temp-settings-data', JSON.stringify({}));
|
||||
this.valuesToBeSavedOnQdn = {};
|
||||
worker.terminate();
|
||||
} catch (error) {
|
||||
worker.terminate();
|
||||
}
|
||||
} catch (error) {
|
||||
console.log({ error });
|
||||
} finally {
|
||||
this.isSaving = false;
|
||||
}
|
||||
}
|
||||
|
||||
_updateTempSettingsData() {
|
||||
this.valuesToBeSavedOnQdn = JSON.parse(
|
||||
localStorage.getItem('temp-settings-data') || '{}'
|
||||
);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
window.addEventListener(
|
||||
'temp-settings-data-event',
|
||||
this._updateTempSettingsData
|
||||
);
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
window.removeEventListener(
|
||||
'temp-settings-data-event',
|
||||
this._updateTempSettingsData
|
||||
);
|
||||
super.disconnectedCallback();
|
||||
}
|
||||
|
||||
publishProfile(){
|
||||
|
||||
}
|
||||
|
||||
onClose(){
|
||||
this.isOpenProfileModalUpdate = false
|
||||
}
|
||||
render() {
|
||||
console.log('sup profile2', this.name);
|
||||
return html`
|
||||
${this.isSaving ||
|
||||
(!this.error && this.resourceExists === undefined)
|
||||
? html`
|
||||
<paper-spinner-lite
|
||||
active
|
||||
style="display: block; margin: 0 auto;"
|
||||
></paper-spinner-lite>
|
||||
`
|
||||
: !this.name
|
||||
? html`
|
||||
<mwc-icon
|
||||
id="profile-icon"
|
||||
class=${Object.values(this.valuesToBeSavedOnQdn)
|
||||
.length > 0 || this.resourceExists === false
|
||||
? 'active'
|
||||
: '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"
|
||||
>account_circle</mwc-icon
|
||||
>
|
||||
<vaadin-tooltip
|
||||
for="profile-icon"
|
||||
position="bottom"
|
||||
hover-delay=${300}
|
||||
hide-delay=${1}
|
||||
text=${this.error
|
||||
? get('save.saving1')
|
||||
: Object.values(this.valuesToBeSavedOnQdn)
|
||||
.length > 0 ||
|
||||
this.resourceExists === false
|
||||
? get('save.saving3')
|
||||
: get('save.saving2')}
|
||||
>
|
||||
</vaadin-tooltip>
|
||||
<popover-component for="profile-icon" message="">
|
||||
<div style="margin-bottom:20px">
|
||||
<p style="margin:10px 0px; font-size:16px">
|
||||
${`${get('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`
|
||||
<div style="user-select:none;cursor:pointer" @click=${()=> {
|
||||
this.isOpenProfileModalUpdate = !this.isOpenProfileModalUpdate
|
||||
}}>
|
||||
<avatar-component
|
||||
.resource=${{
|
||||
name: this.name,
|
||||
service: 'THUMBNAIL',
|
||||
identifier: 'qortal_avatar',
|
||||
}}
|
||||
name=${this.name}
|
||||
></avatar-component>
|
||||
</div>
|
||||
`}
|
||||
|
||||
<profile-modal-update
|
||||
?isOpen=${this.isOpenProfileModalUpdate}
|
||||
.setIsOpen=${(val)=> {
|
||||
this.isOpenProfileModalUpdate = val
|
||||
}}
|
||||
.onSubmit=${(val, isEdit)=> this.publishProfile(val, isEdit)}
|
||||
.editContent=${this.editContent}
|
||||
.onClose=${()=> this.onClose()}
|
||||
></profile-modal-update>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('profile-qdn', ProfileQdn);
|
@ -3,12 +3,13 @@ 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 WebWorker from '../WebWorkerFile.js';
|
||||
import '@polymer/paper-spinner/paper-spinner-lite.js';
|
||||
import '@vaadin/tooltip';
|
||||
import { get, translate } from 'lit-translate';
|
||||
import {
|
||||
decryptGroupData,
|
||||
|
||||
encryptDataGroup,
|
||||
objectToBase64,
|
||||
uint8ArrayToBase64,
|
||||
|
@ -337,6 +337,7 @@ class ShowPlugin extends connect(store)(LitElement) {
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log('this.tabs', this.tabs)
|
||||
const plugSrc = (myPlug) => {
|
||||
return myPlug === undefined ? 'about:blank' : `${window.location.origin}/plugin/${myPlug.domain}/${myPlug.page}${this.linkParam}`
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user