Implementing pipeline UI
-- added pipeline messages sending and rendering -- added transaction signed event rendering -- bug fixes and UI improvements
This commit is contained in:
parent
a71222cb4f
commit
da61ff1559
30
css/main.css
30
css/main.css
@ -1037,7 +1037,7 @@ sm-button[variant=primary] {
|
||||
grid-template-columns: auto 1fr;
|
||||
grid-template-areas: "dp .";
|
||||
}
|
||||
.contact.chat, .contact.group {
|
||||
.contact.chat, .contact.group, .contact.pipeline {
|
||||
grid-template-columns: auto 1fr auto;
|
||||
grid-template-areas: "dp . time" "dp . .";
|
||||
}
|
||||
@ -1196,34 +1196,23 @@ sm-button[variant=primary] {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
#warn_no_encryption,
|
||||
.date-card,
|
||||
.group-event-card {
|
||||
.event-card {
|
||||
padding: 0.4rem 0.6rem;
|
||||
font-weight: 500;
|
||||
font-size: 0.8rem;
|
||||
background-color: rgba(var(--text-color), 0.04);
|
||||
border-radius: 0.3rem;
|
||||
border-radius: 0.5rem;
|
||||
color: rgba(var(--text-color), 0.8);
|
||||
margin: 1rem 0;
|
||||
justify-self: center;
|
||||
align-self: center;
|
||||
text-align: center;
|
||||
}
|
||||
#warn_no_encryption + #warn_no_encryption,
|
||||
#warn_no_encryption + .date-card,
|
||||
#warn_no_encryption + .group-event-card,
|
||||
.date-card + #warn_no_encryption,
|
||||
.date-card + .date-card,
|
||||
.date-card + .group-event-card,
|
||||
.group-event-card + #warn_no_encryption,
|
||||
.group-event-card + .date-card,
|
||||
.group-event-card + .group-event-card {
|
||||
.event-card + .event-card {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.group-event-card {
|
||||
font-size: 0.8rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@ -1232,6 +1221,14 @@ sm-button[variant=primary] {
|
||||
color: #111;
|
||||
}
|
||||
|
||||
.pipeline-event {
|
||||
padding: 0.6rem 0.8rem;
|
||||
background-color: rgba(var(--foreground-color), 0.6);
|
||||
}
|
||||
.pipeline-event--signed .icon {
|
||||
fill: var(--green);
|
||||
}
|
||||
|
||||
.contact,
|
||||
.mail-card {
|
||||
padding: 0.8rem;
|
||||
@ -2265,6 +2262,9 @@ sm-button[variant=primary] {
|
||||
--min-width: 24rem;
|
||||
--border-radius: 0.5rem;
|
||||
}
|
||||
#multisig_tx_popup {
|
||||
--width: 28rem;
|
||||
}
|
||||
#landing {
|
||||
align-items: center;
|
||||
gap: 4vw;
|
||||
|
||||
2
css/main.min.css
vendored
2
css/main.min.css
vendored
File diff suppressed because one or more lines are too long
@ -1066,7 +1066,8 @@ sm-button[variant="primary"] {
|
||||
}
|
||||
|
||||
&.chat,
|
||||
&.group {
|
||||
&.group,
|
||||
&.pipeline {
|
||||
grid-template-columns: auto 1fr auto;
|
||||
grid-template-areas:
|
||||
"dp . time"
|
||||
@ -1246,14 +1247,12 @@ sm-button[variant="primary"] {
|
||||
}
|
||||
}
|
||||
|
||||
#warn_no_encryption,
|
||||
.date-card,
|
||||
.group-event-card {
|
||||
.event-card {
|
||||
padding: 0.4rem 0.6rem;
|
||||
font-weight: 500;
|
||||
font-size: 0.8rem;
|
||||
background-color: rgba(var(--text-color), 0.04);
|
||||
border-radius: 0.3rem;
|
||||
border-radius: 0.5rem;
|
||||
color: rgba(var(--text-color), 0.8);
|
||||
margin: 1rem 0;
|
||||
justify-self: center;
|
||||
@ -1266,7 +1265,6 @@ sm-button[variant="primary"] {
|
||||
}
|
||||
|
||||
.group-event-card {
|
||||
font-size: 0.8rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@ -1274,6 +1272,15 @@ sm-button[variant="primary"] {
|
||||
background: rgb(255, 253, 141);
|
||||
color: #111;
|
||||
}
|
||||
.pipeline-event {
|
||||
padding: 0.6rem 0.8rem;
|
||||
background-color: rgba(var(--foreground-color), 0.6);
|
||||
&--signed {
|
||||
.icon {
|
||||
fill: var(--green);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.contact,
|
||||
.mail-card {
|
||||
@ -2380,6 +2387,9 @@ sm-button[variant="primary"] {
|
||||
--min-width: 24rem;
|
||||
--border-radius: 0.5rem;
|
||||
}
|
||||
#multisig_tx_popup {
|
||||
--width: 28rem;
|
||||
}
|
||||
|
||||
#landing {
|
||||
align-items: center;
|
||||
|
||||
275
index.html
275
index.html
@ -42,6 +42,7 @@
|
||||
messenger.renderUI.chats = renderChatList;
|
||||
messenger.renderUI.directChat = renderDirectUI;
|
||||
messenger.renderUI.groupChat = renderGroupUI;
|
||||
messenger.renderUI.pipeline = renderPipelineUI;
|
||||
messenger.renderUI.mails = m => renderMailList(m, false);
|
||||
messenger.renderUI.marked = renderMarked;
|
||||
//init messenger
|
||||
@ -218,33 +219,34 @@
|
||||
<main id="main_page" class="page grid hidden">
|
||||
<section id="chat_page" class="inner-page">
|
||||
<div id="contacts" class="grid">
|
||||
<header class="grid header">
|
||||
<div class="flex align-center">
|
||||
<sm-input id="search_chats" class="margin-right-0-5" type="search"
|
||||
placeholder="Search FLO ID or name">
|
||||
<svg slot="icon" class="icon" xmlns="http://www.w3.org/2000/svg" height="24px"
|
||||
viewBox="0 0 24 24" width="24px" fill="#000000">
|
||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||
<path
|
||||
d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" />
|
||||
</svg>
|
||||
</sm-input>
|
||||
<sm-menu align-options="right">
|
||||
<sm-menu-option onclick="openCreationPopup('group')">
|
||||
Create new group
|
||||
</sm-menu-option>
|
||||
</sm-menu>
|
||||
</div>
|
||||
</header>
|
||||
<section class="grid gap-0-5" style="padding: 1rem;">
|
||||
<h5>Multisig</h5>
|
||||
<div class="margin-bottom-0-5">
|
||||
<div>
|
||||
<button class="button button--small" onclick="openCreationPopup('multisig')">Create
|
||||
address</button>
|
||||
<button class="button button--small" onclick="openPopup('multisig_tx_popup')">Initiate
|
||||
transaction</button>
|
||||
</div>
|
||||
</section>
|
||||
<div class="grid header">
|
||||
<div class="flex align-center space-between">
|
||||
<h4>Messages</h4>
|
||||
<sm-menu align-options="right">
|
||||
<sm-menu-option onclick="openCreationPopup('group')">
|
||||
Create new group
|
||||
</sm-menu-option>
|
||||
</sm-menu>
|
||||
</div>
|
||||
<sm-input id="search_chats" class="margin-right-0-5" type="search"
|
||||
placeholder="Search FLO ID or name">
|
||||
<svg slot="icon" class="icon" xmlns="http://www.w3.org/2000/svg" height="24px"
|
||||
viewBox="0 0 24 24" width="24px" fill="#000000">
|
||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||
<path
|
||||
d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" />
|
||||
</svg>
|
||||
</sm-input>
|
||||
</div>
|
||||
<div id="chats_list" class="flex observe-empty-state"></div>
|
||||
<div class="empty-state flex flex-direction-column align-center text-center align-self-center">
|
||||
<svg class="icon icon--big" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24"
|
||||
@ -794,19 +796,6 @@
|
||||
</svg>
|
||||
Add contact
|
||||
</button>
|
||||
<button id="crate_multisig_option" class="option interactive" onclick="openCreationPopup('multisig')">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px"
|
||||
viewBox="0 0 24 24" width="24px" fill="#000000">
|
||||
<g>
|
||||
<rect fill="none" height="24" width="24" />
|
||||
</g>
|
||||
<g>
|
||||
<path
|
||||
d="M20,9V6h-2v3h-3v2h3v3h2v-3h3V9H20z M9,12c2.21,0,4-1.79,4-4c0-2.21-1.79-4-4-4S5,5.79,5,8C5,10.21,6.79,12,9,12z M9,6 c1.1,0,2,0.9,2,2c0,1.1-0.9,2-2,2S7,9.1,7,8C7,6.9,7.9,6,9,6z M15.39,14.56C13.71,13.7,11.53,13,9,13c-2.53,0-4.71,0.7-6.39,1.56 C1.61,15.07,1,16.1,1,17.22V20h16v-2.78C17,16.1,16.39,15.07,15.39,14.56z M15,18H3v-0.78c0-0.38,0.2-0.72,0.52-0.88 C4.71,15.73,6.63,15,9,15c2.37,0,4.29,0.73,5.48,1.34C14.8,16.5,15,16.84,15,17.22V18z" />
|
||||
</g>
|
||||
</svg>
|
||||
Create multisig address
|
||||
</button>
|
||||
</fieldset>
|
||||
<div class="grid gap-1">
|
||||
<h5>Contacts</h5>
|
||||
@ -821,17 +810,15 @@
|
||||
</sm-popup>
|
||||
<sm-popup id="creation_popup">
|
||||
<header class="grid popup__header" slot="header">
|
||||
<div class="flex align-center">
|
||||
<button class="popup__header__close justify-self-start">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
||||
fill="#000000">
|
||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||
<path
|
||||
d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z" />
|
||||
</svg>
|
||||
</button>
|
||||
<h4 id="creation_popup__title">Create group</h4>
|
||||
</div>
|
||||
<button class="popup__header__close justify-self-start">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
||||
fill="#000000">
|
||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||
<path
|
||||
d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z" />
|
||||
</svg>
|
||||
</button>
|
||||
<h3 id="creation_popup__title">Create group</h3>
|
||||
</header>
|
||||
<div id="creation_process">
|
||||
<div>
|
||||
@ -986,8 +973,9 @@
|
||||
</svg>
|
||||
</button>
|
||||
<div class="grid gap-0-5 card" style="padding: 1rem;">
|
||||
<span style="font-size: 0.9rem;">Selected sender</span>
|
||||
<span style="font-size: 0.9rem;">Selected multisig address</span>
|
||||
<h4 id="selected_multisig" class="wrap-around" style="font-size: 0.9rem;"></h4>
|
||||
<p id="selected_multisig__balance"></p>
|
||||
</div>
|
||||
<sm-form id="send_tx">
|
||||
<div class="grid gap-0-5">
|
||||
@ -1257,6 +1245,14 @@
|
||||
popupStack.peek().popup.hide()
|
||||
}
|
||||
|
||||
function getFloIdType(floID) {
|
||||
if (messenger.groups.hasOwnProperty(floID))
|
||||
return 'group';
|
||||
else if (messenger.pipeline.hasOwnProperty(floID))
|
||||
return 'pipeline';
|
||||
else return 'plain';
|
||||
}
|
||||
|
||||
document.addEventListener('popupopened', async e => {
|
||||
getRef('main_page').setAttribute('inert', '')
|
||||
//pushes popup as septate entry in history
|
||||
@ -1264,61 +1260,60 @@
|
||||
switch (e.target.id) {
|
||||
case 'contact_details_popup':
|
||||
const floID = floGlobals.activeFloID;
|
||||
const isGroup = messenger.groups.hasOwnProperty(floID);
|
||||
if (isGroup)
|
||||
const floIdType = getFloIdType(floID);
|
||||
if (floIdType === 'group')
|
||||
isAdmin = messenger.groups[floID].admin === floDapps.user.id
|
||||
if (clickedContact.chatCard.closest('#chats_list')) {
|
||||
let isAdmin = false
|
||||
let addAsContact
|
||||
if (!floGlobals.contacts.hasOwnProperty(floID) && !isGroup)
|
||||
addAsContact = html`
|
||||
let isAdmin = false
|
||||
let addAsContact
|
||||
if (!floGlobals.contacts.hasOwnProperty(floID) && floIdType === 'plain')
|
||||
addAsContact = html`
|
||||
<button id="add_as_contact_option" class="option" onclick="addAsContact()">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"> <g> <rect fill="none" height="24" width="24" /> </g> <g> <path d="M20,9V6h-2v3h-3v2h3v3h2v-3h3V9H20z M9,12c2.21,0,4-1.79,4-4c0-2.21-1.79-4-4-4S5,5.79,5,8C5,10.21,6.79,12,9,12z M9,6 c1.1,0,2,0.9,2,2c0,1.1-0.9,2-2,2S7,9.1,7,8C7,6.9,7.9,6,9,6z M15.39,14.56C13.71,13.7,11.53,13,9,13c-2.53,0-4.71,0.7-6.39,1.56 C1.61,15.07,1,16.1,1,17.22V20h16v-2.78C17,16.1,16.39,15.07,15.39,14.56z M15,18H3v-0.78c0-0.38,0.2-0.72,0.52-0.88 C4.71,15.73,6.63,15,9,15c2.37,0,4.29,0.73,5.48,1.34C14.8,16.5,15,16.84,15,17.22V18z" /> </g> </svg>
|
||||
Add as contact
|
||||
</button>`;
|
||||
let markReadUnread
|
||||
if (messenger.marked[floID] && messenger.marked[floID].includes('unread')) {
|
||||
markReadUnread = html`
|
||||
let markReadUnread
|
||||
if (messenger.marked[floID] && messenger.marked[floID].includes('unread')) {
|
||||
markReadUnread = html`
|
||||
<button id="mark_read_option" class="option" onclick="markAsRead()">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"> <g> <rect fill="none" height="24" width="24" /> <path d="M12,18l-6,0l-4,4V4c0-1.1,0.9-2,2-2h16c1.1,0,2,0.9,2,2v7l-2,0V4H4v12l8,0V18z M23,14.34l-1.41-1.41l-4.24,4.24l-2.12-2.12 l-1.41,1.41L17.34,20L23,14.34z" /> </g> </svg>
|
||||
Mark as read
|
||||
</button>
|
||||
`;
|
||||
} else {
|
||||
markReadUnread = html`
|
||||
} else {
|
||||
markReadUnread = html`
|
||||
<button id="mark_unread_option" class="option" onclick="markAsUnread()">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"> <g> <rect fill="none" height="24" width="24" /> </g> <g> <g> <path d="M20,16H4V4h10.1c-0.08-0.39-0.18-1.11,0-2H4C2.9,2,2,2.9,2,4v18l4-4h14c1.1,0,2-0.9,2-2V6.98c-0.58,0.44-1.26,0.77-2,0.92 V16z" /> <circle cx="19" cy="3" r="3" /> <rect height="2" width="8" x="6" y="12" /> <rect height="2" width="12" x="6" y="9" /> <path d="M6,8h12V7.9c-1.21-0.25-2.25-0.95-2.97-1.9H6V8z" /> </g> </g> </svg>
|
||||
Mark as unread
|
||||
</button>
|
||||
`;
|
||||
}
|
||||
let blockUnblock
|
||||
if (messenger.blocked.has(floID)) {
|
||||
blockUnblock = html`
|
||||
}
|
||||
let blockUnblock
|
||||
if (messenger.blocked.has(floID)) {
|
||||
blockUnblock = html`
|
||||
<button class="option" onclick="unblockUser()">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M7 11v2h10v-2H7zm5-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></svg>
|
||||
Unblock
|
||||
</button>
|
||||
`;
|
||||
} else {
|
||||
blockUnblock = html`
|
||||
} else {
|
||||
blockUnblock = html`
|
||||
<button class="option option--danger" onclick="blockUser()">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM4 12c0-4.42 3.58-8 8-8 1.85 0 3.55.63 4.9 1.69L5.69 16.9C4.63 15.55 4 13.85 4 12zm8 8c-1.85 0-3.55-.63-4.9-1.69L18.31 7.1C19.37 8.45 20 10.15 20 12c0 4.42-3.58 8-8 8z"/></svg>
|
||||
Block
|
||||
</button>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
let deleteChat
|
||||
if (!isGroup) {
|
||||
deleteChat = html`
|
||||
let deleteChat
|
||||
if (floIdType === 'plain') {
|
||||
deleteChat = html`
|
||||
<button id="delete_chat_option" class="option option--danger" onclick="deleteChat()">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"> <path d="M0 0h24v24H0V0z" fill="none" /> <path d="M16 9v10H8V9h8m-1.5-6h-5l-1 1H5v2h14V4h-3.5l-1-1zM18 7H6v12c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7z" /> </svg>
|
||||
Delete this chat
|
||||
</button>
|
||||
`
|
||||
}
|
||||
renderElem(getRef('contact_options'), html`
|
||||
}
|
||||
renderElem(getRef('contact_options'), html`
|
||||
${addAsContact}
|
||||
${markReadUnread}
|
||||
${blockUnblock}
|
||||
@ -1328,8 +1323,7 @@
|
||||
</button>
|
||||
${deleteChat}
|
||||
`)
|
||||
}
|
||||
if (isGroup) {
|
||||
if (floIdType === 'group') {
|
||||
const { description, created } = messenger.groups[floID]
|
||||
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> `
|
||||
getRef("last_interaction_time").textContent = `Created ${getFormattedTime(created)}`;
|
||||
@ -1448,12 +1442,6 @@
|
||||
}
|
||||
})
|
||||
|
||||
function setAttributes(el, attrs) {
|
||||
for (key in attrs) {
|
||||
el.setAttribute(key, attrs[key]);
|
||||
}
|
||||
}
|
||||
|
||||
const selectedColors = [
|
||||
'--dark-red',
|
||||
'--red',
|
||||
@ -1483,12 +1471,6 @@
|
||||
return contactsInfo[floID]
|
||||
}
|
||||
|
||||
function clearElements(array = []) {
|
||||
array.forEach(item => {
|
||||
getRef(item).innerHTML = ``
|
||||
})
|
||||
}
|
||||
|
||||
// displays a popup for asking permission. Use this instead of JS confirm
|
||||
const getConfirmation = (title, options = {}) => {
|
||||
return new Promise(resolve => {
|
||||
@ -2363,6 +2345,8 @@
|
||||
if (type === 'group') {
|
||||
initial = html`<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> `
|
||||
name = messenger.groups[floID].name
|
||||
} else if (type === 'pipeline') {
|
||||
initial = html`<svg class="icon group-icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/></g><g><g><path d="M6,15c1.1,0,2,0.9,2,2s-0.9,2-2,2s-2-0.9-2-2S4.9,15,6,15 M6,13c-2.2,0-4,1.8-4,4s1.8,4,4,4s4-1.8,4-4S8.2,13,6,13z M12,5 c1.1,0,2,0.9,2,2s-0.9,2-2,2s-2-0.9-2-2S10.9,5,12,5 M12,3C9.8,3,8,4.8,8,7s1.8,4,4,4s4-1.8,4-4S14.2,3,12,3z M18,15 c1.1,0,2,0.9,2,2s-0.9,2-2,2s-2-0.9-2-2S16.9,15,18,15 M18,13c-2.2,0-4,1.8-4,4s1.8,4,4,4s4-1.8,4-4S20.2,13,18,13z"/></g></g></svg>`
|
||||
} else {
|
||||
initial = name.charAt(0)
|
||||
}
|
||||
@ -2411,10 +2395,14 @@
|
||||
`
|
||||
},
|
||||
messageBubble(msg) {
|
||||
let { admin = false, newMembers = [], rmMembers = [], groupID, name, description, sender, floID, message, time: timestamp, category, unconfirmed = false, updateChatCard = false } = msg
|
||||
if (activeChat.isGroup) {
|
||||
let { admin = false, newMembers = [], rmMembers = [], groupID, name, description, sender, floID, message, time: timestamp, category, unconfirmed = false,
|
||||
pipeID, type } = msg
|
||||
if (activeChat.type === 'group') {
|
||||
floID = groupID
|
||||
category = sender === floDapps.user.id ? 'sent' : 'received'
|
||||
} else if (activeChat.type === 'pipeline') {
|
||||
floID = pipeID
|
||||
category = sender === floDapps.user.id ? 'sent' : 'received'
|
||||
}
|
||||
if (message) {
|
||||
let senderName = null
|
||||
@ -2447,7 +2435,7 @@
|
||||
let dateCard
|
||||
if (!renderedDates.hasOwnProperty(messageDate) || renderedDates[messageDate] > timestamp) {
|
||||
getRef('messages_container').querySelectorAll(`.date-card[data-date="${messageDate}"]`).forEach(card => card.remove())
|
||||
dateCard = html.node`<time class="date-card" data-date="${messageDate}">${messageDate}</time>`
|
||||
dateCard = html.node`<time class="date-card event-card" data-date="${messageDate}">${messageDate}</time>`
|
||||
renderedDates[messageDate] = timestamp
|
||||
}
|
||||
const className = `message ${category} ${unconfirmed ? 'unconfirmed' : ''} ${senderName ? 'distinct-sender' : ''}`
|
||||
@ -2464,7 +2452,7 @@
|
||||
const cards = document.createDocumentFragment()
|
||||
const { admin } = messenger.groups[groupID]
|
||||
newMembers.forEach(member => {
|
||||
let eventCard = html.node`<p class="group-event-card">${getContactName(admin)} added ${member === floDapps.user.id ? 'you' : getContactName(member)}</p>`
|
||||
let eventCard = html.node`<p class="group-event-card event-card">${getContactName(admin)} added ${member === floDapps.user.id ? 'you' : getContactName(member)}</p>`
|
||||
cards.append(eventCard)
|
||||
})
|
||||
return cards
|
||||
@ -2472,14 +2460,30 @@
|
||||
const cards = document.createDocumentFragment()
|
||||
const { admin } = messenger.groups[groupID]
|
||||
rmMembers.forEach(member => {
|
||||
let eventCard = html.node`<p class="group-event-card">${getContactName(admin)} removed ${member === floDapps.user.id ? 'you' : getContactName(member)}</p>`
|
||||
let eventCard = html.node`<p class="group-event-card event-card">${getContactName(admin)} removed ${member === floDapps.user.id ? 'you' : getContactName(member)}</p>`
|
||||
cards.append(eventCard)
|
||||
})
|
||||
return cards
|
||||
} else if (name) {
|
||||
return html.node`<p class="group-event-card">Changed group name to '${name}'</p>`
|
||||
return html.node`<p class="group-event-card event-card">Changed group name to '${name}'</p>`
|
||||
} else if (description) {
|
||||
return html.node`<p class="group-event-card">Changed group description to '${description}'</p>`
|
||||
return html.node`<p class="group-event-card event-card">Changed group description to '${description}'</p>`
|
||||
}
|
||||
} else if (type) {
|
||||
switch (type) {
|
||||
case 'TRANSACTION':
|
||||
return html.node`<p class="pipeline-event pipeline-event--signed event-card flex align-center">
|
||||
<svg class="icon margin-right-0-5" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/></g><g><path d="M23,12l-2.44-2.79l0.34-3.69l-3.61-0.82L15.4,1.5L12,2.96L8.6,1.5L6.71,4.69L3.1,5.5L3.44,9.2L1,12l2.44,2.79l-0.34,3.7 l3.61,0.82L8.6,22.5l3.4-1.47l3.4,1.46l1.89-3.19l3.61-0.82l-0.34-3.69L23,12z M10.09,16.72l-3.8-3.81l1.48-1.48l2.32,2.33 l5.85-5.87l1.48,1.48L10.09,16.72z"/></g></svg>
|
||||
${getContactName(sender)} signed the transaction
|
||||
</p>`
|
||||
break;
|
||||
case 'BROADCAST':
|
||||
return html.node`<div class="pipeline-event pipeline-event--signed event-card flex align-center">
|
||||
<svg class="icon margin-right-0-5" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/></g><g><path d="M23,12l-2.44-2.79l0.34-3.69l-3.61-0.82L15.4,1.5L12,2.96L8.6,1.5L6.71,4.69L3.1,5.5L3.44,9.2L1,12l2.44,2.79l-0.34,3.7 l3.61,0.82L8.6,22.5l3.4-1.47l3.4,1.46l1.89-3.19l3.61-0.82l-0.34-3.69L23,12z M10.09,16.72l-3.8-3.81l1.48-1.48l2.32,2.33 l5.85-5.87l1.48,1.48L10.09,16.72z"/></g></svg>
|
||||
<h4>Transaction approved</h4>
|
||||
<a class="button--small margin-left-0-5" href="${`https://www.blockchain.com/btc/tx/${msg.txid}`}" target="_blank">View on blockchain</a>
|
||||
</div>`
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2536,7 +2540,7 @@
|
||||
btcOperator.getBalance(address).then(balance => {
|
||||
const target = getRef('select_multisig_list').querySelector(`input[value="${address}"]`).parentNode.querySelector('.multisig-option__balance');
|
||||
if (target)
|
||||
target.textContent = `Balance: ${balance}`;
|
||||
target.textContent = `Balance: ${balance} BTC`;
|
||||
}).catch(err => notify(err, 'error'))
|
||||
return html`
|
||||
<li>
|
||||
@ -2676,12 +2680,20 @@
|
||||
updateMessageUI(data.messages)
|
||||
}
|
||||
|
||||
function renderPipelineUI(model, data) {
|
||||
if (Object.keys(data.messages).length && appState.lastPage !== 'chat_page') {
|
||||
document.title = `New message(s)`
|
||||
addNotificationBadge('#chat_page_button', Object.keys(data.messages).length)
|
||||
}
|
||||
updateMessageUI(data.messages)
|
||||
}
|
||||
|
||||
function updateMessageUI(messagesData, sentByMe = false) {
|
||||
for (let messageId in messagesData) {
|
||||
console.log(messagesData[messageId])
|
||||
const { category, floID, time, message, sender, groupID, admin, name } = messagesData[messageId]
|
||||
const { category, floID, time, message, sender, groupID, admin, name, pipeID } = messagesData[messageId]
|
||||
// code to run if a chat is opened
|
||||
if (activeChat && activeChat.floID === (floID || groupID)) {
|
||||
if (activeChat && activeChat.floID === (floID || groupID || pipeID)) {
|
||||
if (!sentByMe && sender && sender === floDapps.user.id) {
|
||||
// if message is sent by me, then dont add it to the chat
|
||||
} else {
|
||||
@ -2698,13 +2710,13 @@
|
||||
delete floGlobals.checkEncryption[activeChat.floID]
|
||||
}
|
||||
}
|
||||
let chatCard = getChatCard(floID || groupID)
|
||||
let chatCard = getChatCard(floID || groupID || pipeID)
|
||||
if (chatCard) {
|
||||
if (admin) {
|
||||
if (name)
|
||||
chatCard.querySelector('.name').textContent = name
|
||||
}
|
||||
if ((floID || groupID) !== getRef('chats_list').children[0].dataset.floId) {
|
||||
if ((floID || groupID || pipeID) !== getRef('chats_list').children[0].dataset.floId) {
|
||||
const animOptions = {
|
||||
easing: 'ease',
|
||||
duration: 300,
|
||||
@ -2755,20 +2767,20 @@
|
||||
if (chatCard.querySelector('.time'))
|
||||
chatCard.querySelector('.time').textContent = getFormattedTime(time, 'relative')
|
||||
|
||||
if (activeChat.floID === (floID || groupID)) {
|
||||
if (activeChat.floID === (floID || groupID || pipeID)) {
|
||||
if (chatScrollInfo.isScrolledUp)
|
||||
getRef('scroll_to_bottom').classList.add('new-message')
|
||||
else {
|
||||
if (document.hasFocus()) {
|
||||
messenger.removeMark((floID || groupID), 'unread')
|
||||
messenger.removeMark((floID || groupID || pipeID), 'unread')
|
||||
setTimeout(() => {
|
||||
document.title = 'FLO Messenger'
|
||||
getChatCard(floID || groupID).classList.remove('unread')
|
||||
getChatCard(floID || groupID || pipeID).classList.remove('unread')
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getChatCard(floID || groupID).classList.add('unread')
|
||||
getChatCard(floID || groupID || pipeID).classList.add('unread')
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3306,20 +3318,33 @@
|
||||
if (message === '') return
|
||||
let time = Date.now()
|
||||
let msgObj = { message, time, unconfirmed: true }
|
||||
if (activeChat.isGroup) {
|
||||
msgObj['groupID'] = activeChat.floID
|
||||
msgObj['sender'] = floDapps.user.id
|
||||
} else {
|
||||
msgObj['floID'] = activeChat.floID
|
||||
msgObj['category'] = 'sent'
|
||||
switch (activeChat.type) {
|
||||
case 'group':
|
||||
msgObj['groupID'] = receiver
|
||||
msgObj['sender'] = floDapps.user.id
|
||||
break;
|
||||
case 'pipeline':
|
||||
msgObj['pipeID'] = receiver
|
||||
msgObj['sender'] = floDapps.user.id
|
||||
break;
|
||||
case 'plain':
|
||||
msgObj['floID'] = activeChat.floID
|
||||
msgObj['category'] = 'sent'
|
||||
break;
|
||||
}
|
||||
updateMessageUI({ msgObj }, true)
|
||||
try {
|
||||
if (activeChat.isGroup) {
|
||||
await messenger.sendGroupMessage(message, receiver)
|
||||
} else
|
||||
await messenger.sendMessage(message, receiver)
|
||||
|
||||
switch (activeChat.type) {
|
||||
case 'group':
|
||||
await messenger.sendGroupMessage(message, receiver)
|
||||
break;
|
||||
case 'pipeline':
|
||||
await messenger.sendPipelineMessage(message, receiver)
|
||||
break;
|
||||
case 'plain':
|
||||
await messenger.sendMessage(message, receiver)
|
||||
break;
|
||||
}
|
||||
if (getRef('messages_container').querySelector(`.unconfirmed`))
|
||||
getRef('messages_container').querySelector(`.unconfirmed`).classList.remove('unconfirmed')
|
||||
const chatCard = getChatCard(activeChat.floID)
|
||||
@ -3373,6 +3398,8 @@
|
||||
type = 'chat'
|
||||
else if (messenger.groups[floID])
|
||||
type = 'group'
|
||||
else if (messenger.pipeline[floID])
|
||||
type = 'pipeline'
|
||||
return render.contactCard(floID, { type, markUnread, ref: getRef('chats_list') })
|
||||
})
|
||||
renderElem(getRef('chats_list'), html`${chats}`)
|
||||
@ -3400,6 +3427,7 @@
|
||||
function renderMessages(floID) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
messenger.getChat(floID).then(chat => {
|
||||
console.log(chat)
|
||||
if (chatLazyLoader) {
|
||||
chatLazyLoader.update(Object.values(chat))
|
||||
} else {
|
||||
@ -3431,12 +3459,19 @@
|
||||
// restore typed message if any
|
||||
getRef('type_message').value = floGlobals.typedMessages[floID] || ''
|
||||
activeChat.floID = floID
|
||||
activeChat.isGroup = messenger.groups.hasOwnProperty(floID)
|
||||
activeChat.type = getFloIdType(floID)
|
||||
updateChatHeaderName(getContactName(floID));
|
||||
if (activeChat.isGroup) {
|
||||
getRef("receiver_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> `
|
||||
const chatCard = getChatCard(floID);
|
||||
if (chatCard) {
|
||||
getRef("receiver_initial").innerHTML = chatCard.querySelector('.initial').innerHTML;
|
||||
} else {
|
||||
getRef("receiver_initial").textContent = getContactName(floID).charAt(0);
|
||||
if (activeChat.type === 'group') {
|
||||
getRef("receiver_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> `
|
||||
} else if (activeChat.type === 'pipeline') {
|
||||
getRef("receiver_initial").innerHTML = `<svg class="icon group-icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/></g><g><g><path d="M6,15c1.1,0,2,0.9,2,2s-0.9,2-2,2s-2-0.9-2-2S4.9,15,6,15 M6,13c-2.2,0-4,1.8-4,4s1.8,4,4,4s4-1.8,4-4S8.2,13,6,13z M12,5 c1.1,0,2,0.9,2,2s-0.9,2-2,2s-2-0.9-2-2S10.9,5,12,5 M12,3C9.8,3,8,4.8,8,7s1.8,4,4,4s4-1.8,4-4S14.2,3,12,3z M18,15 c1.1,0,2,0.9,2,2s-0.9,2-2,2s-2-0.9-2-2S16.9,15,18,15 M18,13c-2.2,0-4,1.8-4,4s1.8,4,4,4s4-1.8,4-4S20.2,13,18,13z"/></g></g></svg>`
|
||||
} else {
|
||||
getRef("receiver_initial").textContent = getContactName(floID).charAt(0);
|
||||
}
|
||||
}
|
||||
getRef("receiver_initial").setAttribute('style', `--contact-color: var(${contactColor(floID)})`)
|
||||
messenger.removeMark(floID, "unread");
|
||||
@ -3445,8 +3480,8 @@
|
||||
getRef('scroll_to_bottom').classList.remove('no-transformations')
|
||||
}
|
||||
renderMessages(floID).then(() => {
|
||||
if (!floGlobals.pubKeys[floID] && !activeChat.isGroup) {
|
||||
getRef('messages_container').prepend(html.node`<strong id="warn_no_encryption">Converstion is not encrypted until receiver replies</strong>`)
|
||||
if (!floGlobals.pubKeys[floID] && activeChat.type === 'plain') {
|
||||
getRef('messages_container').prepend(html.node`<strong id="warn_no_encryption" class="event-card">Converstion is not encrypted until receiver replies</strong>`)
|
||||
floGlobals.checkEncryption[floID] = true
|
||||
}
|
||||
resolve()
|
||||
@ -3689,7 +3724,7 @@
|
||||
}
|
||||
|
||||
function getChatCard(floID) {
|
||||
return getRef('chats_list').querySelector(`.chat[data-flo-id="${floID}"], .group[data-flo-id="${floID}"]`)
|
||||
return getRef('chats_list').querySelector(`[data-flo-id="${floID}"]`)
|
||||
}
|
||||
|
||||
function addAsContact() {
|
||||
@ -4017,16 +4052,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
getRef('select_multisig_list').addEventListener('change', e => {
|
||||
getRef('selected_multisig').textContent = e.target.value
|
||||
delegate(getRef('select_multisig_list'), 'click', '.multisig-option', e => {
|
||||
getRef('selected_multisig').textContent = e.delegateTarget.querySelector('input').value;
|
||||
getRef('selected_multisig__balance').textContent = e.delegateTarget.querySelector('.multisig-option__balance').textContent;
|
||||
setTimeout(() => {
|
||||
showChildElement('multisig_process', 1, { entry: slideInLeft, exit: slideOutLeft }).then(() => {
|
||||
getRef('send_tx').querySelector('sm-input').focusIn()
|
||||
getRef('enter_receiver_button').classList.remove('hidden')
|
||||
})
|
||||
}, 300);
|
||||
}, 200);
|
||||
})
|
||||
|
||||
const txParticipantsObserver = new MutationObserver(mutations => {
|
||||
mutations.forEach(mutation => {
|
||||
if (mutation.type === 'childList') {
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
(function(EXPORTS) { //btcOperator v1.0.8
|
||||
(function (EXPORTS) { //btcOperator v1.0.8
|
||||
/* BTC Crypto and API Operator */
|
||||
const btcOperator = EXPORTS;
|
||||
|
||||
//This library uses API provided by chain.so (https://chain.so/)
|
||||
const URL = "https://chain.so/api/v2/";
|
||||
|
||||
const fetch_api = btcOperator.fetch = function(api) {
|
||||
const fetch_api = btcOperator.fetch = function (api) {
|
||||
return new Promise((resolve, reject) => {
|
||||
console.debug(URL + api);
|
||||
fetch(URL + api).then(response => {
|
||||
@ -23,8 +23,8 @@
|
||||
fetch('https://api.blockchain.info/mempool/fees').then(response => {
|
||||
if (response.ok)
|
||||
response.json()
|
||||
.then(result => resolve(result.regular))
|
||||
.catch(error => reject(error));
|
||||
.then(result => resolve(result.regular))
|
||||
.catch(error => reject(error));
|
||||
else
|
||||
reject(response);
|
||||
}).catch(error => reject(error))
|
||||
@ -69,7 +69,7 @@
|
||||
|
||||
coinjs.compressed = true;
|
||||
|
||||
const verifyKey = btcOperator.verifyKey = function(addr, key) {
|
||||
const verifyKey = btcOperator.verifyKey = function (addr, key) {
|
||||
if (!addr || !key)
|
||||
return undefined;
|
||||
switch (coinjs.addressDecode(addr).type) {
|
||||
@ -84,7 +84,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
const validateAddress = btcOperator.validateAddress = function(addr) {
|
||||
const validateAddress = btcOperator.validateAddress = function (addr) {
|
||||
if (!addr)
|
||||
return undefined;
|
||||
let type = coinjs.addressDecode(addr).type;
|
||||
@ -94,7 +94,7 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
btcOperator.multiSigAddress = function(pubKeys, minRequired) {
|
||||
btcOperator.multiSigAddress = function (pubKeys, minRequired) {
|
||||
if (!Array.isArray(pubKeys))
|
||||
throw "pubKeys must be an array of public keys";
|
||||
else if (pubKeys.length < minRequired)
|
||||
@ -105,7 +105,7 @@
|
||||
//convert from one blockchain to another blockchain (target version)
|
||||
btcOperator.convert = {};
|
||||
|
||||
btcOperator.convert.wif = function(source_wif, target_version = coinjs.priv) {
|
||||
btcOperator.convert.wif = function (source_wif, target_version = coinjs.priv) {
|
||||
let keyHex = decodeLegacy(source_wif).hex;
|
||||
if (!keyHex || keyHex.length < 66 || !/01$/.test(keyHex))
|
||||
return null;
|
||||
@ -113,7 +113,7 @@
|
||||
return encodeLegacy(keyHex, target_version);
|
||||
}
|
||||
|
||||
btcOperator.convert.legacy2legacy = function(source_addr, target_version = coinjs.pub) {
|
||||
btcOperator.convert.legacy2legacy = function (source_addr, target_version = coinjs.pub) {
|
||||
let rawHex = decodeLegacy(source_addr).hex;
|
||||
if (!rawHex)
|
||||
return null;
|
||||
@ -121,7 +121,7 @@
|
||||
return encodeLegacy(rawHex, target_version);
|
||||
}
|
||||
|
||||
btcOperator.convert.legacy2bech = function(source_addr, target_version = coinjs.bech32.version, target_hrp = coinjs.bech32.hrp) {
|
||||
btcOperator.convert.legacy2bech = function (source_addr, target_version = coinjs.bech32.version, target_hrp = coinjs.bech32.hrp) {
|
||||
let rawHex = decodeLegacy(source_addr).hex;
|
||||
if (!rawHex)
|
||||
return null;
|
||||
@ -129,7 +129,7 @@
|
||||
return encodeBech32(rawHex, target_version, target_hrp);
|
||||
}
|
||||
|
||||
btcOperator.convert.bech2bech = function(source_addr, target_version = coinjs.bech32.version, target_hrp = coinjs.bech32.hrp) {
|
||||
btcOperator.convert.bech2bech = function (source_addr, target_version = coinjs.bech32.version, target_hrp = coinjs.bech32.hrp) {
|
||||
let rawHex = decodeBech32(source_addr).hex;
|
||||
if (!rawHex)
|
||||
return null;
|
||||
@ -137,7 +137,7 @@
|
||||
return encodeBech32(rawHex, target_version, target_hrp);
|
||||
}
|
||||
|
||||
btcOperator.convert.bech2legacy = function(source_addr, target_version = coinjs.pub) {
|
||||
btcOperator.convert.bech2legacy = function (source_addr, target_version = coinjs.pub) {
|
||||
let rawHex = decodeBech32(source_addr).hex;
|
||||
if (!rawHex)
|
||||
return null;
|
||||
@ -319,7 +319,7 @@
|
||||
script = Crypto.util.bytesToHex(s.buffer);
|
||||
} else //redeemScript for multisig
|
||||
script = rs;
|
||||
tx.addinput(utxos[i].txid, utxos[i].output_no, script, 0xfffffffd /*sequence*/ ); //0xfffffffd for Replace-by-fee
|
||||
tx.addinput(utxos[i].txid, utxos[i].output_no, script, 0xfffffffd /*sequence*/); //0xfffffffd for Replace-by-fee
|
||||
}
|
||||
addUTXOs(tx, senders, redeemScripts, required_amount, n + 1)
|
||||
.then(result => resolve(result))
|
||||
@ -373,7 +373,7 @@
|
||||
current_value.add(new BigInteger('' + edit_value)) : parseInt(current_value + edit_value);
|
||||
}
|
||||
|
||||
btcOperator.sendTx = function(senders, privkeys, receivers, amounts, fee, change_addr = null) {
|
||||
btcOperator.sendTx = function (senders, privkeys, receivers, amounts, fee, change_addr = null) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
({
|
||||
@ -404,7 +404,7 @@
|
||||
//create transaction
|
||||
createTransaction(senders, redeemScripts, receivers, amounts, fee, change_addr || senders[0]).then(tx => {
|
||||
console.debug("Unsigned:", tx.serialize());
|
||||
new Set(wif_keys).forEach(key => console.debug("Signing key:", key, tx.sign(key, 1 /*sighashtype*/ ))); //Sign the tx using private key WIF
|
||||
new Set(wif_keys).forEach(key => console.debug("Signing key:", key, tx.sign(key, 1 /*sighashtype*/))); //Sign the tx using private key WIF
|
||||
console.debug("Signed:", tx.serialize());
|
||||
debugger;
|
||||
broadcast(tx.serialize())
|
||||
@ -414,7 +414,7 @@
|
||||
})
|
||||
}
|
||||
|
||||
btcOperator.createTx = function(senders, receivers, amounts, fee = null, change_addr = null) {
|
||||
btcOperator.createTx = function (senders, receivers, amounts, fee = null, change_addr = null) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
({
|
||||
@ -441,7 +441,7 @@
|
||||
})
|
||||
}
|
||||
|
||||
btcOperator.createMultiSigTx = function(sender, redeemScript, receivers, amounts, fee) {
|
||||
btcOperator.createMultiSigTx = function (sender, redeemScript, receivers, amounts, fee) {
|
||||
return new Promise((resolve, reject) => {
|
||||
//validate tx parameters
|
||||
if (validateAddress(sender) !== "multisig")
|
||||
@ -483,7 +483,7 @@
|
||||
return tx;
|
||||
}
|
||||
|
||||
btcOperator.signTx = function(tx, privkeys, sighashtype = 1) {
|
||||
btcOperator.signTx = function (tx, privkeys, sighashtype = 1) {
|
||||
tx = deserializeTx(tx);
|
||||
if (!Array.isArray(privkeys))
|
||||
privkeys = [privkeys];
|
||||
@ -494,7 +494,7 @@
|
||||
return tx.serialize();
|
||||
}
|
||||
|
||||
btcOperator.checkSigned = function(tx, bool = true) {
|
||||
btcOperator.checkSigned = function (tx, bool = true) {
|
||||
tx = deserializeTx(tx);
|
||||
let n = [];
|
||||
for (let i in tx.ins) {
|
||||
@ -519,7 +519,7 @@
|
||||
return bool ? !(n.filter(x => x !== true).length) : n;
|
||||
}
|
||||
|
||||
btcOperator.checkIfSameTx = function(tx1, tx2) {
|
||||
btcOperator.checkIfSameTx = function (tx1, tx2) {
|
||||
tx1 = deserializeTx(tx1);
|
||||
tx2 = deserializeTx(tx2);
|
||||
if (tx1.ins.length !== tx2.ins.length || tx1.outs.length !== tx2.outs.length)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user