mirror of
				https://github.com/Qortal/qortal-ui.git
				synced 2025-11-04 06:37:47 +00:00 
			
		
		
		
	added tx notification for join group
This commit is contained in:
		@@ -836,7 +836,8 @@
 | 
			
		||||
		"cchange92": "Unread messages below",
 | 
			
		||||
		"cchange93": "Image copied to clipboard",
 | 
			
		||||
		"cchange94": "loaded",
 | 
			
		||||
		"cchange95": "Only my resources"
 | 
			
		||||
		"cchange95": "Only my resources",
 | 
			
		||||
		"cchange96": "Open Group Management"
 | 
			
		||||
	},
 | 
			
		||||
	"welcomepage": {
 | 
			
		||||
		"wcchange1": "Welcome to Q-Chat",
 | 
			
		||||
@@ -1168,5 +1169,9 @@
 | 
			
		||||
		"lot11": "There are no open lotteries!",
 | 
			
		||||
		"lot12": "There are no finished lotteries!",
 | 
			
		||||
		"lot13": "Players"
 | 
			
		||||
	},
 | 
			
		||||
	"notifications": {
 | 
			
		||||
		"notify1": "Confirming transaction",
 | 
			
		||||
		"notify2": "Transaction confirmed"
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -42,6 +42,8 @@ import '../functional-components/side-menu.js'
 | 
			
		||||
import '../functional-components/side-menu-item.js'
 | 
			
		||||
import './start-minting.js'
 | 
			
		||||
import './notification-view/notification-bell.js'
 | 
			
		||||
import './notification-view/notification-bell-general.js'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
 | 
			
		||||
 | 
			
		||||
@@ -556,7 +558,10 @@ class AppView extends connect(store)(LitElement) {
 | 
			
		||||
                                    <img src="${this.config.coin.logo}" style="height:32px; padding-left:12px;">
 | 
			
		||||
                                </span>
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div style="display:flex;align-items:center;gap:20px">
 | 
			
		||||
                            <notification-bell></notification-bell>
 | 
			
		||||
                            <notification-bell-general></notification-bell-general>
 | 
			
		||||
                            </div>
 | 
			
		||||
                            <div style="display: inline;">
 | 
			
		||||
                                <span>
 | 
			
		||||
                                    <img src="/img/${translate("selectmenu.languageflag")}-flag-round-icon-32.png" style="width: 32px; height: 32px; padding-top: 4px;">
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ import './login-section.js'
 | 
			
		||||
import '../qort-theme-toggle.js'
 | 
			
		||||
 | 
			
		||||
import settings from '../../functional-components/settings-page.js'
 | 
			
		||||
import { addAutoLoadImageChat, removeAutoLoadImageChat, addChatLastSeen, allowQAPPAutoAuth, removeQAPPAutoAuth, removeQAPPAutoLists, allowQAPPAutoLists, addTabInfo, setTabNotifications, setNewTab } from '../../redux/app/app-actions.js'
 | 
			
		||||
import { addAutoLoadImageChat, removeAutoLoadImageChat, addChatLastSeen, allowQAPPAutoAuth, removeQAPPAutoAuth, removeQAPPAutoLists, allowQAPPAutoLists, addTabInfo, setTabNotifications, setNewTab, setNewNotification } from '../../redux/app/app-actions.js'
 | 
			
		||||
 | 
			
		||||
window.reduxStore = store
 | 
			
		||||
window.reduxAction = {
 | 
			
		||||
@@ -28,7 +28,8 @@ window.reduxAction = {
 | 
			
		||||
    removeQAPPAutoLists: removeQAPPAutoLists,
 | 
			
		||||
    addTabInfo: addTabInfo,
 | 
			
		||||
    setTabNotifications: setTabNotifications,
 | 
			
		||||
    setNewTab: setNewTab
 | 
			
		||||
    setNewTab: setNewTab,
 | 
			
		||||
    setNewNotification: setNewNotification
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const animationDuration = 0.7 // Seconds
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,535 @@
 | 
			
		||||
import { LitElement, html, css } from 'lit';
 | 
			
		||||
import { connect } from 'pwa-helpers';
 | 
			
		||||
 | 
			
		||||
import '@vaadin/item';
 | 
			
		||||
import '@vaadin/list-box';
 | 
			
		||||
import '@polymer/paper-icon-button/paper-icon-button.js';
 | 
			
		||||
import '@polymer/iron-icons/iron-icons.js';
 | 
			
		||||
import { store } from '../../store.js';
 | 
			
		||||
import { setNewNotification, setNewTab } from '../../redux/app/app-actions.js';
 | 
			
		||||
import { routes } from '../../plugins/routes.js';
 | 
			
		||||
import '@material/mwc-icon';
 | 
			
		||||
import { translate } from 'lit-translate';
 | 
			
		||||
import { repeat } from 'lit/directives/repeat.js';
 | 
			
		||||
 | 
			
		||||
import config from '../../notifications/config.js';
 | 
			
		||||
import '../../../../plugins/plugins/core/components/TimeAgo.js';
 | 
			
		||||
import './popover.js';
 | 
			
		||||
 | 
			
		||||
const currentNotification = {
 | 
			
		||||
	type: 'JOIN_GROUP',
 | 
			
		||||
	timestamp: Date.now(),
 | 
			
		||||
	status: 'confirming',
 | 
			
		||||
	reference: {
 | 
			
		||||
		signature:
 | 
			
		||||
			'5wpPP7ngE13z8x7FKr3tkx5AhMyzWAcFeTmkyefSbddRZ3ieMRcbwt4VDz5bakJzpFaE16NcSofa8w35AGLN4J47',
 | 
			
		||||
	},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const notifications = [currentNotification];
 | 
			
		||||
class NotificationBellGeneral extends connect(store)(LitElement) {
 | 
			
		||||
	static properties = {
 | 
			
		||||
		notifications: { type: Array },
 | 
			
		||||
		showNotifications: { type: Boolean },
 | 
			
		||||
		notificationCount: { type: Boolean },
 | 
			
		||||
		theme: { type: String, reflect: true },
 | 
			
		||||
		notifications: { type: Array },
 | 
			
		||||
		currentNotification: { type: Object },
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	constructor() {
 | 
			
		||||
		super();
 | 
			
		||||
		this.notifications = [];
 | 
			
		||||
		this.showNotifications = false;
 | 
			
		||||
		this.notificationCount = false;
 | 
			
		||||
		this.initialFetch = false;
 | 
			
		||||
		this.theme = localStorage.getItem('qortalTheme')
 | 
			
		||||
			? localStorage.getItem('qortalTheme')
 | 
			
		||||
			: 'light';
 | 
			
		||||
		this.currentNotification = null;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	firstUpdated() {
 | 
			
		||||
		try {
 | 
			
		||||
			let value = JSON.parse(localStorage.getItem('isFirstTimeUser'));
 | 
			
		||||
			if (!value && value !== false) {
 | 
			
		||||
				value = true;
 | 
			
		||||
			}
 | 
			
		||||
			this.isFirstTimeUser = value;
 | 
			
		||||
		} catch (error) {}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	async stateChanged(state) {
 | 
			
		||||
		if (state.app.newNotification) {
 | 
			
		||||
			const newNotification = state.app.newNotification;
 | 
			
		||||
			this.notifications = [newNotification, ...this.notifications];
 | 
			
		||||
			store.dispatch(setNewNotification(null));
 | 
			
		||||
			if (this.isFirstTimeUser) {
 | 
			
		||||
				const target = this.shadowRoot.getElementById(
 | 
			
		||||
					'popover-notification'
 | 
			
		||||
				);
 | 
			
		||||
				const popover =
 | 
			
		||||
					this.shadowRoot.querySelector('popover-component');
 | 
			
		||||
				if (popover) {
 | 
			
		||||
					popover.openPopover(target);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				localStorage.setItem('isFirstTimeUser', JSON.stringify(false));
 | 
			
		||||
				this.isFirstTimeUser = false;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	handleBlur() {
 | 
			
		||||
		setTimeout(() => {
 | 
			
		||||
			if (!this.shadowRoot.contains(document.activeElement)) {
 | 
			
		||||
				this.showNotifications = false;
 | 
			
		||||
			}
 | 
			
		||||
		}, 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	changeStatus(signature, statusTx) {
 | 
			
		||||
		const copyNotifications = [...this.notifications];
 | 
			
		||||
		const findNotification = this.notifications.findIndex(
 | 
			
		||||
			(notification) => notification.reference.signature === signature
 | 
			
		||||
		);
 | 
			
		||||
		if (findNotification !== -1) {
 | 
			
		||||
			copyNotifications[findNotification] = {
 | 
			
		||||
				...copyNotifications[findNotification],
 | 
			
		||||
				status: statusTx,
 | 
			
		||||
			};
 | 
			
		||||
			this.notifications = copyNotifications;
 | 
			
		||||
			
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	render() {
 | 
			
		||||
		const hasOngoing = this.notifications.find(
 | 
			
		||||
			(notification) => notification.status !== 'confirmed'
 | 
			
		||||
		);
 | 
			
		||||
		return html`
 | 
			
		||||
			<div class="layout">
 | 
			
		||||
				<popover-component
 | 
			
		||||
					for="popover-notification"
 | 
			
		||||
					message="Your transaction is getting confirmed. To see its progress, click on the bell icon."
 | 
			
		||||
				></popover-component>
 | 
			
		||||
				<div
 | 
			
		||||
					id="popover-notification"
 | 
			
		||||
					@click=${() => this._toggleNotifications()}
 | 
			
		||||
				>
 | 
			
		||||
					${hasOngoing
 | 
			
		||||
						? html`
 | 
			
		||||
								<mwc-icon style="color: green;cursor:pointer"
 | 
			
		||||
									>notifications</mwc-icon
 | 
			
		||||
								>
 | 
			
		||||
						  `
 | 
			
		||||
						: html`
 | 
			
		||||
								<mwc-icon
 | 
			
		||||
									style="color: var(--black); cursor:pointer"
 | 
			
		||||
									>notifications</mwc-icon
 | 
			
		||||
								>
 | 
			
		||||
						  `}
 | 
			
		||||
				</div>
 | 
			
		||||
				${hasOngoing
 | 
			
		||||
					? html`
 | 
			
		||||
							<span
 | 
			
		||||
								class="count"
 | 
			
		||||
								style="cursor:pointer"
 | 
			
		||||
								@click=${() => this._toggleNotifications()}
 | 
			
		||||
							>
 | 
			
		||||
								<mwc-icon
 | 
			
		||||
									style="color: var(--black);font-size:18px"
 | 
			
		||||
									>pending</mwc-icon
 | 
			
		||||
								>
 | 
			
		||||
							</span>
 | 
			
		||||
					  `
 | 
			
		||||
					: ''}
 | 
			
		||||
 | 
			
		||||
				<div
 | 
			
		||||
					id="notification-panel"
 | 
			
		||||
					class="popover-panel"
 | 
			
		||||
					style="visibility:${this.showNotifications
 | 
			
		||||
						? 'visibile'
 | 
			
		||||
						: 'hidden'}"
 | 
			
		||||
					tabindex="0"
 | 
			
		||||
					@blur=${this.handleBlur}
 | 
			
		||||
				>
 | 
			
		||||
					<div class="notifications-list">
 | 
			
		||||
						${repeat(
 | 
			
		||||
							this.notifications,
 | 
			
		||||
							(notification) => notification.reference.signature, // key function
 | 
			
		||||
							(notification) => html`
 | 
			
		||||
								<notification-item-tx
 | 
			
		||||
									.changeStatus=${(val1, val2) =>
 | 
			
		||||
										this.changeStatus(val1, val2)}
 | 
			
		||||
									status=${notification.status}
 | 
			
		||||
									timestamp=${notification.timestamp}
 | 
			
		||||
									type=${notification.type}
 | 
			
		||||
									signature=${notification.reference
 | 
			
		||||
										.signature}
 | 
			
		||||
								></notification-item-tx>
 | 
			
		||||
							`
 | 
			
		||||
						)}
 | 
			
		||||
					</div>
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
		`;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_toggleNotifications() {
 | 
			
		||||
		if (this.notifications.length === 0) return;
 | 
			
		||||
		this.showNotifications = !this.showNotifications;
 | 
			
		||||
		if (this.showNotifications) {
 | 
			
		||||
			requestAnimationFrame(() => {
 | 
			
		||||
				this.shadowRoot.getElementById('notification-panel').focus();
 | 
			
		||||
			});
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static styles = css`
 | 
			
		||||
		.layout {
 | 
			
		||||
			display: flex;
 | 
			
		||||
			flex-direction: column;
 | 
			
		||||
			align-items: center;
 | 
			
		||||
			position: relative;
 | 
			
		||||
			margin-right: 20px;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.count {
 | 
			
		||||
			position: absolute;
 | 
			
		||||
			top: -5px;
 | 
			
		||||
			right: -5px;
 | 
			
		||||
			font-size: 12px;
 | 
			
		||||
			background-color: red;
 | 
			
		||||
			color: white;
 | 
			
		||||
			border-radius: 50%;
 | 
			
		||||
			width: 16px;
 | 
			
		||||
			height: 16px;
 | 
			
		||||
			display: flex;
 | 
			
		||||
			align-items: center;
 | 
			
		||||
			justify-content: center;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.nocount {
 | 
			
		||||
			display: none;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.popover-panel {
 | 
			
		||||
			position: absolute;
 | 
			
		||||
			width: 200px;
 | 
			
		||||
			padding: 10px;
 | 
			
		||||
			background-color: var(--white);
 | 
			
		||||
			border: 1px solid var(--black);
 | 
			
		||||
			border-radius: 4px;
 | 
			
		||||
			box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
 | 
			
		||||
			top: 40px;
 | 
			
		||||
			max-height: 350px;
 | 
			
		||||
			overflow: auto;
 | 
			
		||||
			scrollbar-width: thin;
 | 
			
		||||
			scrollbar-color: #6a6c75 #a1a1a1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.popover-panel::-webkit-scrollbar {
 | 
			
		||||
			width: 11px;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.popover-panel::-webkit-scrollbar-track {
 | 
			
		||||
			background: #a1a1a1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.popover-panel::-webkit-scrollbar-thumb {
 | 
			
		||||
			background-color: #6a6c75;
 | 
			
		||||
			border-radius: 6px;
 | 
			
		||||
			border: 3px solid #a1a1a1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.notifications-list {
 | 
			
		||||
			display: flex;
 | 
			
		||||
			flex-direction: column;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.notification-item {
 | 
			
		||||
			padding: 5px;
 | 
			
		||||
			border-bottom: 1px solid;
 | 
			
		||||
			display: flex;
 | 
			
		||||
			justify-content: space-between;
 | 
			
		||||
			cursor: pointer;
 | 
			
		||||
			transition: 0.2s all;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.notification-item:hover {
 | 
			
		||||
			background: var(--nav-color-hover);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		p {
 | 
			
		||||
			font-size: 14px;
 | 
			
		||||
			color: var(--black);
 | 
			
		||||
			margin: 0px;
 | 
			
		||||
			padding: 0px;
 | 
			
		||||
		}
 | 
			
		||||
	`;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
customElements.define('notification-bell-general', NotificationBellGeneral);
 | 
			
		||||
 | 
			
		||||
class NotificationItemTx extends connect(store)(LitElement) {
 | 
			
		||||
	static properties = {
 | 
			
		||||
		status: { type: String },
 | 
			
		||||
		type: { type: String },
 | 
			
		||||
		timestamp: { type: Number },
 | 
			
		||||
		signature: { type: String },
 | 
			
		||||
		changeStatus: { attribute: false },
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	constructor() {
 | 
			
		||||
		super();
 | 
			
		||||
		this.nodeUrl = this.getNodeUrl();
 | 
			
		||||
		this.myNode = this.getMyNode();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	async getStatus() {
 | 
			
		||||
		let interval = null;
 | 
			
		||||
		let stop = false;
 | 
			
		||||
		const getAnswer = async () => {
 | 
			
		||||
			const getTx = async (minterAddr) => {
 | 
			
		||||
				const url = `${this.nodeUrl}/transactions/signature/${this.signature}`;
 | 
			
		||||
				const res = await fetch(url);
 | 
			
		||||
				const data = await res.json();
 | 
			
		||||
				return data;
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			if (!stop) {
 | 
			
		||||
				stop = true;
 | 
			
		||||
				try {
 | 
			
		||||
					const txTransaction = await getTx();
 | 
			
		||||
					if (!txTransaction.error && txTransaction.signature && txTransaction.blockHeight) {
 | 
			
		||||
						clearInterval(interval);
 | 
			
		||||
						this.changeStatus(this.signature, 'confirmed');
 | 
			
		||||
					}
 | 
			
		||||
				} catch (error) {}
 | 
			
		||||
				stop = false;
 | 
			
		||||
			}
 | 
			
		||||
		};
 | 
			
		||||
		interval = setInterval(getAnswer, 20000);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	firstUpdated() {
 | 
			
		||||
		this.getStatus();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	render() {
 | 
			
		||||
		return html`
 | 
			
		||||
			<div class="notification-item" @click=${() => {}}>
 | 
			
		||||
				<div>
 | 
			
		||||
					<p style="margin-bottom:10px; font-weight:bold">
 | 
			
		||||
						${translate('transpage.tchange1')}
 | 
			
		||||
					</p>
 | 
			
		||||
				</div>
 | 
			
		||||
				<div>
 | 
			
		||||
					<p style="margin-bottom:5px">
 | 
			
		||||
						${translate('walletpage.wchange35')}: ${this.type}
 | 
			
		||||
					</p>
 | 
			
		||||
					<p style="margin-bottom:5px">
 | 
			
		||||
						${translate('tubespage.schange28')}:
 | 
			
		||||
						${this.status === 'confirming'
 | 
			
		||||
							? translate('notifications.notify1')
 | 
			
		||||
							: translate('notifications.notify2')}
 | 
			
		||||
					</p>
 | 
			
		||||
					${this.status !== 'confirmed'
 | 
			
		||||
						? html`
 | 
			
		||||
								<div class="centered">
 | 
			
		||||
									<div class="loader">Loading...</div>
 | 
			
		||||
								</div>
 | 
			
		||||
						  `
 | 
			
		||||
						: ''}
 | 
			
		||||
					<div
 | 
			
		||||
						style="display:flex;justify-content:space-between;align-items:center"
 | 
			
		||||
					>
 | 
			
		||||
						<message-time
 | 
			
		||||
							timestamp=${this.timestamp}
 | 
			
		||||
							style="color:red;font-size:12px"
 | 
			
		||||
						></message-time>
 | 
			
		||||
						${this.status === 'confirmed'
 | 
			
		||||
							? html`
 | 
			
		||||
									<mwc-icon style="color: green;"
 | 
			
		||||
										>done</mwc-icon
 | 
			
		||||
									>
 | 
			
		||||
							  `
 | 
			
		||||
							: ''}
 | 
			
		||||
					</div>
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
		`;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_toggleNotifications() {
 | 
			
		||||
		if (this.notifications.length === 0) return;
 | 
			
		||||
		this.showNotifications = !this.showNotifications;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static styles = css`
 | 
			
		||||
		.centered {
 | 
			
		||||
			display: flex;
 | 
			
		||||
			justify-content: center;
 | 
			
		||||
			align-items: center;
 | 
			
		||||
		}
 | 
			
		||||
		.layout {
 | 
			
		||||
			width: 100px;
 | 
			
		||||
			display: flex;
 | 
			
		||||
			flex-direction: column;
 | 
			
		||||
			align-items: center;
 | 
			
		||||
			position: relative;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.count {
 | 
			
		||||
			position: absolute;
 | 
			
		||||
			top: -5px;
 | 
			
		||||
			right: -5px;
 | 
			
		||||
			font-size: 12px;
 | 
			
		||||
			background-color: red;
 | 
			
		||||
			color: white;
 | 
			
		||||
			border-radius: 50%;
 | 
			
		||||
			width: 16px;
 | 
			
		||||
			height: 16px;
 | 
			
		||||
			display: flex;
 | 
			
		||||
			align-items: center;
 | 
			
		||||
			justify-content: center;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.nocount {
 | 
			
		||||
			display: none;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.popover-panel {
 | 
			
		||||
			position: absolute;
 | 
			
		||||
			width: 200px;
 | 
			
		||||
			padding: 10px;
 | 
			
		||||
			background-color: var(--white);
 | 
			
		||||
			border: 1px solid var(--black);
 | 
			
		||||
			border-radius: 4px;
 | 
			
		||||
			box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
 | 
			
		||||
			top: 40px;
 | 
			
		||||
			max-height: 350px;
 | 
			
		||||
			overflow: auto;
 | 
			
		||||
			scrollbar-width: thin;
 | 
			
		||||
			scrollbar-color: #6a6c75 #a1a1a1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.popover-panel::-webkit-scrollbar {
 | 
			
		||||
			width: 11px;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.popover-panel::-webkit-scrollbar-track {
 | 
			
		||||
			background: #a1a1a1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.popover-panel::-webkit-scrollbar-thumb {
 | 
			
		||||
			background-color: #6a6c75;
 | 
			
		||||
			border-radius: 6px;
 | 
			
		||||
			border: 3px solid #a1a1a1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.notifications-list {
 | 
			
		||||
			display: flex;
 | 
			
		||||
			flex-direction: column;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.notification-item {
 | 
			
		||||
			padding: 5px;
 | 
			
		||||
			border-bottom: 1px solid;
 | 
			
		||||
			display: flex;
 | 
			
		||||
			flex-direction: column;
 | 
			
		||||
			cursor: default;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.notification-item:hover {
 | 
			
		||||
			background: var(--nav-color-hover);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		p {
 | 
			
		||||
			font-size: 14px;
 | 
			
		||||
			color: var(--black);
 | 
			
		||||
			margin: 0px;
 | 
			
		||||
			padding: 0px;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.loader,
 | 
			
		||||
		.loader:before,
 | 
			
		||||
		.loader:after {
 | 
			
		||||
			border-radius: 50%;
 | 
			
		||||
			width: 10px;
 | 
			
		||||
			height: 10px;
 | 
			
		||||
			-webkit-animation-fill-mode: both;
 | 
			
		||||
			animation-fill-mode: both;
 | 
			
		||||
			-webkit-animation: load7 1.8s infinite ease-in-out;
 | 
			
		||||
			animation: load7 1.8s infinite ease-in-out;
 | 
			
		||||
		}
 | 
			
		||||
		.loader {
 | 
			
		||||
			color: var(--black);
 | 
			
		||||
			font-size: 5px;
 | 
			
		||||
			margin-bottom: 20px;
 | 
			
		||||
			position: relative;
 | 
			
		||||
			text-indent: -9999em;
 | 
			
		||||
			-webkit-transform: translateZ(0);
 | 
			
		||||
			-ms-transform: translateZ(0);
 | 
			
		||||
			transform: translateZ(0);
 | 
			
		||||
			-webkit-animation-delay: -0.16s;
 | 
			
		||||
			animation-delay: -0.16s;
 | 
			
		||||
		}
 | 
			
		||||
		.loader:before,
 | 
			
		||||
		.loader:after {
 | 
			
		||||
			content: '';
 | 
			
		||||
			position: absolute;
 | 
			
		||||
			top: 0;
 | 
			
		||||
		}
 | 
			
		||||
		.loader:before {
 | 
			
		||||
			left: -3.5em;
 | 
			
		||||
			-webkit-animation-delay: -0.32s;
 | 
			
		||||
			animation-delay: -0.32s;
 | 
			
		||||
		}
 | 
			
		||||
		.loader:after {
 | 
			
		||||
			left: 3.5em;
 | 
			
		||||
		}
 | 
			
		||||
		@-webkit-keyframes load7 {
 | 
			
		||||
			0%,
 | 
			
		||||
			80%,
 | 
			
		||||
			100% {
 | 
			
		||||
				box-shadow: 0 2.5em 0 -1.3em;
 | 
			
		||||
			}
 | 
			
		||||
			40% {
 | 
			
		||||
				box-shadow: 0 2.5em 0 0;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		@keyframes load7 {
 | 
			
		||||
			0%,
 | 
			
		||||
			80%,
 | 
			
		||||
			100% {
 | 
			
		||||
				box-shadow: 0 2.5em 0 -1.3em;
 | 
			
		||||
			}
 | 
			
		||||
			40% {
 | 
			
		||||
				box-shadow: 0 2.5em 0 0;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	`;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
customElements.define('notification-item-tx', NotificationItemTx);
 | 
			
		||||
@@ -210,7 +210,6 @@ class NotificationBell extends connect(store)(LitElement) {
 | 
			
		||||
 | 
			
		||||
    static styles = css`
 | 
			
		||||
        .layout {
 | 
			
		||||
          width: 100px;
 | 
			
		||||
          display: flex;
 | 
			
		||||
          flex-direction: column;
 | 
			
		||||
          align-items: center;
 | 
			
		||||
@@ -220,7 +219,7 @@ class NotificationBell extends connect(store)(LitElement) {
 | 
			
		||||
        .count {
 | 
			
		||||
          position: absolute;
 | 
			
		||||
          top: 2px;
 | 
			
		||||
          right: 32px;
 | 
			
		||||
          right: 0px;
 | 
			
		||||
          font-size: 12px;
 | 
			
		||||
          background-color: red;
 | 
			
		||||
          color: white;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										74
									
								
								core/src/components/notification-view/popover.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								core/src/components/notification-view/popover.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
// popover-component.js
 | 
			
		||||
import { LitElement, html, css } from 'lit';
 | 
			
		||||
import { createPopper } from '@popperjs/core';
 | 
			
		||||
import '@material/mwc-icon'
 | 
			
		||||
 | 
			
		||||
export class PopoverComponent extends 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)
 | 
			
		||||
        }
 | 
			
		||||
    `;
 | 
			
		||||
 | 
			
		||||
    static properties = {
 | 
			
		||||
        for: { type: String, reflect: true },
 | 
			
		||||
        message: { type: String }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super();
 | 
			
		||||
        this.message = '';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    closePopover() {
 | 
			
		||||
        this.style.display = 'none';
 | 
			
		||||
        if (this.popperInstance) {
 | 
			
		||||
            this.popperInstance.destroy();
 | 
			
		||||
            this.popperInstance = null;
 | 
			
		||||
        }
 | 
			
		||||
        this.requestUpdate();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    render() {
 | 
			
		||||
        return html`
 | 
			
		||||
            <span class="close-icon" @click="${this.closePopover}"><mwc-icon style="color: var(--black)">close</mwc-icon></span>
 | 
			
		||||
            <div><mwc-icon style="color: var(--black)">info</mwc-icon> ${this.message}</div>
 | 
			
		||||
        `;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
customElements.define('popover-component', PopoverComponent);
 | 
			
		||||
@@ -759,6 +759,7 @@ class ShowPlugin extends connect(store)(LitElement) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    changePage(page) {
 | 
			
		||||
        console.log({page})
 | 
			
		||||
        const copiedTabs = [...this.tabs]
 | 
			
		||||
        copiedTabs[this.currentTab] = {
 | 
			
		||||
            ...copiedTabs[this.currentTab],
 | 
			
		||||
@@ -819,7 +820,15 @@ class ShowPlugin extends connect(store)(LitElement) {
 | 
			
		||||
 | 
			
		||||
        if (state.app.newTab) {
 | 
			
		||||
            const newTab = state.app.newTab
 | 
			
		||||
            if (!this.tabs.find((tab) => tab.id === newTab.id)) {
 | 
			
		||||
            console.log('this.tabs', this.tabs)
 | 
			
		||||
            if(newTab.openExisting && this.tabs.find((tab)=> tab.url === newTab.url)){
 | 
			
		||||
                const findIndex = this.tabs.findIndex((tab) => tab.url === newTab.url)
 | 
			
		||||
                if (findIndex !== -1) {
 | 
			
		||||
                    this.currentTab = findIndex
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                store.dispatch(setNewTab(null))
 | 
			
		||||
            } else if (!this.tabs.find((tab) => tab.id === newTab.id)) {
 | 
			
		||||
                this.addTab(newTab)
 | 
			
		||||
                this.currentTab = this.tabs.length - 1
 | 
			
		||||
                store.dispatch(setNewTab(null))
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
// Core App Actions here...
 | 
			
		||||
import { UPDATE_BLOCK_INFO, UPDATE_NODE_STATUS, UPDATE_NODE_INFO, CHAT_HEADS, ACCOUNT_INFO, ADD_AUTO_LOAD_IMAGES_CHAT, REMOVE_AUTO_LOAD_IMAGES_CHAT, ALLOW_QAPP_AUTO_AUTH, REMOVE_QAPP_AUTO_AUTH, SET_CHAT_LAST_SEEN, ADD_CHAT_LAST_SEEN, ALLOW_QAPP_AUTO_LISTS, REMOVE_QAPP_AUTO_LISTS, SET_NEW_TAB, ADD_TAB_INFO, SET_TAB_NOTIFICATIONS, IS_OPEN_DEV_DIALOG } from '../app-action-types.js'
 | 
			
		||||
import { UPDATE_BLOCK_INFO, UPDATE_NODE_STATUS, UPDATE_NODE_INFO, CHAT_HEADS, ACCOUNT_INFO, ADD_AUTO_LOAD_IMAGES_CHAT, REMOVE_AUTO_LOAD_IMAGES_CHAT, ALLOW_QAPP_AUTO_AUTH, REMOVE_QAPP_AUTO_AUTH, SET_CHAT_LAST_SEEN, ADD_CHAT_LAST_SEEN, ALLOW_QAPP_AUTO_LISTS, REMOVE_QAPP_AUTO_LISTS, SET_NEW_TAB, ADD_TAB_INFO, SET_TAB_NOTIFICATIONS, IS_OPEN_DEV_DIALOG, SET_NEW_NOTIFICATION } from '../app-action-types.js'
 | 
			
		||||
 | 
			
		||||
export const doUpdateBlockInfo = (blockObj) => {
 | 
			
		||||
    return (dispatch, getState) => {
 | 
			
		||||
@@ -126,6 +126,12 @@ export const setNewTab = (payload) => {
 | 
			
		||||
        payload
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
export const setNewNotification = (payload) => {
 | 
			
		||||
    return {
 | 
			
		||||
        type: SET_NEW_NOTIFICATION,
 | 
			
		||||
        payload
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
export const setIsOpenDevDialog = (payload)=> {
 | 
			
		||||
    return {
 | 
			
		||||
        type: IS_OPEN_DEV_DIALOG,
 | 
			
		||||
 
 | 
			
		||||
@@ -31,3 +31,4 @@ export const SET_NEW_TAB = 'SET_NEW_TAB'
 | 
			
		||||
export const ADD_TAB_INFO = 'ADD_TAB_INFO'
 | 
			
		||||
export const SET_TAB_NOTIFICATIONS = 'SET_TAB_NOTIFICATIONS'
 | 
			
		||||
export const IS_OPEN_DEV_DIALOG = 'IS_OPEN_DEV_DIALOG'
 | 
			
		||||
export const SET_NEW_NOTIFICATION = 'SET_NEW_NOTIFICATION'
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
// Loading state, login state, isNavDrawOpen state etc. None of this needs to be saved to localstorage.
 | 
			
		||||
import { loadStateFromLocalStorage, saveStateToLocalStorage } from '../../localStorageHelpers.js'
 | 
			
		||||
import { LOG_IN, LOG_OUT, NETWORK_CONNECTION_STATUS, INIT_WORKERS, ADD_PLUGIN_URL, ADD_PLUGIN, ADD_NEW_PLUGIN_URL, NAVIGATE, SELECT_ADDRESS, ACCOUNT_INFO, CHAT_HEADS, UPDATE_BLOCK_INFO, UPDATE_NODE_STATUS, UPDATE_NODE_INFO, LOAD_NODE_CONFIG, SET_NODE, ADD_NODE, PAGE_URL, ADD_AUTO_LOAD_IMAGES_CHAT, REMOVE_AUTO_LOAD_IMAGES_CHAT, ALLOW_QAPP_AUTO_AUTH, REMOVE_QAPP_AUTO_AUTH, SET_CHAT_LAST_SEEN, ADD_CHAT_LAST_SEEN, ALLOW_QAPP_AUTO_LISTS, REMOVE_QAPP_AUTO_LISTS, SET_NEW_TAB, ADD_TAB_INFO, SET_TAB_NOTIFICATIONS, IS_OPEN_DEV_DIALOG, REMOVE_NODE, EDIT_NODE } from './app-action-types.js'
 | 
			
		||||
import { LOG_IN, LOG_OUT, NETWORK_CONNECTION_STATUS, INIT_WORKERS, ADD_PLUGIN_URL, ADD_PLUGIN, ADD_NEW_PLUGIN_URL, NAVIGATE, SELECT_ADDRESS, ACCOUNT_INFO, CHAT_HEADS, UPDATE_BLOCK_INFO, UPDATE_NODE_STATUS, UPDATE_NODE_INFO, LOAD_NODE_CONFIG, SET_NODE, ADD_NODE, PAGE_URL, ADD_AUTO_LOAD_IMAGES_CHAT, REMOVE_AUTO_LOAD_IMAGES_CHAT, ALLOW_QAPP_AUTO_AUTH, REMOVE_QAPP_AUTO_AUTH, SET_CHAT_LAST_SEEN, ADD_CHAT_LAST_SEEN, ALLOW_QAPP_AUTO_LISTS, REMOVE_QAPP_AUTO_LISTS, SET_NEW_TAB, ADD_TAB_INFO, SET_TAB_NOTIFICATIONS, IS_OPEN_DEV_DIALOG, REMOVE_NODE, EDIT_NODE, SET_NEW_NOTIFICATION } from './app-action-types.js'
 | 
			
		||||
import { initWorkersReducer } from './reducers/init-workers.js'
 | 
			
		||||
import { loginReducer } from './reducers/login-reducer.js'
 | 
			
		||||
import { setNode, addNode, removeNode, editNode } from './reducers/manage-node.js'
 | 
			
		||||
@@ -50,7 +50,8 @@ const INITIAL_STATE = {
 | 
			
		||||
    chatLastSeen: [],
 | 
			
		||||
    newTab: null,
 | 
			
		||||
    tabInfo: {},
 | 
			
		||||
    isOpenDevDialog: false
 | 
			
		||||
    isOpenDevDialog: false,
 | 
			
		||||
    newNotification: null
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default (state = INITIAL_STATE, action) => {
 | 
			
		||||
@@ -277,6 +278,13 @@ export default (state = INITIAL_STATE, action) => {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        case SET_NEW_NOTIFICATION: {
 | 
			
		||||
            return {
 | 
			
		||||
                ...state,
 | 
			
		||||
                newNotification: action.payload
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        default:
 | 
			
		||||
            return state
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -12,6 +12,7 @@
 | 
			
		||||
				"@hapi/hapi": "21.3.2",
 | 
			
		||||
				"@hapi/inert": "7.1.0",
 | 
			
		||||
				"@lit-labs/motion": "1.0.4",
 | 
			
		||||
				"@popperjs/core": "^2.11.8",
 | 
			
		||||
				"@tiptap/core": "2.0.4",
 | 
			
		||||
				"@tiptap/extension-highlight": "2.0.4",
 | 
			
		||||
				"@tiptap/extension-image": "2.0.4",
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,7 @@
 | 
			
		||||
		"@hapi/hapi": "21.3.2",
 | 
			
		||||
		"@hapi/inert": "7.1.0",
 | 
			
		||||
		"@lit-labs/motion": "1.0.4",
 | 
			
		||||
		"@popperjs/core": "^2.11.8",
 | 
			
		||||
		"@tiptap/core": "2.0.4",
 | 
			
		||||
		"@tiptap/extension-highlight": "2.0.4",
 | 
			
		||||
		"@tiptap/extension-image": "2.0.4",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										348
									
								
								plugins/plugins/core/components/ChatGroupManager.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										348
									
								
								plugins/plugins/core/components/ChatGroupManager.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,348 @@
 | 
			
		||||
import { LitElement, html, css } from 'lit';
 | 
			
		||||
import { Epml } from '../../../epml';
 | 
			
		||||
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/button';
 | 
			
		||||
import './WrapperModal';
 | 
			
		||||
import './TipUser';
 | 
			
		||||
import './UserInfo/UserInfo';
 | 
			
		||||
import './ChatImage';
 | 
			
		||||
import './ReusableImage';
 | 
			
		||||
import {
 | 
			
		||||
	get
 | 
			
		||||
} from 'lit-translate';
 | 
			
		||||
 | 
			
		||||
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent });
 | 
			
		||||
 | 
			
		||||
class ChatGroupsManager extends LitElement {
 | 
			
		||||
	static get properties() {
 | 
			
		||||
		return {
 | 
			
		||||
			leaveGroupObj: { type: Object },
 | 
			
		||||
			error: { type: Boolean },
 | 
			
		||||
			chatHeads: { type: Array },
 | 
			
		||||
			groupAdmin: { attribute: false },
 | 
			
		||||
			groupMembers: { attribute: false },
 | 
			
		||||
			selectedHead: { type: Object },
 | 
			
		||||
			toggle: { attribute: false },
 | 
			
		||||
			getMoreMembers: { attribute: false },
 | 
			
		||||
			setOpenPrivateMessage: { attribute: false },
 | 
			
		||||
			userName: { type: String },
 | 
			
		||||
			walletBalance: { type: Number },
 | 
			
		||||
			sendMoneyLoading: { type: Boolean },
 | 
			
		||||
			btnDisable: { type: Boolean },
 | 
			
		||||
			errorMessage: { type: String },
 | 
			
		||||
			successMessage: { type: String },
 | 
			
		||||
			setOpenTipUser: { attribute: false },
 | 
			
		||||
			setOpenUserInfo: { attribute: false },
 | 
			
		||||
			setUserName: { attribute: false },
 | 
			
		||||
			chatId: { type: String },
 | 
			
		||||
			_chatId: { type: String },
 | 
			
		||||
			isReceipient: { type: Boolean },
 | 
			
		||||
			groups: { type: Array },
 | 
			
		||||
			viewImage: { type: Boolean },
 | 
			
		||||
            autoView: {type: Boolean},
 | 
			
		||||
            onlyMyImages: {type: Boolean},
 | 
			
		||||
			repost: {attribute: false}
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	constructor() {
 | 
			
		||||
		super();
 | 
			
		||||
		this.leaveGroupObj = {};
 | 
			
		||||
		this.leaveFee = 0.001;
 | 
			
		||||
		this.error = false;
 | 
			
		||||
		this.chatHeads = [];
 | 
			
		||||
		this.groupAdmin = [];
 | 
			
		||||
		this.groupMembers = [];
 | 
			
		||||
		this.observerHandler = this.observerHandler.bind(this);
 | 
			
		||||
		this.getGroups = this.getGroups.bind(this);
 | 
			
		||||
		this.viewElement = '';
 | 
			
		||||
		this.downObserverElement = '';
 | 
			
		||||
 | 
			
		||||
		this.sendMoneyLoading = false;
 | 
			
		||||
		this.btnDisable = false;
 | 
			
		||||
		this.errorMessage = '';
 | 
			
		||||
		this.successMessage = '';
 | 
			
		||||
 | 
			
		||||
		this.groups = [];
 | 
			
		||||
		this.viewImage = false;
 | 
			
		||||
		this.myName =
 | 
			
		||||
			window.parent.reduxStore.getState().app.accountInfo.names[0].name;
 | 
			
		||||
		this.myAddress =
 | 
			
		||||
			window.parent.reduxStore.getState().app.selectedAddress.address;
 | 
			
		||||
        this.autoView =false
 | 
			
		||||
        this.onlyMyImages = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static get styles() {
 | 
			
		||||
		return 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;
 | 
			
		||||
                align-items: center;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			.container-body {
 | 
			
		||||
				width: 100%;
 | 
			
		||||
				display: flex;
 | 
			
		||||
				flex-direction: column;
 | 
			
		||||
				flex-grow: 1;
 | 
			
		||||
				overflow: auto;
 | 
			
		||||
				margin-top: 5px;
 | 
			
		||||
				padding: 0px 6px;
 | 
			
		||||
				box-sizing: border-box;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			.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);
 | 
			
		||||
			}
 | 
			
		||||
			.message-myBg {
 | 
			
		||||
				background-color: var(--chat-bubble-myBg) !important;
 | 
			
		||||
				margin-bottom: 15px;
 | 
			
		||||
				border-radius: 5px;
 | 
			
		||||
				padding: 5px;
 | 
			
		||||
			}
 | 
			
		||||
			.message-data-name {
 | 
			
		||||
				user-select: none;
 | 
			
		||||
				color: #03a9f4;
 | 
			
		||||
				margin-bottom: 5px;
 | 
			
		||||
			}
 | 
			
		||||
			.message-user-info {
 | 
			
		||||
				display: flex;
 | 
			
		||||
				justify-content: space-between;
 | 
			
		||||
				width: 100%;
 | 
			
		||||
				gap: 10px;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			.hideImg {
 | 
			
		||||
				visibility: hidden;
 | 
			
		||||
			}
 | 
			
		||||
            .checkbox-row {
 | 
			
		||||
                position: relative;
 | 
			
		||||
		    display: flex;
 | 
			
		||||
		    align-items: center;
 | 
			
		||||
		    align-content: center;
 | 
			
		||||
		    font-family: Montserrat, sans-serif;
 | 
			
		||||
		    font-weight: 600;
 | 
			
		||||
		    color: var(--black);
 | 
			
		||||
			padding-left: 5px;
 | 
			
		||||
	      }
 | 
			
		||||
		`;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	async getGroups() {
 | 
			
		||||
		try {
 | 
			
		||||
           
 | 
			
		||||
            let endpoint = `/groups`
 | 
			
		||||
           
 | 
			
		||||
           
 | 
			
		||||
			const groups = await parentEpml.request('apiCall', {
 | 
			
		||||
				type: 'api',
 | 
			
		||||
				url: endpoint,
 | 
			
		||||
			});
 | 
			
		||||
 | 
			
		||||
            let list = groups
 | 
			
		||||
 | 
			
		||||
			this.groups = list
 | 
			
		||||
		} catch (error) {
 | 
			
		||||
			console.log(error);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	firstUpdated() {
 | 
			
		||||
		// this.viewElement = this.shadowRoot.getElementById('viewElement');
 | 
			
		||||
		// this.downObserverElement =
 | 
			
		||||
		// 	this.shadowRoot.getElementById('downObserver');
 | 
			
		||||
		// this.elementObserver();
 | 
			
		||||
		this.getGroups()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
	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.images.length < 20) {
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
			this.getMoreImages();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    selectAuto(e) {
 | 
			
		||||
        if (e.target.checked) {
 | 
			
		||||
          this.autoView = false
 | 
			
		||||
        } else {
 | 
			
		||||
            this.autoView = true
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    selectMyImages(e) {
 | 
			
		||||
        if (e.target.checked) {
 | 
			
		||||
          this.onlyMyImages = false
 | 
			
		||||
        } else {
 | 
			
		||||
            this.onlyMyImages = true
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	render() {
 | 
			
		||||
		console.log('this.groups', this.groups)
 | 
			
		||||
		return html`
 | 
			
		||||
     
 | 
			
		||||
        <div class="container">
 | 
			
		||||
            <div class="close-row" style="margin-top: 15px">
 | 
			
		||||
            <mwc-icon @click=${()=> {
 | 
			
		||||
                this.getGroups()
 | 
			
		||||
            }} style="color: var(--black); cursor:pointer;">refresh</mwc-icon>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="checkbox-row">
 | 
			
		||||
                            <label for="authButton" id="authButtonLabel" style="color: var(--black);">
 | 
			
		||||
                                ${get('chatpage.cchange69')}
 | 
			
		||||
                            </label>
 | 
			
		||||
                            <mwc-checkbox style="margin-right: -15px;" id="authButton" @click=${(e) => this.selectAuto(e)} ?checked=${this.autoView}></mwc-checkbox>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="checkbox-row">
 | 
			
		||||
                            <label for="authButton" id="authButtonLabel" style="color: var(--black);">
 | 
			
		||||
                                ${get('chatpage.cchange95')}
 | 
			
		||||
                            </label>
 | 
			
		||||
                            <mwc-checkbox style="margin-right: -15px;" id="authButton" @click=${(e) => this.selectMyImages(e)} ?checked=${this.onlyMyImages}></mwc-checkbox>
 | 
			
		||||
                    </div>
 | 
			
		||||
            <div id="viewElement" class="container-body">
 | 
			
		||||
              
 | 
			
		||||
             
 | 
			
		||||
                <div id='downObserver'></div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    `;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
customElements.define('chat-groups-manager', ChatGroupsManager);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										98
									
								
								plugins/plugins/core/components/ChatGroupsModal.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								plugins/plugins/core/components/ChatGroupsModal.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,98 @@
 | 
			
		||||
import { LitElement, html, css } from 'lit';
 | 
			
		||||
import {
 | 
			
		||||
	translate,
 | 
			
		||||
} from 'lit-translate';
 | 
			
		||||
import '@material/mwc-menu';
 | 
			
		||||
import '@material/mwc-list/mwc-list-item.js';
 | 
			
		||||
import '@material/mwc-dialog'
 | 
			
		||||
import './ChatGroupManager'
 | 
			
		||||
 | 
			
		||||
export class ChatGroupsModal extends LitElement {
 | 
			
		||||
	static get properties() {
 | 
			
		||||
		return {
 | 
			
		||||
	  openDialogGroupsModal: { type: Boolean },
 | 
			
		||||
	  setOpenDialogGroupsModal: { attribute: false}
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static get styles() {
 | 
			
		||||
		return css`
 | 
			
		||||
			* {
 | 
			
		||||
				--mdc-theme-text-primary-on-background: var(--black);
 | 
			
		||||
				--mdc-dialog-max-width: 85vw;
 | 
			
		||||
				--mdc-dialog-max-height: 95vh;
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			.imageContainer {
 | 
			
		||||
		display: flex;
 | 
			
		||||
		justify-content: center;
 | 
			
		||||
		align-items: center;
 | 
			
		||||
		height: 100%;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
			@-webkit-keyframes loadingAnimation {
 | 
			
		||||
				0% {
 | 
			
		||||
					-webkit-transform: rotate(0deg);
 | 
			
		||||
					transform: rotate(0deg);
 | 
			
		||||
				}
 | 
			
		||||
				100% {
 | 
			
		||||
					-webkit-transform: rotate(360deg);
 | 
			
		||||
					transform: rotate(360deg);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			@keyframes loadingAnimation {
 | 
			
		||||
				0% {
 | 
			
		||||
					-webkit-transform: rotate(0deg);
 | 
			
		||||
					transform: rotate(0deg);
 | 
			
		||||
				}
 | 
			
		||||
				100% {
 | 
			
		||||
					-webkit-transform: rotate(360deg);
 | 
			
		||||
					transform: rotate(360deg);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		`;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	constructor() {
 | 
			
		||||
		super();
 | 
			
		||||
	this.openDialogGroupsModal = false
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	firstUpdated() {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	render() {
 | 
			
		||||
		console.log('hello')
 | 
			
		||||
		return html`
 | 
			
		||||
		
 | 
			
		||||
			<mwc-dialog 
 | 
			
		||||
                id="showDialogGroupsModal" 
 | 
			
		||||
                ?open=${this.openDialogGroupsModal} 
 | 
			
		||||
                @closed=${() => {
 | 
			
		||||
					this.setOpenDialogGroupsModal(false)
 | 
			
		||||
				}}>
 | 
			
		||||
					<div class="dialog-header"></div>
 | 
			
		||||
					<div class="dialog-container ">
 | 
			
		||||
						<chat-groups-manager></chat-groups-manager>
 | 
			
		||||
			</div>
 | 
			
		||||
					<mwc-button
 | 
			
		||||
						slot="primaryAction"
 | 
			
		||||
						dialogAction="cancel"
 | 
			
		||||
						class="red"
 | 
			
		||||
						@click=${() => {
 | 
			
		||||
							this.setOpenDialogGroupsModal(false)
 | 
			
		||||
						}}
 | 
			
		||||
					>
 | 
			
		||||
					    ${translate('general.close')}
 | 
			
		||||
					</mwc-button>
 | 
			
		||||
				</mwc-dialog>
 | 
			
		||||
		`;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
customElements.define('chat-groups-modal', ChatGroupsModal);
 | 
			
		||||
@@ -1095,6 +1095,7 @@ class ChatPage extends LitElement {
 | 
			
		||||
            const blobFound = handleTransferIntoURL(event.clipboardData)
 | 
			
		||||
            if (blobFound) {
 | 
			
		||||
                this.insertFile(blobFound)
 | 
			
		||||
                e.preventDefault();
 | 
			
		||||
                return
 | 
			
		||||
            } else {
 | 
			
		||||
                const item_list = await navigator.clipboard.read()
 | 
			
		||||
@@ -1114,6 +1115,7 @@ class ChatPage extends LitElement {
 | 
			
		||||
                            type: image_type
 | 
			
		||||
                        })
 | 
			
		||||
                        this.insertFile(file)
 | 
			
		||||
                        e.preventDefault();
 | 
			
		||||
                    } catch (error) {
 | 
			
		||||
                        console.error(error)
 | 
			
		||||
                        let errorMsg = get("chatpage.cchange81")
 | 
			
		||||
 
 | 
			
		||||
@@ -2849,6 +2849,17 @@ class GroupManagement extends LitElement {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setTxNotification(tx){
 | 
			
		||||
        window.parent.reduxStore.dispatch(
 | 
			
		||||
            window.parent.reduxAction.setNewNotification({
 | 
			
		||||
                type: 'JOIN_GROUP',
 | 
			
		||||
                status: 'confirming',
 | 
			
		||||
                reference: tx,
 | 
			
		||||
                timestamp: Date.now()
 | 
			
		||||
            })
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async _joinGroup(groupId, groupName) {
 | 
			
		||||
        this.resetDefaultSettings()
 | 
			
		||||
        const joinFeeInput = this.joinFee
 | 
			
		||||
@@ -2885,7 +2896,8 @@ class GroupManagement extends LitElement {
 | 
			
		||||
                    lastReference: lastRef,
 | 
			
		||||
                    groupdialog1: groupdialog1,
 | 
			
		||||
                    groupdialog2: groupdialog2
 | 
			
		||||
                }
 | 
			
		||||
                },
 | 
			
		||||
                apiVersion: 2
 | 
			
		||||
            })
 | 
			
		||||
            return myTxnrequest
 | 
			
		||||
        }
 | 
			
		||||
@@ -2897,6 +2909,12 @@ class GroupManagement extends LitElement {
 | 
			
		||||
                throw new Error(txnResponse)
 | 
			
		||||
            } else if (txnResponse.success === true && !txnResponse.data.error) {
 | 
			
		||||
                this.message = this.renderErr8Text()
 | 
			
		||||
                this.setTxNotification({
 | 
			
		||||
                    groupName,
 | 
			
		||||
                    groupId,
 | 
			
		||||
                    timestamp: Date.now(),
 | 
			
		||||
                    ...(txnResponse.data || {})
 | 
			
		||||
                })
 | 
			
		||||
                this.error = false
 | 
			
		||||
            } else {
 | 
			
		||||
                this.error = true
 | 
			
		||||
 
 | 
			
		||||
@@ -160,6 +160,7 @@ export const qchatStyles = css`
 | 
			
		||||
      display: flex;
 | 
			
		||||
      align-items: center;
 | 
			
		||||
      gap: 10px;
 | 
			
		||||
      justify-content: space-between;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .center {
 | 
			
		||||
 
 | 
			
		||||
@@ -12,19 +12,22 @@ import Underline from '@tiptap/extension-underline';
 | 
			
		||||
import Placeholder from '@tiptap/extension-placeholder'
 | 
			
		||||
import Highlight from '@tiptap/extension-highlight'
 | 
			
		||||
import snackbar from '../../components/snackbar.js'
 | 
			
		||||
import ShortUniqueId from 'short-unique-id';
 | 
			
		||||
 | 
			
		||||
import '../../components/ChatWelcomePage.js'
 | 
			
		||||
import '../../components/ChatHead.js'
 | 
			
		||||
import '../../components/ChatPage.js'
 | 
			
		||||
import '../../components/WrapperModal.js'
 | 
			
		||||
import '../../components/ChatSearchResults.js'
 | 
			
		||||
 | 
			
		||||
import '../../components/ChatGroupsModal.js'
 | 
			
		||||
import '@material/mwc-button'
 | 
			
		||||
import '@material/mwc-dialog'
 | 
			
		||||
import '@material/mwc-icon'
 | 
			
		||||
import '@material/mwc-snackbar'
 | 
			
		||||
import '@polymer/paper-spinner/paper-spinner-lite.js'
 | 
			
		||||
import '@vaadin/grid'
 | 
			
		||||
import '@vaadin/tooltip';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
passiveSupport({ events: ['touchstart'] })
 | 
			
		||||
 | 
			
		||||
@@ -55,6 +58,7 @@ class Chat extends LitElement {
 | 
			
		||||
            groupInvites: { type: Array },
 | 
			
		||||
            loggedInUserName: {type: String},
 | 
			
		||||
            loggedInUserAddress: {type: String},
 | 
			
		||||
            openDialogGroupsModal: {type: Boolean}
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -96,6 +100,9 @@ class Chat extends LitElement {
 | 
			
		||||
        this.userSelected = {}
 | 
			
		||||
        this.groupInvites = []
 | 
			
		||||
        this.loggedInUserName = ""
 | 
			
		||||
        this.openDialogGroupsModal = false
 | 
			
		||||
        this.uid = new ShortUniqueId();
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async setActiveChatHeadUrl(url) {
 | 
			
		||||
@@ -188,34 +195,74 @@ class Chat extends LitElement {
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setOpenDialogGroupsModal(val){
 | 
			
		||||
        this.openDialogGroupsModal = val
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    openTabToGroupManagement(){
 | 
			
		||||
        window.parent.reduxStore.dispatch(
 | 
			
		||||
            window.parent.reduxAction.setNewTab({
 | 
			
		||||
                url: `group-management`,
 | 
			
		||||
                id: this.uid.rnd(),
 | 
			
		||||
                myPlugObj: {
 | 
			
		||||
                    "url": "group-management",
 | 
			
		||||
                    "domain": "core",
 | 
			
		||||
                    "page": "group-management/index.html",
 | 
			
		||||
                    "title": "Group Management",
 | 
			
		||||
                    "icon": "vaadin:group",
 | 
			
		||||
                    "mwcicon": "group",
 | 
			
		||||
                    "pluginNumber": "plugin-fJZNpyLGTl",
 | 
			
		||||
                    "menus": [],
 | 
			
		||||
                    "parent": false
 | 
			
		||||
                },
 | 
			
		||||
                openExisting: true
 | 
			
		||||
            })
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    render() {
 | 
			
		||||
        return html`
 | 
			
		||||
            <div class="container clearfix">
 | 
			
		||||
                <div class="people-list" id="people-list">
 | 
			
		||||
                    <div class="search">
 | 
			
		||||
                        <div class="create-chat" @click=${() => { this.openPrivateMessage = true }}>
 | 
			
		||||
                        <div id="openPrivateMessage" class="create-chat" @click=${() => { this.openPrivateMessage = true }}>
 | 
			
		||||
                        <mwc-icon style="color: var(--black);">edit_square</mwc-icon>
 | 
			
		||||
                          ${translate("chatpage.cchange1")}
 | 
			
		||||
                        <vaadin-tooltip
 | 
			
		||||
                        for="openPrivateMessage"
 | 
			
		||||
                        position="top"
 | 
			
		||||
                        hover-delay=${200}
 | 
			
		||||
                        hide-delay=${1}
 | 
			
		||||
                        text=${get('chatpage.cchange1')}>
 | 
			
		||||
                    </vaadin-tooltip>
 | 
			
		||||
                    </div>
 | 
			
		||||
                        <div class="create-chat" @click=${() => { this.openPrivateMessage = true }}>
 | 
			
		||||
                    <div style="display:flex; align-items:center;gap:10px">
 | 
			
		||||
                       
 | 
			
		||||
                        <div id="goToGroup" class="create-chat" @click=${() => { this.openTabToGroupManagement() }}>
 | 
			
		||||
                        <mwc-icon style="color: var(--black);">group_add</mwc-icon>
 | 
			
		||||
                        <vaadin-tooltip
 | 
			
		||||
                        for="goToGroup"
 | 
			
		||||
                        position="top"
 | 
			
		||||
                        hover-delay=${200}
 | 
			
		||||
                        hide-delay=${1}
 | 
			
		||||
                        text=${get('chatpage.cchange96')}>
 | 
			
		||||
                    </vaadin-tooltip>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div class="create-chat" @click=${() => { this.openPrivateMessage = true }}>
 | 
			
		||||
                        <div id="blockedUsers" class="create-chat" @click=${() => { this.shadowRoot.querySelector('#blockedUserDialog').show() }}>
 | 
			
		||||
                        <mwc-icon style="color: var(--black);">person_off</mwc-icon>
 | 
			
		||||
                        <vaadin-tooltip
 | 
			
		||||
                        for="blockedUsers"
 | 
			
		||||
                        position="top"
 | 
			
		||||
                        hover-delay=${200}
 | 
			
		||||
                        hide-delay=${1}
 | 
			
		||||
                        text=${get('chatpage.cchange3')}>
 | 
			
		||||
                    </vaadin-tooltip>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <ul class="list">
 | 
			
		||||
                        ${this.isEmptyArray(this.chatHeads) ? this.renderLoadingText() : this.renderChatHead(this.chatHeads)}
 | 
			
		||||
                    </ul>
 | 
			
		||||
                    <div class="blockedusers">
 | 
			
		||||
                  
 | 
			
		||||
                        <mwc-button 
 | 
			
		||||
                            raised 
 | 
			
		||||
                            label="${translate("chatpage.cchange3")}" 
 | 
			
		||||
                            icon="person_off" 
 | 
			
		||||
                            @click=${() => this.shadowRoot.querySelector('#blockedUserDialog').show()}>
 | 
			
		||||
                        </mwc-button>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="chat">
 | 
			
		||||
                    <div id="newMessageBar" class="new-message-bar hide-new-message-bar clearfix" @click=${() => this.scrollToBottom()}>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user