blockUser and disableGroup features

- block/unblock users (stop receiving messages)
- disable group (stop receiving messages)
- groups, chats, marked are now warped in messenger module. (can be accessed by messenger properties)
- Improved requestGroupInbox and requestDirectInbox
- Improved assigning renderUI functions
- messenger.init now starts the messenger-startups (no longer needed to call each messenger-startup functions individually)
This commit is contained in:
sairajzero 2022-06-02 02:12:17 +05:30
parent c9fde067f2
commit 60d2447e8c
2 changed files with 345 additions and 275 deletions

View File

@ -61,35 +61,21 @@
//load messages from IDB and render them //load messages from IDB and render them
console.log(`Loading Data! Please Wait...`) console.log(`Loading Data! Please Wait...`)
messenger.initUserDB().then(result => { //Check for availble bg image
console.log(result) setBgImage();
//Check for availble bg image //Set UI render functions
setBgImage() messenger.renderUI.chats = renderChatList;
messenger.loadDataFromIDB().then(data => { messenger.renderUI.directChat = renderDirectUI;
console.log(data) messenger.renderUI.groupChat = renderGroupUI;
floGlobals.appendix = data.appendix; messenger.renderUI.mails = m => renderMailList(m, false);
floGlobals.groups = data.groups; messenger.renderUI.marked = renderMarked;
floGlobals.chats = data.chats //init messenger
floGlobals['marked'] = data.marked messenger.init().then(result => {
renderChatList() console.log(result);
renderMailList(data.mails, false) if(isPinSet){
renderMarked(data.marked) loadPage()
messenger.setUIcallbacks(renderDirectUI, renderGroupUI) }
messenger.requestDirectInbox() }).catch(error => notify(error, "error"));
.then(r => console.log("DirectConn:", r))
.catch(e => console.error("Request error:", e))
messenger.requestGroupInbox()
.then(r => console.log(r))
console.log(`Load Successful!`)
if(isPinSet){
loadPage()
}
}).catch(error => {
//console.error(`Failed to load data`)
notify(error, "error")
})
})
}).catch(error => notify(error, "error")) }).catch(error => notify(error, "error"))
} }
</script> </script>
@ -1143,7 +1129,7 @@
getRef('add_as_contact_option').classList.remove('hide-completely') getRef('add_as_contact_option').classList.remove('hide-completely')
} }
const markUnread = floGlobals.marked[clickedContact.floID]?.includes('unread') const markUnread = messenger.marked[clickedContact.floID]?.includes('unread')
if (markUnread) { if (markUnread) {
getRef('mark_read_option').classList.remove('hide-completely') getRef('mark_read_option').classList.remove('hide-completely')
getRef('mark_unread_option').classList.add('hide-completely') getRef('mark_unread_option').classList.add('hide-completely')
@ -1162,7 +1148,7 @@
getRef("contact_initial").innerHTML = ` getRef("contact_initial").innerHTML = `
<svg class="icon group-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path d="M13.61,28.09c-1.63,0-4.72-2.35-5.33-3.58a21.65,21.65,0,0,1-1.35-7.32s-.26-6.07,6.68-6.07a6.38,6.38,0,0,1,6.69,6.07A21.65,21.65,0,0,1,19,24.51c-.62,1.23-3.7,3.58-5.34,3.58"/><path d="M50.39,28.09c-1.64,0-4.72-2.35-5.34-3.58a21.9,21.9,0,0,1-1.35-7.32s-.26-6.07,6.69-6.07a6.37,6.37,0,0,1,6.68,6.07,21.65,21.65,0,0,1-1.35,7.32c-.61,1.23-3.7,3.58-5.33,3.58"/><path d="M32,31.74c-2.21,0-6.37-3.17-7.2-4.83A29.3,29.3,0,0,1,23,17s-.35-8.21,9-8.21c8.68,0,9,8.21,9,8.21a29.3,29.3,0,0,1-1.83,9.88c-.82,1.66-5,4.83-7.2,4.83"/><path d="M48.29,38.58c-4.16-1.83-8.57-3.08-10.34-6.4a12,12,0,0,1-6,3.73,12,12,0,0,1-5.95-3.73c-1.77,3.32-6.18,4.57-10.34,6.4-1.7.71-3.11,9.88-1.13,9.88A33.06,33.06,0,0,0,31.23,53h1.54a33.06,33.06,0,0,0,16.65-4.53C51.4,48.46,50,39.29,48.29,38.58Z"/><path d="M14.82,36.57c.76-.33,1.54-.65,2.3-1,2.49-1,4.85-2,6.22-3.44C21.07,31.23,19,30.25,18,28.41a8.83,8.83,0,0,1-4.41,2.76,8.83,8.83,0,0,1-4.4-2.76c-1.31,2.46-4.58,3.38-7.66,4.74-1.26.52-2.3,7.31-.84,7.31a24.55,24.55,0,0,0,10.86,3.31C11.89,40.81,12.86,37.39,14.82,36.57Z"/><path d="M62.45,33.15c-3.08-1.36-6.35-2.28-7.66-4.74a8.83,8.83,0,0,1-4.4,2.76A8.83,8.83,0,0,1,46,28.41c-1,1.84-3,2.82-5.32,3.76,1.37,1.43,3.73,2.41,6.22,3.44.76.31,1.54.63,2.26,1,2,.83,3,4.25,3.29,7.21a24.55,24.55,0,0,0,10.86-3.31C64.75,40.46,63.71,33.67,62.45,33.15Z"/></svg> <svg class="icon group-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path d="M13.61,28.09c-1.63,0-4.72-2.35-5.33-3.58a21.65,21.65,0,0,1-1.35-7.32s-.26-6.07,6.68-6.07a6.38,6.38,0,0,1,6.69,6.07A21.65,21.65,0,0,1,19,24.51c-.62,1.23-3.7,3.58-5.34,3.58"/><path d="M50.39,28.09c-1.64,0-4.72-2.35-5.34-3.58a21.9,21.9,0,0,1-1.35-7.32s-.26-6.07,6.69-6.07a6.37,6.37,0,0,1,6.68,6.07,21.65,21.65,0,0,1-1.35,7.32c-.61,1.23-3.7,3.58-5.33,3.58"/><path d="M32,31.74c-2.21,0-6.37-3.17-7.2-4.83A29.3,29.3,0,0,1,23,17s-.35-8.21,9-8.21c8.68,0,9,8.21,9,8.21a29.3,29.3,0,0,1-1.83,9.88c-.82,1.66-5,4.83-7.2,4.83"/><path d="M48.29,38.58c-4.16-1.83-8.57-3.08-10.34-6.4a12,12,0,0,1-6,3.73,12,12,0,0,1-5.95-3.73c-1.77,3.32-6.18,4.57-10.34,6.4-1.7.71-3.11,9.88-1.13,9.88A33.06,33.06,0,0,0,31.23,53h1.54a33.06,33.06,0,0,0,16.65-4.53C51.4,48.46,50,39.29,48.29,38.58Z"/><path d="M14.82,36.57c.76-.33,1.54-.65,2.3-1,2.49-1,4.85-2,6.22-3.44C21.07,31.23,19,30.25,18,28.41a8.83,8.83,0,0,1-4.41,2.76,8.83,8.83,0,0,1-4.4-2.76c-1.31,2.46-4.58,3.38-7.66,4.74-1.26.52-2.3,7.31-.84,7.31a24.55,24.55,0,0,0,10.86,3.31C11.89,40.81,12.86,37.39,14.82,36.57Z"/><path d="M62.45,33.15c-3.08-1.36-6.35-2.28-7.66-4.74a8.83,8.83,0,0,1-4.4,2.76A8.83,8.83,0,0,1,46,28.41c-1,1.84-3,2.82-5.32,3.76,1.37,1.43,3.73,2.41,6.22,3.44.76.31,1.54.63,2.26,1,2,.83,3,4.25,3.29,7.21a24.55,24.55,0,0,0,10.86-3.31C64.75,40.46,63.71,33.67,62.45,33.15Z"/></svg>
` `
if (floGlobals.groups[clickedContact['floID']].admin === myFloID) if (messenger.groups[clickedContact['floID']].admin === myFloID)
getRef('contact_name').disabled = false getRef('contact_name').disabled = false
else else
getRef('contact_name').disabled = true getRef('contact_name').disabled = true
@ -1180,7 +1166,7 @@
case 'contacts_popup': case 'contacts_popup':
const contacts = [] const contacts = []
for (contact in floGlobals.contacts) { for (contact in floGlobals.contacts) {
if (!floGlobals.groups[activeChat.floID].members.includes(contact) && contact in floGlobals.pubKeys) { if (!messenger.groups[activeChat.floID].members.includes(contact) && contact in floGlobals.pubKeys) {
contacts.push(contact) contacts.push(contact)
} }
} }
@ -1382,8 +1368,8 @@
let name let name
if (floGlobals.contacts[floID]) if (floGlobals.contacts[floID])
name = floGlobals.contacts[floID] name = floGlobals.contacts[floID]
else if (floGlobals.groups[floID]) else if (messenger.groups[floID])
name = floGlobals.groups[floID].name name = messenger.groups[floID].name
else if (floID === myFloID) else if (floID === myFloID)
name = 'You' name = 'You'
else else
@ -1678,7 +1664,7 @@
initial.innerHTML = ` initial.innerHTML = `
<svg class="icon group-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path d="M13.61,28.09c-1.63,0-4.72-2.35-5.33-3.58a21.65,21.65,0,0,1-1.35-7.32s-.26-6.07,6.68-6.07a6.38,6.38,0,0,1,6.69,6.07A21.65,21.65,0,0,1,19,24.51c-.62,1.23-3.7,3.58-5.34,3.58"/><path d="M50.39,28.09c-1.64,0-4.72-2.35-5.34-3.58a21.9,21.9,0,0,1-1.35-7.32s-.26-6.07,6.69-6.07a6.37,6.37,0,0,1,6.68,6.07,21.65,21.65,0,0,1-1.35,7.32c-.61,1.23-3.7,3.58-5.33,3.58"/><path d="M32,31.74c-2.21,0-6.37-3.17-7.2-4.83A29.3,29.3,0,0,1,23,17s-.35-8.21,9-8.21c8.68,0,9,8.21,9,8.21a29.3,29.3,0,0,1-1.83,9.88c-.82,1.66-5,4.83-7.2,4.83"/><path d="M48.29,38.58c-4.16-1.83-8.57-3.08-10.34-6.4a12,12,0,0,1-6,3.73,12,12,0,0,1-5.95-3.73c-1.77,3.32-6.18,4.57-10.34,6.4-1.7.71-3.11,9.88-1.13,9.88A33.06,33.06,0,0,0,31.23,53h1.54a33.06,33.06,0,0,0,16.65-4.53C51.4,48.46,50,39.29,48.29,38.58Z"/><path d="M14.82,36.57c.76-.33,1.54-.65,2.3-1,2.49-1,4.85-2,6.22-3.44C21.07,31.23,19,30.25,18,28.41a8.83,8.83,0,0,1-4.41,2.76,8.83,8.83,0,0,1-4.4-2.76c-1.31,2.46-4.58,3.38-7.66,4.74-1.26.52-2.3,7.31-.84,7.31a24.55,24.55,0,0,0,10.86,3.31C11.89,40.81,12.86,37.39,14.82,36.57Z"/><path d="M62.45,33.15c-3.08-1.36-6.35-2.28-7.66-4.74a8.83,8.83,0,0,1-4.4,2.76A8.83,8.83,0,0,1,46,28.41c-1,1.84-3,2.82-5.32,3.76,1.37,1.43,3.73,2.41,6.22,3.44.76.31,1.54.63,2.26,1,2,.83,3,4.25,3.29,7.21a24.55,24.55,0,0,0,10.86-3.31C64.75,40.46,63.71,33.67,62.45,33.15Z"/></svg> <svg class="icon group-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path d="M13.61,28.09c-1.63,0-4.72-2.35-5.33-3.58a21.65,21.65,0,0,1-1.35-7.32s-.26-6.07,6.68-6.07a6.38,6.38,0,0,1,6.69,6.07A21.65,21.65,0,0,1,19,24.51c-.62,1.23-3.7,3.58-5.34,3.58"/><path d="M50.39,28.09c-1.64,0-4.72-2.35-5.34-3.58a21.9,21.9,0,0,1-1.35-7.32s-.26-6.07,6.69-6.07a6.37,6.37,0,0,1,6.68,6.07,21.65,21.65,0,0,1-1.35,7.32c-.61,1.23-3.7,3.58-5.33,3.58"/><path d="M32,31.74c-2.21,0-6.37-3.17-7.2-4.83A29.3,29.3,0,0,1,23,17s-.35-8.21,9-8.21c8.68,0,9,8.21,9,8.21a29.3,29.3,0,0,1-1.83,9.88c-.82,1.66-5,4.83-7.2,4.83"/><path d="M48.29,38.58c-4.16-1.83-8.57-3.08-10.34-6.4a12,12,0,0,1-6,3.73,12,12,0,0,1-5.95-3.73c-1.77,3.32-6.18,4.57-10.34,6.4-1.7.71-3.11,9.88-1.13,9.88A33.06,33.06,0,0,0,31.23,53h1.54a33.06,33.06,0,0,0,16.65-4.53C51.4,48.46,50,39.29,48.29,38.58Z"/><path d="M14.82,36.57c.76-.33,1.54-.65,2.3-1,2.49-1,4.85-2,6.22-3.44C21.07,31.23,19,30.25,18,28.41a8.83,8.83,0,0,1-4.41,2.76,8.83,8.83,0,0,1-4.4-2.76c-1.31,2.46-4.58,3.38-7.66,4.74-1.26.52-2.3,7.31-.84,7.31a24.55,24.55,0,0,0,10.86,3.31C11.89,40.81,12.86,37.39,14.82,36.57Z"/><path d="M62.45,33.15c-3.08-1.36-6.35-2.28-7.66-4.74a8.83,8.83,0,0,1-4.4,2.76A8.83,8.83,0,0,1,46,28.41c-1,1.84-3,2.82-5.32,3.76,1.37,1.43,3.73,2.41,6.22,3.44.76.31,1.54.63,2.26,1,2,.83,3,4.25,3.29,7.21a24.55,24.55,0,0,0,10.86-3.31C64.75,40.46,63.71,33.67,62.45,33.15Z"/></svg>
` `
cardContainer.querySelector('.name').textContent = floGlobals.groups[floID].name cardContainer.querySelector('.name').textContent = messenger.groups[floID].name
} }
else { else {
cardContainer.querySelector('.name').textContent = name !== 'Unknown' ? name : floID cardContainer.querySelector('.name').textContent = name !== 'Unknown' ? name : floID
@ -1713,7 +1699,7 @@
} }
} }
if (type === 'group' && lastMessage.time === 0) { if (type === 'group' && lastMessage.time === 0) {
lastMessage.time = floGlobals.groups[floID].created lastMessage.time = messenger.groups[floID].created
} }
let lastText = document.createElement('p') let lastText = document.createElement('p')
if ((type === 'chat' && lastMessage.category === 'sent') || (type === 'group' && lastMessage.sender === myFloID)) { if ((type === 'chat' && lastMessage.category === 'sent') || (type === 'group' && lastMessage.sender === myFloID)) {
@ -1856,7 +1842,7 @@
else if (admin) { else if (admin) {
if (newMembers.length) { if (newMembers.length) {
const cards = document.createDocumentFragment() const cards = document.createDocumentFragment()
const { admin } = floGlobals.groups[groupID] const { admin } = messenger.groups[groupID]
newMembers.forEach(member => { newMembers.forEach(member => {
let eventCard = document.createElement('p') let eventCard = document.createElement('p')
eventCard.classList.add('group-event-card') eventCard.classList.add('group-event-card')
@ -1872,7 +1858,7 @@
} }
else if (rmMembers.length) { else if (rmMembers.length) {
const cards = document.createDocumentFragment() const cards = document.createDocumentFragment()
const { admin } = floGlobals.groups[groupID] const { admin } = messenger.groups[groupID]
rmMembers.forEach(member => { rmMembers.forEach(member => {
let eventCard = document.createElement('p') let eventCard = document.createElement('p')
eventCard.classList.add('group-event-card') eventCard.classList.add('group-event-card')
@ -2134,7 +2120,7 @@
clickedContact['chatCard'] = contact clickedContact['chatCard'] = contact
clickedContact['floID'] = contact.getAttribute("flo-id") clickedContact['floID'] = contact.getAttribute("flo-id")
clickedContact['name'] = contact.getAttribute("name") clickedContact['name'] = contact.getAttribute("name")
clickedContact['isGroup'] = floGlobals.groups.hasOwnProperty(clickedContact['floID']) clickedContact['isGroup'] = messenger.groups.hasOwnProperty(clickedContact['floID'])
showPopup('contact_details_popup') showPopup('contact_details_popup')
}, 500) }, 500)
getRef('chat_page').addEventListener('touchmove', handleTouchMove) getRef('chat_page').addEventListener('touchmove', handleTouchMove)
@ -2171,7 +2157,7 @@
clickedContact['chatCard'] = contact clickedContact['chatCard'] = contact
clickedContact['floID'] = contact.getAttribute("flo-id") clickedContact['floID'] = contact.getAttribute("flo-id")
clickedContact['name'] = contact.getAttribute("name") clickedContact['name'] = contact.getAttribute("name")
clickedContact['isGroup'] = floGlobals.groups.hasOwnProperty(clickedContact['floID']) clickedContact['isGroup'] = messenger.groups.hasOwnProperty(clickedContact['floID'])
if (clickedContact['floID'] === myFloID) return if (clickedContact['floID'] === myFloID) return
@ -2744,15 +2730,15 @@
getRef('contacts_container').append(frag) getRef('contacts_container').append(frag)
} }
async function renderChatList() { async function renderChatList(chatOrder) {
const frag = document.createDocumentFragment() const frag = document.createDocumentFragment()
getRef('chat_container').innerHTML = '' getRef('chat_container').innerHTML = ''
for (floID of messenger.getChatOrder().mixed) { for (floID of chatOrder) {
const markUnread = floGlobals.marked[floID]?.includes('unread') const markUnread = messenger.marked[floID]?.includes('unread')
let type let type
if (floGlobals.chats[floID]) if (messenger.chats[floID])
type = 'chat' type = 'chat'
else if (floGlobals.groups[floID]) else if (messenger.groups[floID])
type = 'group' type = 'group'
frag.append(render.contactCard(floID, { type, markUnread })) frag.append(render.contactCard(floID, { type, markUnread }))
} }
@ -2927,7 +2913,7 @@
backgroundColor = contact.getAttribute('background-color') backgroundColor = contact.getAttribute('background-color')
activeChat['floID'] = floID activeChat['floID'] = floID
activeChat['isGroup'] = floGlobals.groups[floID] ? true : false activeChat['isGroup'] = messenger.groups[floID] ? true : false
getRef("chat_dp").setAttribute('style', `color: ${textColor}; background-color: ${backgroundColor};`) getRef("chat_dp").setAttribute('style', `color: ${textColor}; background-color: ${backgroundColor};`)
getRef("receiver_name").textContent = getContactName(floID); getRef("receiver_name").textContent = getContactName(floID);
if (activeChat.isGroup) { if (activeChat.isGroup) {
@ -3235,12 +3221,12 @@
getRef("chat_dp").innerHTML = ` getRef("chat_dp").innerHTML = `
<svg class="icon group-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path d="M13.61,28.09c-1.63,0-4.72-2.35-5.33-3.58a21.65,21.65,0,0,1-1.35-7.32s-.26-6.07,6.68-6.07a6.38,6.38,0,0,1,6.69,6.07A21.65,21.65,0,0,1,19,24.51c-.62,1.23-3.7,3.58-5.34,3.58"/><path d="M50.39,28.09c-1.64,0-4.72-2.35-5.34-3.58a21.9,21.9,0,0,1-1.35-7.32s-.26-6.07,6.69-6.07a6.37,6.37,0,0,1,6.68,6.07,21.65,21.65,0,0,1-1.35,7.32c-.61,1.23-3.7,3.58-5.33,3.58"/><path d="M32,31.74c-2.21,0-6.37-3.17-7.2-4.83A29.3,29.3,0,0,1,23,17s-.35-8.21,9-8.21c8.68,0,9,8.21,9,8.21a29.3,29.3,0,0,1-1.83,9.88c-.82,1.66-5,4.83-7.2,4.83"/><path d="M48.29,38.58c-4.16-1.83-8.57-3.08-10.34-6.4a12,12,0,0,1-6,3.73,12,12,0,0,1-5.95-3.73c-1.77,3.32-6.18,4.57-10.34,6.4-1.7.71-3.11,9.88-1.13,9.88A33.06,33.06,0,0,0,31.23,53h1.54a33.06,33.06,0,0,0,16.65-4.53C51.4,48.46,50,39.29,48.29,38.58Z"/><path d="M14.82,36.57c.76-.33,1.54-.65,2.3-1,2.49-1,4.85-2,6.22-3.44C21.07,31.23,19,30.25,18,28.41a8.83,8.83,0,0,1-4.41,2.76,8.83,8.83,0,0,1-4.4-2.76c-1.31,2.46-4.58,3.38-7.66,4.74-1.26.52-2.3,7.31-.84,7.31a24.55,24.55,0,0,0,10.86,3.31C11.89,40.81,12.86,37.39,14.82,36.57Z"/><path d="M62.45,33.15c-3.08-1.36-6.35-2.28-7.66-4.74a8.83,8.83,0,0,1-4.4,2.76A8.83,8.83,0,0,1,46,28.41c-1,1.84-3,2.82-5.32,3.76,1.37,1.43,3.73,2.41,6.22,3.44.76.31,1.54.63,2.26,1,2,.83,3,4.25,3.29,7.21a24.55,24.55,0,0,0,10.86-3.31C64.75,40.46,63.71,33.67,62.45,33.15Z"/></svg> <svg class="icon group-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path d="M13.61,28.09c-1.63,0-4.72-2.35-5.33-3.58a21.65,21.65,0,0,1-1.35-7.32s-.26-6.07,6.68-6.07a6.38,6.38,0,0,1,6.69,6.07A21.65,21.65,0,0,1,19,24.51c-.62,1.23-3.7,3.58-5.34,3.58"/><path d="M50.39,28.09c-1.64,0-4.72-2.35-5.34-3.58a21.9,21.9,0,0,1-1.35-7.32s-.26-6.07,6.69-6.07a6.37,6.37,0,0,1,6.68,6.07,21.65,21.65,0,0,1-1.35,7.32c-.61,1.23-3.7,3.58-5.33,3.58"/><path d="M32,31.74c-2.21,0-6.37-3.17-7.2-4.83A29.3,29.3,0,0,1,23,17s-.35-8.21,9-8.21c8.68,0,9,8.21,9,8.21a29.3,29.3,0,0,1-1.83,9.88c-.82,1.66-5,4.83-7.2,4.83"/><path d="M48.29,38.58c-4.16-1.83-8.57-3.08-10.34-6.4a12,12,0,0,1-6,3.73,12,12,0,0,1-5.95-3.73c-1.77,3.32-6.18,4.57-10.34,6.4-1.7.71-3.11,9.88-1.13,9.88A33.06,33.06,0,0,0,31.23,53h1.54a33.06,33.06,0,0,0,16.65-4.53C51.4,48.46,50,39.29,48.29,38.58Z"/><path d="M14.82,36.57c.76-.33,1.54-.65,2.3-1,2.49-1,4.85-2,6.22-3.44C21.07,31.23,19,30.25,18,28.41a8.83,8.83,0,0,1-4.41,2.76,8.83,8.83,0,0,1-4.4-2.76c-1.31,2.46-4.58,3.38-7.66,4.74-1.26.52-2.3,7.31-.84,7.31a24.55,24.55,0,0,0,10.86,3.31C11.89,40.81,12.86,37.39,14.82,36.57Z"/><path d="M62.45,33.15c-3.08-1.36-6.35-2.28-7.66-4.74a8.83,8.83,0,0,1-4.4,2.76A8.83,8.83,0,0,1,46,28.41c-1,1.84-3,2.82-5.32,3.76,1.37,1.43,3.73,2.41,6.22,3.44.76.31,1.54.63,2.26,1,2,.83,3,4.25,3.29,7.21a24.55,24.55,0,0,0,10.86-3.31C64.75,40.46,63.71,33.67,62.45,33.15Z"/></svg>
` `
getRef("last_interaction_time").textContent = `Created ${getFormatedTime(floGlobals.groups[floID].created)}`; getRef("last_interaction_time").textContent = `Created ${getFormatedTime(messenger.groups[floID].created)}`;
getRef("chat_type").textContent = `Group FLO ID`; getRef("chat_type").textContent = `Group FLO ID`;
getRef('group_members_list').innerHTML = '' getRef('group_members_list').innerHTML = ''
floGlobals.groups[floID].members.forEach(member => { messenger.groups[floID].members.forEach(member => {
let isAdmin = floGlobals.groups[floID].admin === member ? true : false let isAdmin = messenger.groups[floID].admin === member ? true : false
frag.append(render.contactCard(member, { type: 'contact', contactOnly: true, isAdmin })) frag.append(render.contactCard(member, { type: 'contact', contactOnly: true, isAdmin }))
}) })
getRef('group_members_list').append(frag) getRef('group_members_list').append(frag)
@ -3250,9 +3236,9 @@
getRef('delete_chat_button').classList.add('hide-completely') getRef('delete_chat_button').classList.add('hide-completely')
getRef("group_description").value = floGlobals.groups[floID].description === '' ? 'Add group description' : floGlobals.groups[floID].description; getRef("group_description").value = messenger.groups[floID].description === '' ? 'Add group description' : messenger.groups[floID].description;
if (floGlobals.groups[activeChat['floID']].admin === myFloID) { if (messenger.groups[activeChat['floID']].admin === myFloID) {
getRef("chat_name").disabled = false getRef("chat_name").disabled = false
getRef('group_description').disabled = false getRef('group_description').disabled = false
getRef('edit_group_button').classList.remove('hide-completely') getRef('edit_group_button').classList.remove('hide-completely')

View File

@ -1,6 +1,62 @@
(function() { (function() {
const messenger = window.messenger = {}; const messenger = window.messenger = {};
const expiredKeys = {};
const UI = {
group: (d, e) => console.log(d, e),
direct: (d, e) => console.log(d, e),
chats: (c) => console.log(c),
mails: (m) => console.log(m),
marked: (r) => console.log(r)
};
messenger.renderUI = {};
Object.defineProperties(messenger.renderUI, {
chats: {
set: ui_fn => UI.chats = ui_fn
},
directChat: {
set: ui_fn => UI.direct = ui_fn
},
groupChat: {
set: ui_fn => UI.group = ui_fn
},
mails: {
set: ui_fn => UI.mails = ui_fn
},
marked: {
set: ui_fn => UI.marked = ui_fn
},
});
const _loaded = {};
Object.defineProperties(messenger, {
chats: {
get: _loaded.chats
},
groups: {
get: _loaded.groups
},
blocked: {
get: _loaded.blocked
},
marked: {
get: _loaded.marked
}
});
var directConnID, groupConnID = {};
messenger.conn = {};
Object.defineProperties(messenger.conn, {
direct: {
get: directConnID
},
group: {
get: Object.assign({}, groupConnID),
value: g_id => groupConnID[g_id]
}
});
function sendRaw(message, recipient, type, encrypt = null, comment = undefined) { function sendRaw(message, recipient, type, encrypt = null, comment = undefined) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!floCrypto.validateAddr(recipient)) if (!floCrypto.validateAddr(recipient))
@ -21,11 +77,11 @@
}) })
} }
function encrypt(value, key = floGlobals.appendix.AESKey) { function encrypt(value, key = _loaded.appendix.AESKey) {
return Crypto.AES.encrypt(value, key) return Crypto.AES.encrypt(value, key)
} }
function decrypt(value, key = floGlobals.appendix.AESKey) { function decrypt(value, key = _loaded.appendix.AESKey) {
return Crypto.AES.decrypt(value, key) return Crypto.AES.decrypt(value, key)
} }
@ -51,8 +107,7 @@
if (!result || !result.includes(mark)) if (!result || !result.includes(mark))
return resolve("Mark doesnot exist") return resolve("Mark doesnot exist")
else { else {
result.splice(result.indexOf(mark), result.splice(result.indexOf(mark), 1); //remove the mark from the list of marks
1); //remove the mark from the list of marks
compactIDB.writeData("marked", result, key) compactIDB.writeData("marked", result, key)
.then(result => resolve("Mark removed")) .then(result => resolve("Mark removed"))
.catch(error => reject(error)) .catch(error => reject(error))
@ -61,13 +116,12 @@
}) })
} }
const UIcallback = { function requestGroupInbox(groupID) {
group: (d, e) => console.log(d, e), console.debug(UI);
direct: (d, e) => console.log(d, e) if (groupConnID[groupID]) { //close existing request connection (if any)
} floCloudAPI.closeRequest(groupConnID[groupID]);
delete groupConnID[groupID];
function groupConn(groupID) { }
console.debug(UIcallback);
let callbackFn = function(dataSet, error) { let callbackFn = function(dataSet, error) {
if (error) if (error)
return console.error(error) return console.error(error)
@ -78,7 +132,7 @@
let infoChange = false; let infoChange = false;
for (let vc in dataSet) { for (let vc in dataSet) {
if (groupID !== dataSet[vc].receiverID || if (groupID !== dataSet[vc].receiverID ||
!floGlobals.groups[groupID].members.includes(dataSet[vc].senderID)) !_loaded.groups[groupID].members.includes(dataSet[vc].senderID))
continue; continue;
try { try {
let data = { let data = {
@ -86,33 +140,33 @@
sender: dataSet[vc].senderID, sender: dataSet[vc].senderID,
groupID: dataSet[vc].receiverID groupID: dataSet[vc].receiverID
} }
let k = floGlobals.groups[groupID].eKey; let k = _loaded.groups[groupID].eKey;
if (floGlobals.expiredKeys[groupID]) { if (expiredKeys[groupID]) {
var ex = Object.keys(floGlobals.expiredKeys[groupID]).sort() var ex = Object.keys(expiredKeys[groupID]).sort()
while (ex.lenght && vc > ex[0]) ex.shift() while (ex.lenght && vc > ex[0]) ex.shift()
if (ex.length) if (ex.length)
k = floGlobals.expiredKeys[groupID][ex.shift()] k = expiredKeys[groupID][ex.shift()]
} }
dataSet[vc].message = decrypt(dataSet[vc].message, k) dataSet[vc].message = decrypt(dataSet[vc].message, k)
//store the pubKey if not stored already //store the pubKey if not stored already
floDapps.storePubKey(dataSet[vc].senderID, dataSet[vc].pubKey) floDapps.storePubKey(dataSet[vc].senderID, dataSet[vc].pubKey)
if (dataSet[vc].type === "GROUP_MSG") if (dataSet[vc].type === "GROUP_MSG")
data.message = encrypt(dataSet[vc].message); data.message = encrypt(dataSet[vc].message);
else if (data.sender === floGlobals.groups[groupID].admin) { else if (data.sender === _loaded.groups[groupID].admin) {
let groupInfo = floGlobals.groups[groupID] let groupInfo = _loaded.groups[groupID]
data.admin = true; data.admin = true;
if (dataSet[vc].type === "ADD_MEMBERS") { if (dataSet[vc].type === "ADD_MEMBERS") {
data.newMembers = dataSet[vc].message.split("|") data.newMembers = dataSet[vc].message.split("|")
data.note = dataSet[vc].comment data.note = dataSet[vc].comment
groupInfo.members = [...new Set(groupInfo.members.concat(data groupInfo.members = [...new Set(groupInfo.members.concat(data.newMembers))]
.newMembers))]
} else if (dataSet[vc].type === "RM_MEMBERS") { } else if (dataSet[vc].type === "RM_MEMBERS") {
data.rmMembers = dataSet[vc].message.split("|") data.rmMembers = dataSet[vc].message.split("|")
data.note = dataSet[vc].comment data.note = dataSet[vc].comment
groupInfo.members = groupInfo.members.filter(m => !data.rmMembers groupInfo.members = groupInfo.members.filter(m => !data.rmMembers.includes(m))
.includes(m)) if (data.rmMembers.includes(myFloID)) {
if (data.rmMembers.includes(myFloID)) disableGroup(groupID);
groupInfo.status = false return;
}
} else if (dataSet[vc].type === "UP_DESCRIPTION") { } else if (dataSet[vc].type === "UP_DESCRIPTION") {
data.description = dataSet[vc].message data.description = dataSet[vc].message
groupInfo.description = data.description groupInfo.description = data.description
@ -131,40 +185,35 @@
console.log(data) console.log(data)
if (data.sender !== myFloID) if (data.sender !== myFloID)
addMark(data.groupID, "unread") addMark(data.groupID, "unread")
if (!floGlobals.appendix[`lastReceived_${groupID}`] || if (!_loaded.appendix[`lastReceived_${groupID}`] ||
floGlobals.appendix[`lastReceived_${groupID}`] < vc) _loaded.appendix[`lastReceived_${groupID}`] < vc)
floGlobals.appendix[`lastReceived_${groupID}`] = vc; _loaded.appendix[`lastReceived_${groupID}`] = vc;
} catch (error) { } catch (error) {
console.log(error) console.log(error)
} }
} }
compactIDB.writeData("appendix", floGlobals.appendix[`lastReceived_${groupID}`], compactIDB.writeData("appendix", _loaded.appendix[`lastReceived_${groupID}`],
`lastReceived_${groupID}`); `lastReceived_${groupID}`);
if (infoChange) { if (infoChange) {
let newInfo = { let newInfo = {
...floGlobals.groups[groupID] ..._loaded.groups[groupID]
} }
newInfo.eKey = encrypt(newInfo.eKey) newInfo.eKey = encrypt(newInfo.eKey)
compactIDB.writeData("groups", newInfo, groupID) compactIDB.writeData("groups", newInfo, groupID)
} }
console.debug(newInbox); console.debug(newInbox);
UIcallback.group(newInbox); UI.group(newInbox);
} }
return floCloudAPI.requestApplicationData(null, { floCloudAPI.requestApplicationData(null, {
receiverID: groupID, receiverID: groupID,
lowerVectorClock: floGlobals.appendix[`lastReceived_${groupID}`] + 1, lowerVectorClock: _loaded.appendix[`lastReceived_${groupID}`] + 1,
callback: callbackFn callback: callbackFn
}) }).then(conn_id => groupConnID[groupID] = conn_id)
.catch(error => console.error(`request-group(${groupID}):`, error))
} }
messenger.setUIcallbacks = function(directUI = null, groupUI = null) { const initUserDB = function() {
if (directUI instanceof Function)
UIcallback["direct"] = directUI
if (groupUI instanceof Function)
UIcallback["group"] = groupUI
}
messenger.initUserDB = function() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
var obj = { var obj = {
messages: {}, messages: {},
@ -173,6 +222,7 @@
chats: {}, chats: {},
groups: {}, groups: {},
gkeys: {}, gkeys: {},
blocked: {},
appendix: {}, appendix: {},
userSettings: {} userSettings: {}
} }
@ -184,8 +234,30 @@
}) })
} }
messenger.blockUser = function(floID) {
return new Promise((resolve, reject) => {
if (_loaded.blocked.has(floID))
return resolve("User is already blocked");
compactIDB.addData("blocked", true, floID).then(result => {
_loaded.blocked.add(floID);
resolve("Blocked User: " + floID);
}).catch(error => reject(error))
})
}
messenger.unblockUser = function(floID) {
return new Promise((resolve, reject) => {
if (!_loaded.blocked.has(floID))
return resolve("User is not blocked");
compactIDB.removeData("blocked", floID).then(result => {
_loaded.blocked.delete(floID);
resolve("Unblocked User: " + floID);
}).catch(error => reject(error))
})
}
messenger.sendMessage = function(message, receiver) { messenger.sendMessage = function(message, receiver) {
return new Promise(async (resolve, reject) => { return new Promise((resolve, reject) => {
sendRaw(message, receiver, "MESSAGE").then(result => { sendRaw(message, receiver, "MESSAGE").then(result => {
let vc = result.vectorClock; let vc = result.vectorClock;
let data = { let data = {
@ -194,7 +266,7 @@
category: 'sent', category: 'sent',
message: encrypt(message) message: encrypt(message)
} }
floGlobals.chats[receiver] = parseInt(vc) _loaded.chats[receiver] = parseInt(vc)
compactIDB.writeData("chats", parseInt(vc), receiver) compactIDB.writeData("chats", parseInt(vc), receiver)
compactIDB.addData("messages", { compactIDB.addData("messages", {
...data ...data
@ -208,7 +280,7 @@
} }
messenger.sendMail = function(subject, content, recipients, prev = null) { messenger.sendMail = function(subject, content, recipients, prev = null) {
return new Promise(async (resolve, reject) => { return new Promise((resolve, reject) => {
if (!Array.isArray(recipients)) if (!Array.isArray(recipients))
recipients = [recipients] recipients = [recipients]
let mail = { let mail = {
@ -240,112 +312,114 @@
}) })
} }
messenger.requestDirectInbox = function() { const requestDirectInbox = function() {
return new Promise((resolve, reject) => { if (directInboxConn) { //close existing request connection (if any)
let callbackFn = function(dataSet, error) { floCloudAPI.closeRequest(directConnID);
if (error) directConnID = undefined;
return console.error(error) }
let newInbox = { let callbackFn = function(dataSet, error) {
messages: {}, if (error)
mails: {}, return console.error(error)
newgroups: [], let newInbox = {
keyrevoke: [] messages: {},
} mails: {},
console.log(dataSet) newgroups: [],
for (let vc in dataSet) { keyrevoke: []
try { }
//store the pubKey if not stored already console.debug("Check if key is vc", dataSet);
floDapps.storePubKey(dataSet[vc].senderID, dataSet[vc].pubKey) for (let vc in dataSet) {
if (dataSet[vc].message instanceof Object && "secret" in dataSet[vc].message) try {
dataSet[vc].message = floCrypto.decryptData(dataSet[vc].message, myPrivKey) //store the pubKey if not stored already
if (dataSet[vc].type === "MESSAGE") { floDapps.storePubKey(dataSet[vc].senderID, dataSet[vc].pubKey);
//process as message if (_loaded.blocked.has(dataSet[vc].senderID) && dataSet[vc].type !== "REVOKE_KEY")
let dm = { throw "blocked-user";
time: dataSet[vc].time, if (dataSet[vc].message instanceof Object && "secret" in dataSet[vc].message)
floID: dataSet[vc].senderID, dataSet[vc].message = floCrypto.decryptData(dataSet[vc].message, myPrivKey)
category: "received", if (dataSet[vc].type === "MESSAGE") {
message: encrypt(dataSet[vc].message) //process as message
} let dm = {
compactIDB.addData("messages", { time: dataSet[vc].time,
...dm floID: dataSet[vc].senderID,
}, `${dm.floID}|${vc}`) category: "received",
floGlobals.chats[dm.floID] = parseInt(vc) message: encrypt(dataSet[vc].message)
compactIDB.writeData("chats", parseInt(vc), dm.floID) }
dm.message = dataSet[vc].message; compactIDB.addData("messages", {
newInbox.messages[vc] = dm; ...dm
addMark(dm.floID, "unread") }, `${dm.floID}|${vc}`)
} else if (dataSet[vc].type === "MAIL") { _loaded.chats[dm.floID] = parseInt(vc)
//process as mail compactIDB.writeData("chats", parseInt(vc), dm.floID)
let data = JSON.parse(dataSet[vc].message); dm.message = dataSet[vc].message;
let mail = { newInbox.messages[vc] = dm;
time: dataSet[vc].time, addMark(dm.floID, "unread")
from: dataSet[vc].senderID, } else if (dataSet[vc].type === "MAIL") {
to: [myFloID], //process as mail
subject: data.subject, let data = JSON.parse(dataSet[vc].message);
content: encrypt(data.content), let mail = {
ref: data.ref, time: dataSet[vc].time,
prev: data.prev from: dataSet[vc].senderID,
} to: [myFloID],
compactIDB.addData("mails", { subject: data.subject,
...mail content: encrypt(data.content),
}, mail.ref); ref: data.ref,
mail.content = data.content; prev: data.prev
newInbox.mails[mail.ref] = mail; }
addMark(mail.ref, "unread") compactIDB.addData("mails", {
} else if (dataSet[vc].type === "CREATE_GROUP") { ...mail
//process create group }, mail.ref);
let groupInfo = JSON.parse(dataSet[vc].message); mail.content = data.content;
let h = ["groupID", "created", "admin"].map(x => groupInfo[x]).join('|') newInbox.mails[mail.ref] = mail;
if (groupInfo.admin === dataSet[vc].senderID && addMark(mail.ref, "unread")
floCrypto.verifySign(h, groupInfo.hash, groupInfo.pubKey) && } else if (dataSet[vc].type === "CREATE_GROUP") {
floCrypto.getFloID(groupInfo.pubKey) === groupInfo.groupID) { //process create group
let eKey = groupInfo.eKey let groupInfo = JSON.parse(dataSet[vc].message);
groupInfo.eKey = encrypt(eKey) let h = ["groupID", "created", "admin"].map(x => groupInfo[x]).join('|')
compactIDB.writeData("groups", { if (groupInfo.admin === dataSet[vc].senderID &&
...groupInfo floCrypto.verifySign(h, groupInfo.hash, groupInfo.pubKey) &&
}, groupInfo.groupID) floCrypto.getFloID(groupInfo.pubKey) === groupInfo.groupID) {
groupInfo.eKey = eKey let eKey = groupInfo.eKey
floGlobals.groups[groupInfo.groupID] = groupInfo groupInfo.eKey = encrypt(eKey)
groupConn(groupInfo.groupID) compactIDB.writeData("groups", {
newInbox.newgroups.push(groupInfo.groupID) ...groupInfo
} }, groupInfo.groupID)
} else if (dataSet[vc].type === "REVOKE_KEY") { groupInfo.eKey = eKey
let r = JSON.parse(dataSet[vc].message); _loaded.groups[groupInfo.groupID] = groupInfo
let groupInfo = floGlobals.groups[r.groupID] requestGroupInbox(groupInfo.groupID)
if (dataSet[vc].senderID === groupInfo.admin) { newInbox.newgroups.push(groupInfo.groupID)
if (typeof floGlobals.expiredKeys[r.groupID] !== "object") }
floGlobals.expiredKeys[r.groupID] = {} } else if (dataSet[vc].type === "REVOKE_KEY") {
floGlobals.expiredKeys[r.groupID][vc] = groupInfo.eKey let r = JSON.parse(dataSet[vc].message);
let eKey = r.newKey let groupInfo = _loaded.groups[r.groupID]
groupInfo.eKey = encrypt(eKey); if (dataSet[vc].senderID === groupInfo.admin) {
compactIDB.writeData("groups", { if (typeof expiredKeys[r.groupID] !== "object")
...groupInfo expiredKeys[r.groupID] = {}
}, groupInfo.groupID) expiredKeys[r.groupID][vc] = groupInfo.eKey
groupInfo.eKey = eKey let eKey = r.newKey
newInbox.keyrevoke.push(groupInfo.groupID) groupInfo.eKey = encrypt(eKey);
} compactIDB.writeData("groups", {
...groupInfo
}, groupInfo.groupID)
groupInfo.eKey = eKey
newInbox.keyrevoke.push(groupInfo.groupID)
} }
} catch (error) {
console.log(error)
} finally {
if (floGlobals.appendix.lastReceived < vc)
floGlobals.appendix.lastReceived = vc;
} }
} catch (error) {
if (error !== "blocked-user")
console.log(error);
} finally {
if (_loaded.appendix.lastReceived < vc)
_loaded.appendix.lastReceived = vc;
} }
compactIDB.writeData("appendix", floGlobals.appendix.lastReceived, "lastReceived");
console.debug(newInbox);
UIcallback.direct(newInbox)
} }
compactIDB.writeData("appendix", _loaded.appendix.lastReceived, "lastReceived");
var options = { console.debug(newInbox);
UI.direct(newInbox)
}
floCloudAPI.requestApplicationData(null, {
receiverID: myFloID, receiverID: myFloID,
lowerVectorClock: floGlobals.appendix.lastReceived + 1, lowerVectorClock: _loaded.appendix.lastReceived + 1,
callback: callbackFn callback: callbackFn
} }).then(conn_id => directConnID = conn_id)
floCloudAPI.requestApplicationData(null, options) .catch(error => console.error("request-direct:", error));
.then(result => resolve(result))
.catch(error => reject(error))
})
} }
messenger.getMail = function(mailRef) { messenger.getMail = function(mailRef) {
@ -357,35 +431,32 @@
}); });
} }
messenger.getChatOrder = function(type = ["direct", "group", "mixed"]) { const getChatOrder = messenger.getChatOrder = function(seperate = false) {
if (typeof type === "string") let result;
type = type.split('|') if (seperate) {
let result = {} result = {};
if (type.includes("direct")) result.direct = Object.keys(_loaded.chats).map(a => [_loaded.chats[a], a])
result.direct = Object.keys(floGlobals.chats).map(a => [floGlobals.chats[a], a]) .sort((a, b) => b[0] - a[0]).map(a => a[1]);
.sort((a, b) => b[0] - a[0]).map(a => a[1]) result.group = Object.keys(_loaded.groups).map(a => [parseInt(_loaded.appendix[`lastReceived_${a}`]), a])
if (type.includes("group")) .sort((a, b) => b[0] - a[0]).map(a => a[1]);
result.group = Object.keys(floGlobals.groups).map(a => [parseInt(floGlobals.appendix[`lastReceived_${a}`]), a]) } else {
.sort((a, b) => b[0] - a[0]).map(a => a[1]) result = Object.keys(_loaded.chats).map(a => [_loaded.chats[a], a])
if (type.includes("mixed")) .concat(Object.keys(_loaded.groups).map(a => [parseInt(_loaded.appendix[`lastReceived_${a}`]), a]))
result.mixed = Object.keys(floGlobals.chats).map(a => [floGlobals.chats[a], a]) .sort((a, b) => b[0] - a[0]).map(a => a[1])
.concat(Object.keys(floGlobals.groups).map(a => [parseInt(floGlobals.appendix[`lastReceived_${a}`]), a])) }
.sort((a, b) => b[0] - a[0]).map(a => a[1]) return result;
if (type.length === 1)
result = result[type[0]]
return result
} }
messenger.storeContact = function(floID, name) { messenger.storeContact = function(floID, name) {
return floDapps.storeContact(floID, name) return floDapps.storeContact(floID, name)
} }
const loadDataFromIDB = messenger.loadDataFromIDB = function(dataList = 'default') { const loadDataFromIDB = function(defaultList = true) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (dataList === 'default') if (defaultList)
dataList = ["mails", "marked", "groups", "chats", "appendix"] dataList = ["mails", "marked", "groups", "chats", "blocked", "appendix"]
else if (dataList === 'all') else
dataList = ["messages", "mails", "marked", "chats", "groups", "gkeys", "appendix"] dataList = ["messages", "mails", "marked", "chats", "groups", "gkeys", "blocked", "appendix"]
let promises = [] let promises = []
for (var i = 0; i < dataList.length; i++) for (var i = 0; i < dataList.length; i++)
promises[i] = compactIDB.readAllData(dataList[i]) promises[i] = compactIDB.readAllData(dataList[i])
@ -393,7 +464,7 @@
let data = {} let data = {}
for (var i = 0; i < dataList.length; i++) for (var i = 0; i < dataList.length; i++)
data[dataList[i]] = results[i] data[dataList[i]] = results[i]
data.appendix.lastReceived = data.appendix.lastReceived || '0' data.appendix.lastReceived = data.appendix.lastReceived || '0';
if (data.appendix.AESKey) { if (data.appendix.AESKey) {
try { try {
let AESKey = floCrypto.decryptData(data.appendix.AESKey, myPrivKey); let AESKey = floCrypto.decryptData(data.appendix.AESKey, myPrivKey);
@ -401,16 +472,16 @@
if (dataList.includes("messages")) if (dataList.includes("messages"))
for (let m in data.messages) for (let m in data.messages)
if (data.messages[m].message) if (data.messages[m].message)
data.messages[m].message = decrypt(data.messages[m].message, AESKey) data.messages[m].message = decrypt(data.messages[m].message, AESKey);
if (dataList.includes("mails")) if (dataList.includes("mails"))
for (let m in data.mails) for (let m in data.mails)
data.mails[m].content = decrypt(data.mails[m].content, AESKey) data.mails[m].content = decrypt(data.mails[m].content, AESKey);
if (dataList.includes("groups")) if (dataList.includes("groups"))
for (let g in data.groups) for (let g in data.groups)
data.groups[g].eKey = decrypt(data.groups[g].eKey, AESKey) data.groups[g].eKey = decrypt(data.groups[g].eKey, AESKey);
if (dataList.includes("gkeys")) if (dataList.includes("gkeys"))
for (let k in data.gkeys) for (let k in data.gkeys)
data.gkeys[k] = decrypt(data.gkeys[k], AESKey) data.gkeys[k] = decrypt(data.gkeys[k], AESKey);
resolve(data) resolve(data)
} catch (error) { } catch (error) {
reject("Corrupted AES Key"); reject("Corrupted AES Key");
@ -418,7 +489,7 @@
} else { } else {
if (Object.keys(data.mails).length) if (Object.keys(data.mails).length)
return reject("AES Key not Found") return reject("AES Key not Found")
let AESKey = floCrypto.randString(32); let AESKey = floCrypto.randString(32, false);
let encryptedKey = floCrypto.encryptData(AESKey, myPubKey); let encryptedKey = floCrypto.encryptData(AESKey, myPubKey);
compactIDB.addData("appendix", encryptedKey, "AESKey").then(result => { compactIDB.addData("appendix", encryptedKey, "AESKey").then(result => {
data.appendix.AESKey = AESKey; data.appendix.AESKey = AESKey;
@ -430,14 +501,14 @@
} }
messenger.addMark = function(key, mark) { messenger.addMark = function(key, mark) {
if (floGlobals.marked.hasOwnProperty(key) && !floGlobals.marked[key].includes(mark)) if (_loaded.marked.hasOwnProperty(key) && !_loaded.marked[key].includes(mark))
floGlobals.marked[key].push(mark) _loaded.marked[key].push(mark)
return addMark(key, mark) return addMark(key, mark)
} }
messenger.removeMark = function(key, mark) { messenger.removeMark = function(key, mark) {
if (floGlobals.marked.hasOwnProperty(key)) if (_loaded.marked.hasOwnProperty(key))
floGlobals.marked[key] = floGlobals.marked[key].filter(v => v !== mark) _loaded.marked[key] = _loaded.marked[key].filter(v => v !== mark)
return removeMark(key, mark) return removeMark(key, mark)
} }
@ -491,7 +562,7 @@
messenger.backupData = function() { messenger.backupData = function() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
loadDataFromIDB("all").then(data => { loadDataFromIDB(false).then(data => {
delete data.appendix.AESKey; delete data.appendix.AESKey;
data.contacts = floGlobals.contacts; data.contacts = floGlobals.contacts;
data.pubKeys = floGlobals.pubKeys; data.pubKeys = floGlobals.pubKeys;
@ -556,14 +627,14 @@
for (let g in data.groups) for (let g in data.groups)
data.groups[g].eKey = encrypt(data.groups[g].eKey) data.groups[g].eKey = encrypt(data.groups[g].eKey)
for (let c in data.chats) for (let c in data.chats)
if (data.chats[c] <= floGlobals.chats[c]) if (data.chats[c] <= _loaded.chats[c])
delete data.chats[c] delete data.chats[c]
for (let l in data.appendix) for (let l in data.appendix)
if (l.startsWith('lastReceived') && data.appendix[l] <= floGlobals.appendix[l]) if (l.startsWith('lastReceived') && data.appendix[l] <= _loaded.appendix[l])
delete data.appendix[l] delete data.appendix[l]
for (let c in data.contacts) for (let c in data.contacts)
if (c in floGlobals.contacts) if (c in floGlobals.contacts)
delete data.contact[c] delete data.contacts[c]
for (let p in data.pubKeys) for (let p in data.pubKeys)
if (p in floGlobals.pubKeys) if (p in floGlobals.pubKeys)
delete data.pubKeys[p] delete data.pubKeys[p]
@ -623,12 +694,12 @@
groupInfo.hash = floCrypto.signData(h, id.privKey) groupInfo.hash = floCrypto.signData(h, id.privKey)
let eKey = floCrypto.randString(16, false) let eKey = floCrypto.randString(16, false)
groupInfo.eKey = encrypt(eKey) groupInfo.eKey = encrypt(eKey)
p1 = compactIDB.addData("groups", groupInfo, id.floID) let p1 = compactIDB.addData("groups", groupInfo, id.floID)
p2 = compactIDB.addData("gkeys", encrypt(id.privKey), id.floID) let p2 = compactIDB.addData("gkeys", encrypt(id.privKey), id.floID)
Promise.all([p1, p2]).then(r => { Promise.all([p1, p2]).then(r => {
groupInfo.eKey = eKey groupInfo.eKey = eKey
floGlobals.groups[id.floID] = groupInfo; _loaded.groups[id.floID] = groupInfo;
groupConn(id.floID) requestGroupInbox(id.floID)
resolve(groupInfo) resolve(groupInfo)
}).catch(e => reject(e)) }).catch(e => reject(e))
}) })
@ -636,7 +707,7 @@
messenger.changeGroupName = function(groupID, name) { messenger.changeGroupName = function(groupID, name) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let groupInfo = floGlobals.groups[groupID] let groupInfo = _loaded.groups[groupID]
if (myFloID !== groupInfo.admin) if (myFloID !== groupInfo.admin)
return reject("Access denied: Admin only!") return reject("Access denied: Admin only!")
let message = encrypt(name, groupInfo.eKey) let message = encrypt(name, groupInfo.eKey)
@ -648,7 +719,7 @@
messenger.changeGroupDescription = function(groupID, description) { messenger.changeGroupDescription = function(groupID, description) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let groupInfo = floGlobals.groups[groupID] let groupInfo = _loaded.groups[groupID]
if (myFloID !== groupInfo.admin) if (myFloID !== groupInfo.admin)
return reject("Access denied: Admin only!") return reject("Access denied: Admin only!")
let message = encrypt(description, groupInfo.eKey) let message = encrypt(description, groupInfo.eKey)
@ -674,11 +745,10 @@
else if (imem2.length) else if (imem2.length)
return reject(`Invalid Members (pubKey not available): ${imem2}`) return reject(`Invalid Members (pubKey not available): ${imem2}`)
//send new newMem list to existing members //send new newMem list to existing members
let groupInfo = floGlobals.groups[groupID] let groupInfo = _loaded.groups[groupID]
if (myFloID !== groupInfo.admin) if (myFloID !== groupInfo.admin)
return reject("Access denied: Admin only!") return reject("Access denied: Admin only!")
//send groupInfo to new newMem //send groupInfo to new newMem
let k = groupInfo.eKey
groupInfo = JSON.stringify(groupInfo) groupInfo = JSON.stringify(groupInfo)
let promises = newMem.map(m => sendRaw(groupInfo, m, "CREATE_GROUP", true)); let promises = newMem.map(m => sendRaw(groupInfo, m, "CREATE_GROUP", true));
Promise.allSettled(promises).then(results => { Promise.allSettled(promises).then(results => {
@ -689,8 +759,8 @@
success.push(newMem[i]) success.push(newMem[i])
else if (results[i].status === "rejected") else if (results[i].status === "rejected")
failed.push(newMem[i]) failed.push(newMem[i])
console.log(success.join("|"), k) console.log(success.join("|"))
let message = encrypt(success.join("|"), k) let message = encrypt(success.join("|"), groupInfo.eKey)
sendRaw(message, groupID, "ADD_MEMBERS", false, note) sendRaw(message, groupID, "ADD_MEMBERS", false, note)
.then(r => resolve(`Members added: ${success}`)) .then(r => resolve(`Members added: ${success}`))
.catch(e => reject(e)) .catch(e => reject(e))
@ -702,16 +772,16 @@
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!Array.isArray(rmMem) && typeof rmMem === "string") if (!Array.isArray(rmMem) && typeof rmMem === "string")
rmMem = [rmMem] rmMem = [rmMem]
let groupInfo = floGlobals.groups[groupID] let groupInfo = _loaded.groups[groupID]
let imem = rmMem.filter(m => !groupInfo.members.includes(m)) let imem = rmMem.filter(m => !groupInfo.members.includes(m))
if (imem.length) if (imem.length)
return reject(`Invalid members: ${imem}`) return reject(`Invalid members: ${imem}`)
if (myFloID !== groupInfo.admin) if (myFloID !== groupInfo.admin)
return reject("Access denied: Admin only!") return reject("Access denied: Admin only!")
let message = encrypt(rmMem.join("|"), groupInfo.eKey) let message = encrypt(rmMem.join("|"), groupInfo.eKey)
p1 = sendRaw(message, groupID, "RM_MEMBERS", false, note) let p1 = sendRaw(message, groupID, "RM_MEMBERS", false, note)
groupInfo.members = groupInfo.members.filter(m => !rmMem.includes(m)) groupInfo.members = groupInfo.members.filter(m => !rmMem.includes(m))
p2 = revokeKey(groupID) let p2 = revokeKey(groupID)
Promise.all([p1, p2]) Promise.all([p1, p2])
.then(r => resolve(`Members removed: ${rmMem}`)) .then(r => resolve(`Members removed: ${rmMem}`))
.catch(e => reject(e)) .catch(e => reject(e))
@ -720,7 +790,7 @@
const revokeKey = messenger.revokeKey = function(groupID) { const revokeKey = messenger.revokeKey = function(groupID) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let groupInfo = floGlobals.groups[groupID] let groupInfo = _loaded.groups[groupID]
if (myFloID !== groupInfo.admin) if (myFloID !== groupInfo.admin)
return reject("Access denied: Admin only!") return reject("Access denied: Admin only!")
let newKey = floCrypto.randString(16, false); let newKey = floCrypto.randString(16, false);
@ -734,8 +804,8 @@
} }
messenger.sendGroupMessage = function(message, groupID) { messenger.sendGroupMessage = function(message, groupID) {
return new Promise(async (resolve, reject) => { return new Promise((resolve, reject) => {
let k = floGlobals.groups[groupID].eKey let k = _loaded.groups[groupID].eKey
message = encrypt(message, k) message = encrypt(message, k)
sendRaw(message, groupID, "GROUP_MSG", false) sendRaw(message, groupID, "GROUP_MSG", false)
.then(result => resolve(`${groupID}: ${message}`)) .then(result => resolve(`${groupID}: ${message}`))
@ -743,32 +813,46 @@
}) })
} }
messenger.requestGroupInbox = function() { const disableGroup = messenger.disableGroup = function(groupID) {
return new Promise((resolve) => { return new Promise((resolve, reject) => {
let promises = [] if (!_loaded.groups[groupID])
let reqFn = (g) => new Promise((res, rej) => { return reject("Group not found");
groupConn(g) let groupInfo = {
.then(r => res([g, r])) ..._loaded.groups[groupID]
.catch(e => rej([g, e])) };
}) if (groupInfo.disabled)
for (let g in floGlobals.groups) return resolve("Group already diabled");
if (floGlobals.groups[g].status !== false) groupInfo.disabled = true;
promises.push(reqFn(g)) groupInfo.eKey = encrypt(groupInfo.eKey)
Promise.allSettled(promises).then(result => { compactIDB.writeData("groups", groupInfo, groupID).then(result => {
let ret = {}; floCloudAPI.closeRequest(groupConnID[groupID]);
result.forEach(r => { delete groupConnID[groupID];
if (r.status === 'fulfilled') resolve("Group diabled");
ret[r.value[0]] = { }).catch(error => reject(error))
status: r.status, })
value: r.value[1] }
}
else if (r.status === "rejected") messenger.init = function() {
ret[r.reason[0]] = { return new Promise((resolve, reject) => {
status: r.status, initUserDB().then(result => {
reason: r.reason[1] console.debug(result);
} loadDataFromIDB().then(data => {
}) console.debug(data);
resolve(ret) //load data to memory
_loaded.appendix = data.appendix;
_loaded.groups = data.groups;
_loaded.chats = data.chats;
_loaded.marked = data.marked;
_loaded.blocked = new Set(Object.keys(data.blocked));
//call UI render functions
UI.chats(getChatOrder());
UI.mails(data.mail);
UI.marked(data.marked);
//request data from cloud
requestDirectInbox();
data.groups.map(g => requestGroupInbox(g))
resolve("Messenger initiated");
}).catch(error => reject(error));
}) })
}) })
} }