mirror of
https://github.com/Qortal/qortal-ui.git
synced 2025-11-03 14:17:30 +00:00
added tab notification and fixed websocket q-chat
This commit is contained in:
@@ -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 } from '../../redux/app/app-actions.js'
|
||||
import { addAutoLoadImageChat, removeAutoLoadImageChat, addChatLastSeen, allowQAPPAutoAuth, removeQAPPAutoAuth, removeQAPPAutoLists, allowQAPPAutoLists, addTabInfo, setTabNotifications, setNewTab } from '../../redux/app/app-actions.js'
|
||||
|
||||
window.reduxStore = store
|
||||
window.reduxAction = {
|
||||
@@ -25,7 +25,10 @@ window.reduxAction = {
|
||||
allowQAPPAutoAuth: allowQAPPAutoAuth,
|
||||
removeQAPPAutoAuth: removeQAPPAutoAuth,
|
||||
allowQAPPAutoLists: allowQAPPAutoLists,
|
||||
removeQAPPAutoLists: removeQAPPAutoLists
|
||||
removeQAPPAutoLists: removeQAPPAutoLists,
|
||||
addTabInfo: addTabInfo,
|
||||
setTabNotifications: setTabNotifications,
|
||||
setNewTab: setNewTab
|
||||
}
|
||||
|
||||
const animationDuration = 0.7 // Seconds
|
||||
|
||||
@@ -6,9 +6,13 @@ import { addPluginRoutes } from '../plugins/addPluginRoutes.js'
|
||||
import { repeat } from 'lit/directives/repeat.js';
|
||||
import ShortUniqueId from 'short-unique-id';
|
||||
import { setNewTab } from '../redux/app/app-actions.js'
|
||||
import localForage from "localforage";
|
||||
|
||||
import '@material/mwc-icon'
|
||||
|
||||
const chatLastSeen = localForage.createInstance({
|
||||
name: "chat-last-seen",
|
||||
});
|
||||
class ShowPlugin extends connect(store)(LitElement) {
|
||||
static get properties() {
|
||||
return {
|
||||
@@ -20,6 +24,9 @@ class ShowPlugin extends connect(store)(LitElement) {
|
||||
currentTab: { type: Number },
|
||||
tabs: { type: Array },
|
||||
theme: { type: String, reflect: true },
|
||||
tabInfo: { type: Object },
|
||||
chatLastSeen: { type: Array },
|
||||
chatHeads: { type: Array }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +57,7 @@ class ShowPlugin extends connect(store)(LitElement) {
|
||||
}
|
||||
|
||||
.hideIframe {
|
||||
visibility: hidden;
|
||||
display: none;
|
||||
position: absolute;
|
||||
zIndex: -10;
|
||||
}
|
||||
@@ -58,7 +65,7 @@ class ShowPlugin extends connect(store)(LitElement) {
|
||||
.showIframe {
|
||||
zIndex: 1;
|
||||
position: relative;
|
||||
visibility: visible;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
@@ -155,6 +162,20 @@ class ShowPlugin extends connect(store)(LitElement) {
|
||||
color: #999;
|
||||
--mdc-icon-size: 20px;
|
||||
}
|
||||
|
||||
.count {
|
||||
position: absolute;
|
||||
background: red;
|
||||
color: white;
|
||||
padding: 5px;
|
||||
font-size: 12px;
|
||||
border-radius: 50%;
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
@@ -165,6 +186,9 @@ class ShowPlugin extends connect(store)(LitElement) {
|
||||
this.tabs = []
|
||||
this.uid = new ShortUniqueId()
|
||||
this.theme = localStorage.getItem('qortalTheme') ? localStorage.getItem('qortalTheme') : 'light'
|
||||
this.tabInfo = {}
|
||||
this.chatLastSeen = []
|
||||
this.chatHeads = []
|
||||
}
|
||||
|
||||
async getUpdateComplete() {
|
||||
@@ -189,9 +213,44 @@ class ShowPlugin extends connect(store)(LitElement) {
|
||||
return myPlug === undefined ? 'about:blank' : `${window.location.origin}/plugin/${myPlug.domain}/${myPlug.page}${this.linkParam}`
|
||||
}
|
||||
|
||||
|
||||
return html`
|
||||
<div class="tabs">
|
||||
${this.tabs.map((tab, index) => html`
|
||||
${this.tabs.map((tab, index) => {
|
||||
let title = ''
|
||||
let count = 0
|
||||
if (tab.myPlugObj && tab.myPlugObj.title) {
|
||||
title = tab.myPlugObj.title
|
||||
}
|
||||
if (tab.myPlugObj && (tab.myPlugObj.url === 'websites' || tab.myPlugObj.url === 'qapps') && this.tabInfo[tab.id]) {
|
||||
title = this.tabInfo[tab.id].name
|
||||
}
|
||||
if (tab.myPlugObj && (tab.myPlugObj.url === 'websites' || tab.myPlugObj.url === 'qapps') && this.tabInfo[tab.id]) {
|
||||
count = this.tabInfo[tab.id].count
|
||||
}
|
||||
|
||||
if (tab.myPlugObj && tab.myPlugObj.url === 'q-chat') {
|
||||
for (const chat of this.chatHeads) {
|
||||
|
||||
const lastReadMessage = this.chatLastSeen.find((ch) => {
|
||||
let id
|
||||
if (chat.groupId === 0) {
|
||||
id = chat.groupId
|
||||
} else if (chat.groupId) {
|
||||
id = chat.groupId
|
||||
} else {
|
||||
id = chat.address
|
||||
}
|
||||
|
||||
return ch.key.includes(id)
|
||||
})
|
||||
if (lastReadMessage && lastReadMessage.timestamp < chat.timestamp) {
|
||||
count = count + 1
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return html`
|
||||
<div
|
||||
class="tab ${this.currentTab === index ? 'active' : ''}"
|
||||
@click=${() => this.currentTab = index}
|
||||
@@ -200,15 +259,20 @@ class ShowPlugin extends connect(store)(LitElement) {
|
||||
<div class="${this.currentTab === index ? "iconActive" : "iconInactive"}">
|
||||
<mwc-icon>${tab.myPlugObj && tab.myPlugObj.mwcicon}</mwc-icon>
|
||||
</div>
|
||||
${count ? html`
|
||||
<div class="count">${count}</div>
|
||||
` : ''}
|
||||
|
||||
<div>
|
||||
|
||||
${tab.myPlugObj && tab.myPlugObj.title}
|
||||
${title}
|
||||
|
||||
</div>
|
||||
<div class="close" @click=${() => { this.removeTab(index) }}>x</div>
|
||||
</div>
|
||||
</div>
|
||||
`)}
|
||||
`
|
||||
})}
|
||||
<button
|
||||
class="add-tab-button"
|
||||
title="Add Tab"
|
||||
@@ -227,7 +291,7 @@ class ShowPlugin extends connect(store)(LitElement) {
|
||||
|
||||
${repeat(this.tabs, (tab) => tab.id, (tab, index) => html`
|
||||
<div class=${this.currentTab === index ? "showIframe" : "hideIframe"}>
|
||||
<iframe src="${plugSrc(tab.myPlugObj)}" id="showPluginFrame${index}" style="width:100%;
|
||||
<iframe src="${plugSrc(tab.myPlugObj)}" data-id=${tab.id} id="showPluginFrame${index}" style="width:100%;
|
||||
height:calc(var(--window-height) - 102px);
|
||||
border:0;
|
||||
padding:0;
|
||||
@@ -321,7 +385,7 @@ class ShowPlugin extends connect(store)(LitElement) {
|
||||
this.tabs = copiedTabs
|
||||
}
|
||||
|
||||
stateChanged(state) {
|
||||
async stateChanged(state) {
|
||||
const split = state.app.url.split('/')
|
||||
const newRegisteredUrls = state.app.registeredUrls
|
||||
|
||||
@@ -352,6 +416,23 @@ class ShowPlugin extends connect(store)(LitElement) {
|
||||
if (newLinkParam !== this.linkParam) {
|
||||
this.linkParam = newLinkParam
|
||||
}
|
||||
if (this.tabInfo !== state.app.tabInfo) {
|
||||
this.tabInfo = state.app.tabInfo
|
||||
}
|
||||
if (this.chatLastSeen !== state.app.chatLastSeen) {
|
||||
this.chatLastSeen = state.app.chatLastSeen
|
||||
}
|
||||
if (state.app.chatHeads !== this.unModifiedChatHeads) {
|
||||
let chatHeads = []
|
||||
if (state.app.chatHeads && state.app.chatHeads.groups) {
|
||||
chatHeads = [...chatHeads, ...state.app.chatHeads.groups]
|
||||
}
|
||||
if (state.app.chatHeads && state.app.chatHeads.direct) {
|
||||
chatHeads = [...chatHeads, ...state.app.chatHeads.direct]
|
||||
}
|
||||
this.chatHeads = chatHeads
|
||||
this.unModifiedChatHeads = state.app.chatHeads
|
||||
}
|
||||
|
||||
if (state.app.newTab) {
|
||||
const newTab = state.app.newTab
|
||||
@@ -623,8 +704,8 @@ class NavBar extends connect(store)(LitElement) {
|
||||
<div class="app-list">
|
||||
${repeat(this.myMenuList, (plugin) => plugin.url, (plugin, index) => html`
|
||||
<div class="app-icon" @click=${() => {
|
||||
this.changePage(plugin)
|
||||
}}>
|
||||
this.changePage(plugin)
|
||||
}}>
|
||||
<div class="app-icon-box">
|
||||
<mwc-icon class="menuIcon">${plugin.mwcicon}</mwc-icon>
|
||||
</div>
|
||||
|
||||
@@ -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 } 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 } from '../app-action-types.js'
|
||||
|
||||
export const doUpdateBlockInfo = (blockObj) => {
|
||||
return (dispatch, getState) => {
|
||||
@@ -127,3 +127,16 @@ export const setNewTab = (payload) => {
|
||||
}
|
||||
}
|
||||
|
||||
export const addTabInfo = (payload) => {
|
||||
return {
|
||||
type: ADD_TAB_INFO,
|
||||
payload
|
||||
}
|
||||
}
|
||||
|
||||
export const setTabNotifications = (payload) => {
|
||||
return {
|
||||
type: SET_TAB_NOTIFICATIONS,
|
||||
payload
|
||||
}
|
||||
}
|
||||
@@ -25,4 +25,6 @@ export const ALLOW_QAPP_AUTO_LISTS = 'ALLOW_QAPP_AUTO_LISTS'
|
||||
export const REMOVE_QAPP_AUTO_LISTS = 'REMOVE_QAPP_AUTO_LISTS'
|
||||
export const SET_CHAT_LAST_SEEN = 'SET_CHAT_LAST_SEEN'
|
||||
export const ADD_CHAT_LAST_SEEN = 'ADD_CHAT_LAST_SEEN'
|
||||
export const SET_NEW_TAB = 'SET_NEW_TAB'
|
||||
export const SET_NEW_TAB = 'SET_NEW_TAB'
|
||||
export const ADD_TAB_INFO = 'ADD_TAB_INFO'
|
||||
export const SET_TAB_NOTIFICATIONS = 'SET_TAB_NOTIFICATIONS'
|
||||
@@ -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 } 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 } from './app-action-types.js'
|
||||
import { initWorkersReducer } from './reducers/init-workers.js'
|
||||
import { loginReducer } from './reducers/login-reducer.js'
|
||||
import { setNode, addNode } from './reducers/manage-node.js'
|
||||
@@ -47,7 +47,8 @@ const INITIAL_STATE = {
|
||||
qAPPAutoAuth: loadStateFromLocalStorage('qAPPAutoAuth') || false,
|
||||
qAPPAutoLists: loadStateFromLocalStorage('qAPPAutoLists') || false,
|
||||
chatLastSeen: [],
|
||||
newTab: null
|
||||
newTab: null,
|
||||
tabInfo: {}
|
||||
}
|
||||
|
||||
export default (state = INITIAL_STATE, action) => {
|
||||
@@ -228,6 +229,40 @@ export default (state = INITIAL_STATE, action) => {
|
||||
newTab: action.payload
|
||||
}
|
||||
}
|
||||
case ADD_TAB_INFO: {
|
||||
const newTabInfo = action.payload
|
||||
if (state.tabInfo[newTabInfo.id] && state.tabInfo[newTabInfo.id].name && newTabInfo.name === state.tabInfo[newTabInfo.id].name) break
|
||||
return {
|
||||
...state,
|
||||
tabInfo: {
|
||||
...state.tabInfo,
|
||||
[newTabInfo.id]: {
|
||||
...newTabInfo,
|
||||
count: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case SET_TAB_NOTIFICATIONS: {
|
||||
const count = action.payload.count
|
||||
const name = action.payload.name
|
||||
const newTabInfo = {}
|
||||
Object.keys(state.tabInfo).forEach((key) => {
|
||||
const tab = state.tabInfo[key]
|
||||
if (tab.name == name) {
|
||||
newTabInfo[key] = {
|
||||
...tab,
|
||||
count
|
||||
}
|
||||
} else {
|
||||
newTabInfo[key] = tab
|
||||
}
|
||||
})
|
||||
return {
|
||||
...state,
|
||||
tabInfo: newTabInfo
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return state
|
||||
|
||||
Reference in New Issue
Block a user