mirror of
https://github.com/Qortal/qortal-ui.git
synced 2025-03-27 15:55:55 +00:00
added list for friends
This commit is contained in:
parent
369fa15224
commit
a2f388a7b8
@ -1176,5 +1176,18 @@
|
|||||||
"notify1": "Confirming transaction",
|
"notify1": "Confirming transaction",
|
||||||
"notify2": "Transaction confirmed",
|
"notify2": "Transaction confirmed",
|
||||||
"explanation": "Your transaction is getting confirmed. To track its progress, click on the bell icon."
|
"explanation": "Your transaction is getting confirmed. To track its progress, click on the bell icon."
|
||||||
|
},
|
||||||
|
"friends": {
|
||||||
|
"friend1": "Add name",
|
||||||
|
"friend2": "Add friend",
|
||||||
|
"friend3": "Adding a friend allows you to connect easily with that person. Be sure to also follow that user to support the hosting of their published resources.",
|
||||||
|
"friend4": "Notes",
|
||||||
|
"friend5": "Follow name",
|
||||||
|
"friend6": "Alias",
|
||||||
|
"friend7": "Add an alias to better remember your friend (Optional)",
|
||||||
|
"friend8": "Send a Q-Chat message",
|
||||||
|
"friend9": "Send a Q-Mail",
|
||||||
|
"friend10": "Edit friend",
|
||||||
|
"friend11": "Following"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -43,6 +43,7 @@ import '../functional-components/side-menu-item.js'
|
|||||||
import './start-minting.js'
|
import './start-minting.js'
|
||||||
import './notification-view/notification-bell.js'
|
import './notification-view/notification-bell.js'
|
||||||
import './notification-view/notification-bell-general.js'
|
import './notification-view/notification-bell-general.js'
|
||||||
|
import './friends-view/friends-side-panel-parent.js'
|
||||||
|
|
||||||
|
|
||||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||||
@ -559,8 +560,10 @@ class AppView extends connect(store)(LitElement) {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div style="display:flex;align-items:center;gap:20px">
|
<div style="display:flex;align-items:center;gap:20px">
|
||||||
|
<friends-side-panel-parent></friends-side-panel-parent>
|
||||||
<notification-bell></notification-bell>
|
<notification-bell></notification-bell>
|
||||||
<notification-bell-general></notification-bell-general>
|
<notification-bell-general></notification-bell-general>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div style="display: inline;">
|
<div style="display: inline;">
|
||||||
<span>
|
<span>
|
||||||
@ -647,6 +650,8 @@ class AppView extends connect(store)(LitElement) {
|
|||||||
<mwc-button dense unelevated label="${translate("login.lp7")}" icon="lock_open" @click="${() => this.closeLockScreenActive()}"></mwc-button>
|
<mwc-button dense unelevated label="${translate("login.lp7")}" icon="lock_open" @click="${() => this.closeLockScreenActive()}"></mwc-button>
|
||||||
</div>
|
</div>
|
||||||
</paper-dialog>
|
</paper-dialog>
|
||||||
|
<div id="portal-target"></div>
|
||||||
|
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
222
core/src/components/friends-view/ChatSideNavHeads.js
Normal file
222
core/src/components/friends-view/ChatSideNavHeads.js
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
import { LitElement, html, css } from 'lit'
|
||||||
|
import { render } from 'lit/html.js'
|
||||||
|
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||||
|
import '@material/mwc-icon'
|
||||||
|
import '@vaadin/tooltip';
|
||||||
|
|
||||||
|
import './friend-item-actions'
|
||||||
|
|
||||||
|
class ChatSideNavHeads extends LitElement {
|
||||||
|
static get properties() {
|
||||||
|
return {
|
||||||
|
selectedAddress: { type: Object },
|
||||||
|
config: { type: Object },
|
||||||
|
chatInfo: { type: Object },
|
||||||
|
iconName: { type: String },
|
||||||
|
activeChatHeadUrl: { type: String },
|
||||||
|
isImageLoaded: { type: Boolean },
|
||||||
|
setActiveChatHeadUrl: {attribute: false},
|
||||||
|
openEditFriend: {attribute: false}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles() {
|
||||||
|
return css`
|
||||||
|
:host {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
padding: 10px 2px 10px 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
box-sizing: border-box;
|
||||||
|
font-size: 14px;
|
||||||
|
transition: 0.2s background-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
li:hover {
|
||||||
|
background-color: var(--lightChatHeadHover);
|
||||||
|
}
|
||||||
|
|
||||||
|
.active {
|
||||||
|
background: var(--menuactive);
|
||||||
|
border-left: 4px solid #3498db;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-icon {
|
||||||
|
font-size:40px;
|
||||||
|
color: var(--chat-group);
|
||||||
|
}
|
||||||
|
|
||||||
|
.status {
|
||||||
|
color: #92959e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clearfix {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clearfix:after {
|
||||||
|
visibility: hidden;
|
||||||
|
display: block;
|
||||||
|
font-size: 0;
|
||||||
|
content: " ";
|
||||||
|
clear: both;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
this.selectedAddress = {}
|
||||||
|
this.config = {
|
||||||
|
user: {
|
||||||
|
node: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.chatInfo = {}
|
||||||
|
this.iconName = ''
|
||||||
|
this.activeChatHeadUrl = ''
|
||||||
|
this.isImageLoaded = false
|
||||||
|
this.imageFetches = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
createImage(imageUrl) {
|
||||||
|
const imageHTMLRes = new Image();
|
||||||
|
imageHTMLRes.src = imageUrl;
|
||||||
|
imageHTMLRes.style= "width:30px; height:30px; float: left; border-radius:50%; font-size:14px";
|
||||||
|
imageHTMLRes.onclick= () => {
|
||||||
|
this.openDialogImage = true;
|
||||||
|
}
|
||||||
|
imageHTMLRes.onload = () => {
|
||||||
|
this.isImageLoaded = true;
|
||||||
|
}
|
||||||
|
imageHTMLRes.onerror = () => {
|
||||||
|
if (this.imageFetches < 4) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.imageFetches = this.imageFetches + 1;
|
||||||
|
imageHTMLRes.src = imageUrl;
|
||||||
|
}, 500);
|
||||||
|
} else {
|
||||||
|
this.isImageLoaded = false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return imageHTMLRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let avatarImg = ""
|
||||||
|
if (this.chatInfo.name) {
|
||||||
|
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
|
||||||
|
const nodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port;
|
||||||
|
const avatarUrl = `${nodeUrl}/arbitrary/THUMBNAIL/${this.chatInfo.name}/qortal_avatar?async=true&apiKey=${myNode.apiKey}`;
|
||||||
|
avatarImg = this.createImage(avatarUrl)
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<li style="display:flex; justify-content: space-between; align-items: center" @click=${(e) => {
|
||||||
|
const target = e.target
|
||||||
|
const popover =
|
||||||
|
this.shadowRoot.querySelector('friend-item-actions');
|
||||||
|
if (popover) {
|
||||||
|
popover.openPopover(target);
|
||||||
|
}
|
||||||
|
}} class="clearfix" id=${`friend-item-parent-${this.chatInfo.name}`}>
|
||||||
|
<div style="display:flex; flex-grow: 1; align-items: center">
|
||||||
|
${this.isImageLoaded ? html`${avatarImg}` : html``}
|
||||||
|
${!this.isImageLoaded && !this.chatInfo.name && !this.chatInfo.groupName
|
||||||
|
? html`<mwc-icon class="img-icon">account_circle</mwc-icon>`
|
||||||
|
: html``}
|
||||||
|
${!this.isImageLoaded && this.chatInfo.name
|
||||||
|
? html`<div
|
||||||
|
style="width:30px; height:30px; float: left; border-radius:50%; background: ${this.activeChatHeadUrl === this.chatInfo.url
|
||||||
|
? "var(--chatHeadBgActive)"
|
||||||
|
: "var(--chatHeadBg)"}; color: ${this.activeChatHeadUrl ===
|
||||||
|
this.chatInfo.url
|
||||||
|
? "var(--chatHeadTextActive)"
|
||||||
|
: "var(--chatHeadText)"}; font-weight:bold; display: flex; justify-content: center; align-items: center; text-transform: capitalize"
|
||||||
|
>
|
||||||
|
${this.chatInfo.name.charAt(0)}
|
||||||
|
</div>`
|
||||||
|
: ""}
|
||||||
|
${!this.isImageLoaded && this.chatInfo.groupName
|
||||||
|
? html`<div
|
||||||
|
style="width:30px; height:30px; float: left; border-radius:50%; background: ${this.activeChatHeadUrl === this.chatInfo.url
|
||||||
|
? "var(--chatHeadBgActive)"
|
||||||
|
: "var(--chatHeadBg)"}; color: ${this.activeChatHeadUrl === this.chatInfo.url
|
||||||
|
? "var(--chatHeadTextActive)"
|
||||||
|
: "var(--chatHeadText)"}; font-weight:bold; display: flex; justify-content: center; align-items: center; text-transform: capitalize"
|
||||||
|
>
|
||||||
|
${this.chatInfo.groupName.charAt(0)}
|
||||||
|
</div>`
|
||||||
|
: ""}
|
||||||
|
<div>
|
||||||
|
<div class="name">
|
||||||
|
<span style="float:left; padding-left: 8px; color: var(--chat-group);">
|
||||||
|
${this.chatInfo.groupName
|
||||||
|
? this.chatInfo.groupName
|
||||||
|
: this.chatInfo.name !== undefined
|
||||||
|
? this.chatInfo.name
|
||||||
|
: this.chatInfo.address.substr(0, 15)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div style="display:flex; align-items: center">
|
||||||
|
${this.chatInfo.willFollow ? html`
|
||||||
|
<mwc-icon id="willFollowIcon" style="color: var(--black)">connect_without_contact</mwc-icon>
|
||||||
|
<vaadin-tooltip
|
||||||
|
|
||||||
|
for="willFollowIcon"
|
||||||
|
position="top"
|
||||||
|
hover-delay=${200}
|
||||||
|
hide-delay=${1}
|
||||||
|
text=${get('friends.friend11')}>
|
||||||
|
</vaadin-tooltip>
|
||||||
|
` : ''}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<friend-item-actions
|
||||||
|
for=${`friend-item-parent-${this.chatInfo.name}`}
|
||||||
|
message=${get('notifications.explanation')}
|
||||||
|
.openEditFriend=${()=> {
|
||||||
|
this.openEditFriend(this.chatInfo)
|
||||||
|
}}
|
||||||
|
name=${this.chatInfo.name}
|
||||||
|
></friend-item-actions>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
shouldUpdate(changedProperties) {
|
||||||
|
if(changedProperties.has('activeChatHeadUrl')){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if(changedProperties.has('chatInfo')){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if(changedProperties.has('isImageLoaded')){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
getUrl(chatUrl) {
|
||||||
|
this.setActiveChatHeadUrl(chatUrl)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
window.customElements.define('chat-side-nav-heads', ChatSideNavHeads)
|
253
core/src/components/friends-view/add-friends-modal.js
Normal file
253
core/src/components/friends-view/add-friends-modal.js
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
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';
|
||||||
|
|
||||||
|
class AddFriendsModal extends LitElement {
|
||||||
|
static get properties() {
|
||||||
|
return {
|
||||||
|
isOpen: { type: Boolean },
|
||||||
|
setIsOpen: { attribute: false },
|
||||||
|
isLoading: { type: Boolean },
|
||||||
|
userSelected: { type: Object },
|
||||||
|
alias: { type: String },
|
||||||
|
willFollow: { type: Boolean },
|
||||||
|
notes: { type: String },
|
||||||
|
onSubmit: {attribute: false},
|
||||||
|
editContent: {type: Object},
|
||||||
|
onClose: {attribute: false}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.isOpen = false;
|
||||||
|
this.isLoading = false;
|
||||||
|
this.alias = '';
|
||||||
|
this.willFollow = true;
|
||||||
|
this.notes = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-button {
|
||||||
|
display: block;
|
||||||
|
--mdc-theme-primary: red;
|
||||||
|
}
|
||||||
|
.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;
|
||||||
|
max-height: 80vh;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
.modal-overlay.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
firstUpdated() {}
|
||||||
|
|
||||||
|
clearFields(){
|
||||||
|
this.alias = '';
|
||||||
|
this.willFollow = true;
|
||||||
|
this.notes = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
addFriend(){
|
||||||
|
|
||||||
|
this.onSubmit({
|
||||||
|
name: this.userSelected.name,
|
||||||
|
alias: this.alias,
|
||||||
|
notes: this.notes,
|
||||||
|
willFollow: this.willFollow
|
||||||
|
})
|
||||||
|
this.clearFields()
|
||||||
|
this.onClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async updated(changedProperties) {
|
||||||
|
if (changedProperties && changedProperties.has('editContent') && this.editContent) {
|
||||||
|
console.log('this.editedContent', this.editContent)
|
||||||
|
this.userSelected = {
|
||||||
|
name: this.editContent.name ?? '',
|
||||||
|
}
|
||||||
|
this.notes = this.editContent.notes ?? ''
|
||||||
|
this.willFollow = this.editContent.willFollow ?? true
|
||||||
|
this.alias = this.editContent.alias ?? ''
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
console.log('hello2', this.editContent)
|
||||||
|
return html`
|
||||||
|
<div class="modal-overlay ${this.isOpen ? '' : 'hidden'}">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div style="text-align:center">
|
||||||
|
<h1>${this.editContent ? translate('friends.friend10') : translate('friends.friend2')}</h1>
|
||||||
|
<hr />
|
||||||
|
</div>
|
||||||
|
<p>${translate('friends.friend3')}</p>
|
||||||
|
<div class="checkbox-row">
|
||||||
|
<label
|
||||||
|
for="willFollow"
|
||||||
|
id="willFollowLabel"
|
||||||
|
style="color: var(--black);"
|
||||||
|
>
|
||||||
|
${get('friends.friend5')}
|
||||||
|
</label>
|
||||||
|
<mwc-checkbox
|
||||||
|
style="margin-right: -15px;"
|
||||||
|
id="willFollow"
|
||||||
|
@change=${(e) => {
|
||||||
|
this.willFollow = e.target.checked;
|
||||||
|
}}
|
||||||
|
?checked=${this.willFollow}
|
||||||
|
></mwc-checkbox>
|
||||||
|
</div>
|
||||||
|
<div style="height: 15px"></div>
|
||||||
|
<div style="display: flex;flex-direction: column;">
|
||||||
|
<label
|
||||||
|
for="name"
|
||||||
|
id="nameLabel"
|
||||||
|
style="color: var(--black);"
|
||||||
|
>
|
||||||
|
${get('login.name')}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="name"
|
||||||
|
class="input"
|
||||||
|
?disabled=${true}
|
||||||
|
value=${this.userSelected ? this.userSelected.name : ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div style="height: 15px"></div>
|
||||||
|
<div style="display: flex;flex-direction: column;">
|
||||||
|
<label
|
||||||
|
for="alias"
|
||||||
|
id="aliasLabel"
|
||||||
|
style="color: var(--black);"
|
||||||
|
>
|
||||||
|
${get('friends.friend6')}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="alias"
|
||||||
|
placeholder=${translate('friends.friend7')}
|
||||||
|
class="input"
|
||||||
|
value=${this.alias}
|
||||||
|
@change=${(e) => (this.alias = e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div style="height: 15px"></div>
|
||||||
|
<div style="margin-bottom:0;">
|
||||||
|
<textarea
|
||||||
|
class="input"
|
||||||
|
@change=${(e) => (this.notes = e.target.value)}
|
||||||
|
value=${this.notes}
|
||||||
|
?disabled=${this.isLoading}
|
||||||
|
id="messageBoxAddFriend"
|
||||||
|
placeholder="${translate('friends.friend4')}"
|
||||||
|
rows="3"
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
|
<div style="display:flex;justify-content:space-between;align-items:center;margin-top:20px">
|
||||||
|
|
||||||
|
<mwc-button
|
||||||
|
?disabled="${this.isLoading}"
|
||||||
|
slot="secondaryAction"
|
||||||
|
@click="${() => {
|
||||||
|
this.setIsOpen(false)
|
||||||
|
this.clearFields()
|
||||||
|
this.onClose()
|
||||||
|
} }"
|
||||||
|
class="close-button"
|
||||||
|
>
|
||||||
|
${translate('general.close')}
|
||||||
|
</mwc-button>
|
||||||
|
<mwc-button
|
||||||
|
?disabled="${this.isLoading}"
|
||||||
|
slot="primaryAction"
|
||||||
|
@click=${() => {
|
||||||
|
this.addFriend();
|
||||||
|
}}
|
||||||
|
>${this.editContent ? translate('friends.friend10') : translate('friends.friend2')}
|
||||||
|
</mwc-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define('add-friends-modal', AddFriendsModal);
|
224
core/src/components/friends-view/friend-item-actions.js
Normal file
224
core/src/components/friends-view/friend-item-actions.js
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
// popover-component.js
|
||||||
|
import { LitElement, html, css } from 'lit';
|
||||||
|
import { createPopper } from '@popperjs/core';
|
||||||
|
import '@material/mwc-icon';
|
||||||
|
import { use, get, translate } from 'lit-translate';
|
||||||
|
import { store } from '../../store';
|
||||||
|
import { connect } from 'pwa-helpers';
|
||||||
|
import { setNewTab, setSideEffectAction } from '../../redux/app/app-actions';
|
||||||
|
import ShortUniqueId from 'short-unique-id';
|
||||||
|
|
||||||
|
export class FriendItemActions extends connect(store)(LitElement) {
|
||||||
|
static styles = css`
|
||||||
|
:host {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
background-color: var(--white);
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
padding: 8px;
|
||||||
|
z-index: 10;
|
||||||
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||||
|
color: var(--black);
|
||||||
|
max-width: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-icon {
|
||||||
|
cursor: pointer;
|
||||||
|
float: right;
|
||||||
|
margin-left: 10px;
|
||||||
|
color: var(--black);
|
||||||
|
}
|
||||||
|
|
||||||
|
.send-message-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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.send-message-button:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #03a8f485;
|
||||||
|
}
|
||||||
|
.action-parent {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div[tabindex='0']:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
static get properties() {
|
||||||
|
return {
|
||||||
|
for: { type: String, reflect: true },
|
||||||
|
message: { type: String },
|
||||||
|
openEditFriend: { attribute: false },
|
||||||
|
name: { type: String },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.message = '';
|
||||||
|
this.nodeUrl = this.getNodeUrl();
|
||||||
|
this.uid = new ShortUniqueId();
|
||||||
|
this.getUserAddress = this.getUserAddress.bind(this)
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
firstUpdated() {
|
||||||
|
// We'll defer the popper attachment to the openPopover() method to ensure target availability
|
||||||
|
}
|
||||||
|
|
||||||
|
attachToTarget(target) {
|
||||||
|
console.log({ target });
|
||||||
|
if (!this.popperInstance && target) {
|
||||||
|
this.popperInstance = createPopper(target, this, {
|
||||||
|
placement: 'bottom',
|
||||||
|
strategy: 'fixed',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
openPopover(target) {
|
||||||
|
this.attachToTarget(target);
|
||||||
|
this.style.display = 'block';
|
||||||
|
setTimeout(() => {
|
||||||
|
this.shadowRoot.getElementById('parent-div').focus();
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
closePopover() {
|
||||||
|
this.style.display = 'none';
|
||||||
|
if (this.popperInstance) {
|
||||||
|
this.popperInstance.destroy();
|
||||||
|
this.popperInstance = null;
|
||||||
|
}
|
||||||
|
this.requestUpdate();
|
||||||
|
}
|
||||||
|
handleBlur() {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.closePopover();
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getUserAddress() {
|
||||||
|
try {
|
||||||
|
const url = `${this.nodeUrl}/names/${this.name}`;
|
||||||
|
const res = await fetch(url);
|
||||||
|
const result = await res.json();
|
||||||
|
if (result.error === 401) {
|
||||||
|
return '';
|
||||||
|
} else {
|
||||||
|
return result.owner;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return html`
|
||||||
|
<div id="parent-div" tabindex="0" @blur=${this.handleBlur}>
|
||||||
|
<span class="close-icon" @click="${this.closePopover}"
|
||||||
|
><mwc-icon style="color: var(--black)"
|
||||||
|
>close</mwc-icon
|
||||||
|
></span
|
||||||
|
>
|
||||||
|
<div class="action-parent">
|
||||||
|
<div
|
||||||
|
class="send-message-button"
|
||||||
|
@click="${() => {
|
||||||
|
this.openEditFriend();
|
||||||
|
this.closePopover();
|
||||||
|
}}"
|
||||||
|
>
|
||||||
|
${translate('friends.friend10')}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="send-message-button"
|
||||||
|
@click="${async () => {
|
||||||
|
const address = await this.getUserAddress();
|
||||||
|
if (!address) return;
|
||||||
|
store.dispatch(
|
||||||
|
setNewTab({
|
||||||
|
url: `q-chat`,
|
||||||
|
id: this.uid.rnd(),
|
||||||
|
myPlugObj: {
|
||||||
|
url: 'q-chat',
|
||||||
|
domain: 'core',
|
||||||
|
page: 'messaging/q-chat/index.html',
|
||||||
|
title: 'Q-Chat',
|
||||||
|
icon: 'vaadin:chat',
|
||||||
|
mwcicon: 'forum',
|
||||||
|
pluginNumber: 'plugin-qhsyOnpRhT',
|
||||||
|
menus: [],
|
||||||
|
parent: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
openExisting: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
store.dispatch(
|
||||||
|
setSideEffectAction({
|
||||||
|
type: 'openPrivateChat',
|
||||||
|
data: {
|
||||||
|
address,
|
||||||
|
name: this.name
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
this.closePopover();
|
||||||
|
}}"
|
||||||
|
>
|
||||||
|
${translate('friends.friend8')}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="send-message-button"
|
||||||
|
@click="${() => {
|
||||||
|
const query = `?service=APP&name=Q-Mail/to/${this.name}`;
|
||||||
|
store.dispatch(
|
||||||
|
setNewTab({
|
||||||
|
url: `qdn/browser/index.html${query}`,
|
||||||
|
id: this.uid.rnd(),
|
||||||
|
myPlugObj: {
|
||||||
|
url: 'myapp',
|
||||||
|
domain: 'core',
|
||||||
|
page: `qdn/browser/index.html${query}`,
|
||||||
|
title: 'Q-Mail',
|
||||||
|
icon: 'vaadin:mailbox',
|
||||||
|
mwcicon: 'mail_outline',
|
||||||
|
menus: [],
|
||||||
|
parent: false,
|
||||||
|
},
|
||||||
|
openExisting: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
this.closePopover();
|
||||||
|
}}"
|
||||||
|
>
|
||||||
|
${translate('friends.friend9')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define('friend-item-actions', FriendItemActions);
|
@ -0,0 +1,61 @@
|
|||||||
|
import { LitElement, html, css } from 'lit';
|
||||||
|
import '@material/mwc-icon';
|
||||||
|
import './friends-side-panel.js';
|
||||||
|
class FriendsSidePanelParent extends LitElement {
|
||||||
|
static get properties() {
|
||||||
|
return {
|
||||||
|
isOpen: {type: Boolean}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.isOpen = false
|
||||||
|
}
|
||||||
|
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 */
|
||||||
|
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return html`
|
||||||
|
<mwc-icon @click=${()=> {
|
||||||
|
this.isOpen = !this.isOpen
|
||||||
|
}} style="color: var(--black); cursor:pointer"
|
||||||
|
>group</mwc-icon
|
||||||
|
>
|
||||||
|
<friends-side-panel ?isOpen=${this.isOpen} .setIsOpen=${(val)=> this.isOpen = val}></friends-side-panel>
|
||||||
|
|
||||||
|
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define('friends-side-panel-parent', FriendsSidePanelParent);
|
61
core/src/components/friends-view/friends-side-panel.js
Normal file
61
core/src/components/friends-view/friends-side-panel.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import { LitElement, html, css } from 'lit';
|
||||||
|
import '@material/mwc-icon';
|
||||||
|
import './friends-view'
|
||||||
|
class FriendsSidePanel extends LitElement {
|
||||||
|
static get properties() {
|
||||||
|
return {
|
||||||
|
setIsOpen: { attribute: false},
|
||||||
|
isOpen: {type: Boolean}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static styles = css`
|
||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
position: fixed;
|
||||||
|
top: 55px;
|
||||||
|
right: 0px;
|
||||||
|
width: 420px;
|
||||||
|
max-width: 95%;
|
||||||
|
height: calc(100vh - 55px);
|
||||||
|
background-color: var(--white);
|
||||||
|
border-left: 1px solid rgb(224, 224, 224);
|
||||||
|
overflow-y: auto;
|
||||||
|
z-index: 1;
|
||||||
|
transform: translateX(100%); /* start from outside the right edge */
|
||||||
|
transition: transform 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
:host([isOpen]) {
|
||||||
|
transform: unset; /* slide in to its original position */
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 16px;
|
||||||
|
border-bottom: 1px solid #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return html`
|
||||||
|
<div class="header">
|
||||||
|
<span>Panel Title</span>
|
||||||
|
<mwc-icon style="cursor:pointer" @click=${()=> {
|
||||||
|
this.setIsOpen(false)
|
||||||
|
}}>close</mwc-icon>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<friends-view></friends-view></div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define('friends-side-panel', FriendsSidePanel);
|
178
core/src/components/friends-view/friends-view-css.js
Normal file
178
core/src/components/friends-view/friends-view-css.js
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
import { css } from 'lit'
|
||||||
|
|
||||||
|
export const friendsViewStyles = css`
|
||||||
|
.top-bar-icon {
|
||||||
|
cursor: pointer;
|
||||||
|
height: 18px;
|
||||||
|
width: 18px;
|
||||||
|
transition: 0.2s all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-bar-icon:hover {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-row {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
height: 50px;
|
||||||
|
flex:0
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-body {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-grow: 1;
|
||||||
|
margin-top: 5px;
|
||||||
|
padding: 0px 6px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-body::-webkit-scrollbar-track {
|
||||||
|
background-color: whitesmoke;
|
||||||
|
border-radius: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-body::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
border-radius: 7px;
|
||||||
|
background-color: whitesmoke;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-body::-webkit-scrollbar-thumb {
|
||||||
|
background-color: rgb(180, 176, 176);
|
||||||
|
border-radius: 7px;
|
||||||
|
transition: all 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-body::-webkit-scrollbar-thumb:hover {
|
||||||
|
background-color: rgb(148, 146, 146);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: var(--black);
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-right-panel-label {
|
||||||
|
font-family: Montserrat, sans-serif;
|
||||||
|
color: var(--group-header);
|
||||||
|
padding: 5px;
|
||||||
|
font-size: 13px;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-name {
|
||||||
|
font-family: Raleway, sans-serif;
|
||||||
|
font-size: 20px;
|
||||||
|
color: var(--chat-bubble-msg-color);
|
||||||
|
text-align: center;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-description {
|
||||||
|
font-family: Roboto, sans-serif;
|
||||||
|
color: var(--chat-bubble-msg-color);
|
||||||
|
letter-spacing: 0.3px;
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-top: 15px;
|
||||||
|
word-break: break-word;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-subheader {
|
||||||
|
font-family: Montserrat, sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--chat-bubble-msg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-data {
|
||||||
|
font-family: Roboto, sans-serif;
|
||||||
|
letter-spacing: 0.3px;
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--chat-bubble-msg-color);
|
||||||
|
}
|
||||||
|
.search-results-div {
|
||||||
|
position: absolute;
|
||||||
|
top: 25px;
|
||||||
|
right: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name-input {
|
||||||
|
width: 100%;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name-input::selection {
|
||||||
|
background-color: var(--mdc-theme-primary);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name-input::placeholder {
|
||||||
|
opacity: 0.9;
|
||||||
|
color: var(--black);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-field {
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-icon {
|
||||||
|
position: absolute;
|
||||||
|
right: 3px;
|
||||||
|
color: var(--chat-bubble-msg-color);
|
||||||
|
transition: all 0.3s ease-in-out;
|
||||||
|
background: none;
|
||||||
|
border-radius: 50%;
|
||||||
|
padding: 6px 3px;
|
||||||
|
font-size: 21px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-icon:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
background: #d7d7d75c;
|
||||||
|
}
|
||||||
|
`
|
303
core/src/components/friends-view/friends-view.js
Normal file
303
core/src/components/friends-view/friends-view.js
Normal file
@ -0,0 +1,303 @@
|
|||||||
|
import { LitElement, html, css } from 'lit';
|
||||||
|
import { render } from 'lit/html.js';
|
||||||
|
import { connect } from 'pwa-helpers';
|
||||||
|
|
||||||
|
import '@material/mwc-button';
|
||||||
|
import '@material/mwc-dialog';
|
||||||
|
import '@polymer/paper-spinner/paper-spinner-lite.js';
|
||||||
|
import '@polymer/paper-progress/paper-progress.js';
|
||||||
|
import '@material/mwc-icon';
|
||||||
|
import '@vaadin/icon'
|
||||||
|
import '@vaadin/icons'
|
||||||
|
import '@vaadin/button';
|
||||||
|
import './ChatSideNavHeads';
|
||||||
|
import '../../../../plugins/plugins/core/components/ChatSearchResults'
|
||||||
|
import './add-friends-modal'
|
||||||
|
|
||||||
|
import {
|
||||||
|
use,
|
||||||
|
get,
|
||||||
|
translate,
|
||||||
|
translateUnsafeHTML,
|
||||||
|
registerTranslateConfig,
|
||||||
|
} from 'lit-translate';
|
||||||
|
import { store } from '../../store';
|
||||||
|
import { friendsViewStyles } from './friends-view-css';
|
||||||
|
import { parentEpml } from '../show-plugin';
|
||||||
|
|
||||||
|
class FriendsView extends connect(store)(LitElement) {
|
||||||
|
static get properties() {
|
||||||
|
return {
|
||||||
|
error: { type: Boolean },
|
||||||
|
toggle: { attribute: false },
|
||||||
|
userName: { type: String },
|
||||||
|
errorMessage: { type: String },
|
||||||
|
successMessage: { type: String },
|
||||||
|
setUserName: { attribute: false },
|
||||||
|
friendList: { type: Array },
|
||||||
|
userSelected: { type: Object },
|
||||||
|
isLoading: {type: Boolean},
|
||||||
|
userFoundModalOpen: {type: Boolean},
|
||||||
|
userFound: { type: Array},
|
||||||
|
isOpenAddFriendsModal: {type: Boolean},
|
||||||
|
editContent: {type: Object}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
static get styles() {
|
||||||
|
return [friendsViewStyles];
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.error = false;
|
||||||
|
this.observerHandler = this.observerHandler.bind(this);
|
||||||
|
this.viewElement = '';
|
||||||
|
this.downObserverElement = '';
|
||||||
|
this.myAddress =
|
||||||
|
window.parent.reduxStore.getState().app.selectedAddress.address;
|
||||||
|
this.errorMessage = '';
|
||||||
|
this.successMessage = '';
|
||||||
|
this.friendList = [{
|
||||||
|
|
||||||
|
name: "Phil"
|
||||||
|
|
||||||
|
}];
|
||||||
|
this.userSelected = {};
|
||||||
|
this.isLoading = false;
|
||||||
|
this.userFoundModalOpen = false
|
||||||
|
this.userFound = [];
|
||||||
|
this.nodeUrl = this.getNodeUrl();
|
||||||
|
this.myNode = this.getMyNode();
|
||||||
|
this.isOpenAddFriendsModal = false
|
||||||
|
this.editContent = null
|
||||||
|
this.addToFriendList = this.addToFriendList.bind(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
getMoreFriends() {}
|
||||||
|
|
||||||
|
firstUpdated() {
|
||||||
|
this.viewElement = this.shadowRoot.getElementById('viewElement');
|
||||||
|
this.downObserverElement =
|
||||||
|
this.shadowRoot.getElementById('downObserver');
|
||||||
|
this.elementObserver();
|
||||||
|
}
|
||||||
|
|
||||||
|
elementObserver() {
|
||||||
|
const options = {
|
||||||
|
root: this.viewElement,
|
||||||
|
rootMargin: '0px',
|
||||||
|
threshold: 1,
|
||||||
|
};
|
||||||
|
// identify an element to observe
|
||||||
|
const elementToObserve = this.downObserverElement;
|
||||||
|
// passing it a callback function
|
||||||
|
const observer = new IntersectionObserver(
|
||||||
|
this.observerHandler,
|
||||||
|
options
|
||||||
|
);
|
||||||
|
// call `observe()` on that MutationObserver instance,
|
||||||
|
// passing it the element to observe, and the options object
|
||||||
|
observer.observe(elementToObserve);
|
||||||
|
}
|
||||||
|
|
||||||
|
observerHandler(entries) {
|
||||||
|
if (!entries[0].isIntersecting) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (this.friendList.length < 20) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.getMoreFriends();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async userSearch() {
|
||||||
|
const nameValue = this.shadowRoot.getElementById('sendTo').value
|
||||||
|
if(!nameValue) {
|
||||||
|
this.userFound = []
|
||||||
|
this.userFoundModalOpen = true
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const url = `${this.nodeUrl}/names/${nameValue}`
|
||||||
|
const res = await fetch(url)
|
||||||
|
const result = await res.json()
|
||||||
|
if (result.error === 401) {
|
||||||
|
this.userFound = []
|
||||||
|
} else {
|
||||||
|
this.userFound = [
|
||||||
|
...this.userFound,
|
||||||
|
result,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
this.userFoundModalOpen = true;
|
||||||
|
} catch (error) {
|
||||||
|
// let err4string = get("chatpage.cchange35");
|
||||||
|
// parentEpml.request('showSnackBar', `${err4string}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getApiKey() {
|
||||||
|
const apiNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||||
|
let apiKey = apiNode.apiKey
|
||||||
|
return apiKey
|
||||||
|
}
|
||||||
|
|
||||||
|
async myFollowName(name) {
|
||||||
|
let items = [
|
||||||
|
name
|
||||||
|
]
|
||||||
|
let namesJsonString = JSON.stringify({ "items": items })
|
||||||
|
|
||||||
|
let ret = await parentEpml.request('apiCall', {
|
||||||
|
url: `/lists/followedNames?apiKey=${this.getApiKey()}`,
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: `${namesJsonString}`
|
||||||
|
})
|
||||||
|
|
||||||
|
if (ret === true) {
|
||||||
|
this.myFollowedNames = this.myFollowedNames.filter(item => item != name)
|
||||||
|
this.myFollowedNames.push(name)
|
||||||
|
} else {
|
||||||
|
let err3string = get("appspage.schange22")
|
||||||
|
parentEpml.request('showSnackBar', `${err3string}`)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
addToFriendList(val){
|
||||||
|
if(this.editContent){
|
||||||
|
const findFriend = this.friendList.findIndex(item=> item.name === val.name)
|
||||||
|
if(findFriend !== -1){
|
||||||
|
const copyList = [...this.friendList]
|
||||||
|
copyList[findFriend] = val
|
||||||
|
this.friendList = copyList
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
this.friendList = [...this.friendList, val]
|
||||||
|
}
|
||||||
|
if(val.willFollow){
|
||||||
|
this.myFollowName(val.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.userSelected = {};
|
||||||
|
this.isLoading = false;
|
||||||
|
this.isOpenAddFriendsModal = false
|
||||||
|
this.editContent = null
|
||||||
|
}
|
||||||
|
openEditFriend(val){
|
||||||
|
this.isOpenAddFriendsModal = true
|
||||||
|
this.userSelected = val
|
||||||
|
this.editContent = val
|
||||||
|
}
|
||||||
|
|
||||||
|
onClose(){
|
||||||
|
console.log('hello100')
|
||||||
|
this.isLoading = false;
|
||||||
|
this.isOpenAddFriendsModal = false
|
||||||
|
this.editContent = null
|
||||||
|
this.userSelected = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
console.log('friends', this.userSelected);
|
||||||
|
return html`
|
||||||
|
<div class="container">
|
||||||
|
<div id="viewElement" class="container-body" style=${"position: relative"}>
|
||||||
|
<p class="group-name">My Friends</p>
|
||||||
|
<div class="search-field">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="name-input"
|
||||||
|
?disabled=${this.isLoading}
|
||||||
|
id="sendTo"
|
||||||
|
placeholder="${translate("friends.friend1")}"
|
||||||
|
value=${this.userSelected.name ? this.userSelected.name: ''}
|
||||||
|
@keypress=${(e) => {
|
||||||
|
if(e.key === 'Enter'){
|
||||||
|
this.userSearch()
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<vaadin-icon
|
||||||
|
@click=${this.userSearch}
|
||||||
|
slot="icon"
|
||||||
|
icon="vaadin:open-book"
|
||||||
|
class="search-icon">
|
||||||
|
</vaadin-icon>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="search-results-div">
|
||||||
|
<chat-search-results
|
||||||
|
.onClickFunc=${(result) => {
|
||||||
|
this.userSelected = result;
|
||||||
|
this.isOpenAddFriendsModal = true
|
||||||
|
|
||||||
|
console.log({result});
|
||||||
|
this.userFound = [];
|
||||||
|
this.userFoundModalOpen = false;
|
||||||
|
}}
|
||||||
|
.closeFunc=${() => {
|
||||||
|
this.userFoundModalOpen = false;
|
||||||
|
this.userFound = [];
|
||||||
|
}}
|
||||||
|
.searchResults=${this.userFound}
|
||||||
|
?isOpen=${this.userFoundModalOpen}
|
||||||
|
?loading=${this.isLoading}>
|
||||||
|
</chat-search-results>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
|
||||||
|
${this.friendList.map((item) => {
|
||||||
|
return html`<chat-side-nav-heads
|
||||||
|
activeChatHeadUrl=""
|
||||||
|
.setActiveChatHeadUrl=${(val) => {
|
||||||
|
|
||||||
|
}}
|
||||||
|
.chatInfo=${item}
|
||||||
|
.openEditFriend=${(val)=> this.openEditFriend(val)}
|
||||||
|
></chat-side-nav-heads>`;
|
||||||
|
})}
|
||||||
|
<div id="downObserver"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<add-friends-modal
|
||||||
|
?isOpen=${this.isOpenAddFriendsModal}
|
||||||
|
.setIsOpen=${(val)=> {
|
||||||
|
this.isOpenAddFriendsModal = val
|
||||||
|
}}
|
||||||
|
.userSelected=${this.userSelected}
|
||||||
|
.onSubmit=${(val)=> this.addToFriendList(val)}
|
||||||
|
.editContent=${this.editContent}
|
||||||
|
.onClose=${()=> this.onClose()}
|
||||||
|
>
|
||||||
|
</add-friends-modal>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define('friends-view', FriendsView);
|
@ -111,13 +111,13 @@ class NotificationBellGeneral extends connect(store)(LitElement) {
|
|||||||
>
|
>
|
||||||
${hasOngoing
|
${hasOngoing
|
||||||
? html`
|
? html`
|
||||||
<mwc-icon style="color: green;cursor:pointer"
|
<mwc-icon style="color: green;cursor:pointer;user-select:none"
|
||||||
>notifications</mwc-icon
|
>notifications</mwc-icon
|
||||||
>
|
>
|
||||||
`
|
`
|
||||||
: html`
|
: html`
|
||||||
<mwc-icon
|
<mwc-icon
|
||||||
style="color: var(--black); cursor:pointer"
|
style="color: var(--black); cursor:pointer;user-select:none"
|
||||||
>notifications</mwc-icon
|
>notifications</mwc-icon
|
||||||
>
|
>
|
||||||
`}
|
`}
|
||||||
|
@ -26,11 +26,9 @@ import '@vaadin/grid'
|
|||||||
import '@vaadin/text-field'
|
import '@vaadin/text-field'
|
||||||
import '../custom-elements/frag-file-input.js'
|
import '../custom-elements/frag-file-input.js'
|
||||||
|
|
||||||
const chatLastSeen = localForage.createInstance({
|
|
||||||
name: "chat-last-seen",
|
|
||||||
})
|
|
||||||
|
|
||||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
|
||||||
|
export const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
||||||
|
|
||||||
class ShowPlugin extends connect(store)(LitElement) {
|
class ShowPlugin extends connect(store)(LitElement) {
|
||||||
static get properties() {
|
static get properties() {
|
||||||
|
43
package-lock.json
generated
43
package-lock.json
generated
@ -7407,15 +7407,6 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/is-path-inside": {
|
|
||||||
"version": "3.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
|
|
||||||
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/is-plain-object": {
|
"node_modules/is-plain-object": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
|
||||||
@ -7462,15 +7453,6 @@
|
|||||||
"is-potential-custom-element-name": "^1.0.0"
|
"is-potential-custom-element-name": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/is-valid-element-name": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-valid-element-name/-/is-valid-element-name-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-GZITEJY2LkSjQfaIPBha7eyZv+ge0PhBR7KITeCCWvy7VBQrCUdFkvpI+HrAPQjVtVjy1LvlEkqQTHckoszruw==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"is-potential-custom-element-name": "^1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/is-wsl": {
|
"node_modules/is-wsl": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
|
||||||
@ -7758,19 +7740,6 @@
|
|||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/levn": {
|
|
||||||
"version": "0.4.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
|
|
||||||
"integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"prelude-ls": "^1.2.1",
|
|
||||||
"type-check": "~0.4.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.8.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/lie": {
|
"node_modules/lie": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
|
||||||
@ -9746,18 +9715,6 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/strip-json-comments": {
|
|
||||||
"version": "3.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
|
|
||||||
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/strip-outer": {
|
"node_modules/strip-outer": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz",
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
import { LitElement, html } from 'lit'
|
import { LitElement, html } from 'lit'
|
||||||
import { render } from 'lit/html.js'
|
import { render } from 'lit/html.js'
|
||||||
import { Epml } from '../../../epml.js'
|
|
||||||
import { chatSearchResultsStyles } from './ChatSearchResults-css.js'
|
import { chatSearchResultsStyles } from './ChatSearchResults-css.js'
|
||||||
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
|
||||||
import '@vaadin/icon'
|
import '@vaadin/icon'
|
||||||
import '@vaadin/icons'
|
import '@vaadin/icons'
|
||||||
|
|
||||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
|
|
||||||
|
|
||||||
export class ChatSearchResults extends LitElement {
|
export class ChatSearchResults extends LitElement {
|
||||||
static get properties() {
|
static get properties() {
|
||||||
@ -19,7 +17,10 @@ export class ChatSearchResults extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static styles = [chatSearchResultsStyles]
|
static get styles() {
|
||||||
|
return [chatSearchResultsStyles];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return html`
|
return html`
|
||||||
|
@ -221,6 +221,8 @@ class Chat extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
console.log('chatHeads', this.chatHeads)
|
||||||
|
console.log('chatHeadsObj', this.chatHeadsObj)
|
||||||
return html`
|
return html`
|
||||||
<div class="container clearfix">
|
<div class="container clearfix">
|
||||||
<div class="people-list" id="people-list">
|
<div class="people-list" id="people-list">
|
||||||
@ -516,6 +518,26 @@ class Chat extends LitElement {
|
|||||||
chatHeads = JSON.parse(chatHeads)
|
chatHeads = JSON.parse(chatHeads)
|
||||||
this.getChatHeadFromState(chatHeads)
|
this.getChatHeadFromState(chatHeads)
|
||||||
})
|
})
|
||||||
|
parentEpml.subscribe('side_effect_action', async sideEffectActionParam => {
|
||||||
|
const sideEffectAction = JSON.parse(sideEffectActionParam)
|
||||||
|
|
||||||
|
if(sideEffectAction && sideEffectAction.type === 'openPrivateChat'){
|
||||||
|
const name = sideEffectAction.data.name
|
||||||
|
const address = sideEffectAction.data.address
|
||||||
|
console.log({address}, this.chatHeadsObj)
|
||||||
|
if(this.chatHeadsObj.direct && this.chatHeadsObj.direct.find(item=> item.address === address)){
|
||||||
|
this.setActiveChatHeadUrl(`direct/${address}`)
|
||||||
|
window.parent.reduxStore.dispatch(
|
||||||
|
window.parent.reduxAction.setSideEffectAction(null))
|
||||||
|
} else {
|
||||||
|
this.setOpenPrivateMessage({
|
||||||
|
open: true,
|
||||||
|
name: name
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
parentEpml.request('apiCall', {
|
parentEpml.request('apiCall', {
|
||||||
url: `/addresses/balance/${window.parent.reduxStore.getState().app.selectedAddress.address}`
|
url: `/addresses/balance/${window.parent.reduxStore.getState().app.selectedAddress.address}`
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user