feat (user): added delete option for DMs and groups

feat (user): Notification dot over scroll to bottom button when new message comes in

feat (user): added notification sound for messages
This commit is contained in:
sairaj mote 2021-01-23 22:38:27 +05:30
parent 0ef7311a8e
commit 04df52c35f
4 changed files with 193 additions and 78 deletions

View File

@ -677,6 +677,12 @@ sm-button[variant=primary] .icon {
margin: 1rem 0;
justify-self: center;
align-self: center;
text-align: center;
}
.group-event-card {
font-size: 0.8rem;
font-weight: 400;
}
#warn_no_encryption {
@ -1122,6 +1128,9 @@ sm-button[variant=primary] .icon {
font-size: 0.9rem;
margin-top: 0.5rem;
}
#chat_details_panel .copy {
font-weight: 500;
}
#chat .message {
position: relative;
@ -1256,19 +1265,33 @@ sm-button[variant=primary] .icon {
#scroll_to_bottom {
position: absolute;
display: flex;
right: 0;
bottom: 4rem;
width: 2.6rem;
height: 2.6rem;
padding: 0.9rem;
border-radius: 4rem;
z-index: 1;
aspect-ratio: 1/1;
margin: 1.5rem;
stroke-width: 8;
cursor: pointer;
transform: scale(0);
transition: transform 0.3s;
}
#scroll_to_bottom.new-message::after {
position: absolute;
content: "";
top: 0;
right: 0;
z-index: 2;
padding: 0.5rem;
border-radius: 50%;
background: #00E676;
}
#scroll_to_bottom .icon {
width: 2.6rem;
height: 2.6rem;
padding: 0.9rem;
stroke-width: 8;
}
#chat_footer #emoji_toggle {
align-self: center;
@ -1555,7 +1578,7 @@ sm-panel {
}
#main_navbar {
transform: translateX(-100%);
transform: translateX(-110%);
transition: transform 0.3s;
z-index: 4;
box-shadow: 0 0 1rem rgba(0, 0, 0, 0.3);
@ -1597,18 +1620,6 @@ sm-panel {
}
}
@media only screen and (min-width: 640px) {
::-webkit-scrollbar {
width: 0.5rem;
}
::-webkit-scrollbar-thumb {
background: rgba(var(--text-color), 0.3);
border-radius: 1rem;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(var(--text-color), 0.5);
}
.hide-on-desktop {
display: none !important;
}
@ -1650,11 +1661,13 @@ sm-panel {
width: auto;
padding-bottom: 0.5rem;
background: rgba(var(--text-color), 0.06);
margin: 0.5rem;
border-radius: 0.8rem;
}
#main_navbar .logo-section {
display: flex;
justify-content: center;
margin: 1.5rem 0;
margin: 1rem 0 2rem 0;
}
#main_navbar .logo-section .main-logo {
margin: 0;
@ -1697,14 +1710,11 @@ sm-panel {
#chat_page, #mail_page {
grid-template-columns: 20rem 1fr;
box-shadow: 0 0 1rem rgba(0, 0, 0, 0.1);
z-index: 1;
}
#settings_page {
display: grid;
height: 100vh;
box-shadow: 0 0 1rem rgba(0, 0, 0, 0.1);
grid-template-columns: 14rem 1fr;
}
#settings_page sm-button {
@ -1751,6 +1761,9 @@ sm-panel {
#chat .active {
background: rgba(var(--text-color), 0.1);
}
#chat #messages_container {
padding: 1rem 5rem;
}
.contact.active,
.mail-card.active {
@ -1768,6 +1781,18 @@ sm-panel {
}
}
@media (hover: hover) {
::-webkit-scrollbar {
width: 0.5rem;
}
::-webkit-scrollbar-thumb {
background: rgba(var(--text-color), 0.3);
border-radius: 1rem;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(var(--text-color), 0.5);
}
.contact:hover, .mail-card:hover, .navbar-item:hover {
background: rgba(var(--text-color), 0.06);
cursor: pointer;

2
css/main.min.css vendored

File diff suppressed because one or more lines are too long

View File

@ -629,6 +629,11 @@ sm-button[variant="primary"]{
margin: 1rem 0;
justify-self: center;
align-self: center;
text-align: center;
}
.group-event-card{
font-size: 0.8rem;
font-weight: 400;
}
#warn_no_encryption{
background: rgb(255, 253, 141);
@ -1058,6 +1063,9 @@ sm-button[variant="primary"]{
margin-top: 0.5rem;
}
}
.copy{
font-weight: 500;
}
}
#chat{
.message{
@ -1192,18 +1200,32 @@ sm-button[variant="primary"]{
}
#scroll_to_bottom{
position: absolute;
display: flex;
right: 0;
bottom: 4rem;
width: 2.6rem;
height: 2.6rem;
padding: 0.9rem;
border-radius: 4rem;
z-index: 1;
aspect-ratio: 1/1;
margin: 1.5rem;
stroke-width: 8;
cursor: pointer;
transform: scale(0);
transition: transform 0.3s;
&.new-message::after{
position: absolute;
content: '';
top: 0;
right: 0;
z-index: 2;
padding: 0.5rem;
border-radius: 50%;
background: #00E676;
}
.icon{
width: 2.6rem;
height: 2.6rem;
padding: 0.9rem;
stroke-width: 8;
}
}
#chat_footer{
#emoji_toggle{
@ -1475,7 +1497,7 @@ sm-panel{
grid-area: illustration;
}
#main_navbar{
transform: translateX(-100%);
transform: translateX(-110%);
transition: transform 0.3s;
z-index: 4;
box-shadow: 0 0 1rem rgba(0, 0, 0, 0.3);
@ -1515,17 +1537,6 @@ sm-panel{
}
}
@media only screen and (min-width: 640px){
::-webkit-scrollbar{
width: 0.5rem;
}
::-webkit-scrollbar-thumb{
background: rgba(var(--text-color), 0.3);
border-radius: 1rem;
&:hover{
background: rgba(var(--text-color), 0.5);
}
}
.hide-on-desktop{
display: none !important;
}
@ -1564,10 +1575,12 @@ sm-panel{
width: auto;
padding-bottom: 0.5rem;
background: rgba(var(--text-color), 0.06);
margin: 0.5rem;
border-radius: 0.8rem;
.logo-section{
display: flex;
justify-content: center;
margin: 1.5rem 0;
margin: 1rem 0 2rem 0;
.main-logo{
margin: 0;
}
@ -1607,13 +1620,10 @@ sm-panel{
}
#chat_page, #mail_page{
grid-template-columns: 20rem 1fr;
box-shadow: 0 0 1rem rgba(0, 0, 0, 0.1);
z-index: 1;
}
#settings_page{
display: grid;
height: 100vh;
box-shadow: 0 0 1rem rgba(0, 0, 0, 0.1);
grid-template-columns: 14rem 1fr;
sm-button{
width: max-content;
@ -1656,6 +1666,9 @@ sm-panel{
.active{
background: rgba(var(--text-color), 0.1);
}
#messages_container{
padding: 1rem 5rem;
}
}
.contact.active,
.mail-card.active{
@ -1671,6 +1684,17 @@ sm-panel{
}
}
@media (hover: hover){
::-webkit-scrollbar{
width: 0.5rem;
}
::-webkit-scrollbar-thumb{
background: rgba(var(--text-color), 0.3);
border-radius: 1rem;
&:hover{
background: rgba(var(--text-color), 0.5);
}
}
.contact:hover, .mail-card:hover, .navbar-item:hover{
background: rgba(var(--text-color), 0.06);
cursor: pointer;

View File

@ -225,12 +225,12 @@
<path
d="M46.73,14.81l7,7,7.65-7.6A7.15,7.15,0,0,0,61.39,4L60.11,2.77a7.23,7.23,0,0,0-10.19,0L3.87,48.57a5,5,0,0,0-1.39,2.6L.53,61.27a1.74,1.74,0,0,0,2,2l10.15-1.94A5.06,5.06,0,0,0,15.34,60L49.6,25.9" />
</svg>
<!--<svg id="delete_person" onclick="deletePerson()" class="icon" viewBox="0 0 64 64" title="Remove">
<svg id="delete_person" onclick="deleteChat()" class="icon" viewBox="0 0 64 64" title="Remove">
<title>remove</title>
<line x1="4" y1="6.3" x2="60" y2="6.3" />
<path d="M53.5,20.5v38.9c0,2.3-1.8,4.1-4.1,4.1h0H14.6c-2.3,0-4.1-1.8-4.1-4.1c0,0,0,0,0,0V20.5" />
<path d="M22.7,6.6V3.8c0-1.8,1.5-3.3,3.3-3.3h11.4c1.8,0,3.3,1.5,3.3,3.3v2.8" />
</svg>-->
</svg>
</div>
</div>
<h5>FLO ID</h5>
@ -444,10 +444,12 @@
<h5 id="warn_no_encryption">Messages are not encrypted until receiver replies</h5>
<section id="messages_container" class="flex direction-column">
</section>
<svg id="scroll_to_bottom" onclick="scrollToBottom()" class="icon" viewBox="0 0 64 64">
<title></title>
<polyline points="63.65 15.99 32 47.66 0.35 15.99"/>
</svg>
<div id="scroll_to_bottom" onclick="scrollToBottom()">
<svg class="icon" viewBox="0 0 64 64">
<title></title>
<polyline points="63.65 15.99 32 47.66 0.35 15.99"/>
</svg>
</div>
<footer id="chat_footer" class="grid">
<div id="emoji_picker" class="hide-completely"></div>
<div class="flex">
@ -472,6 +474,17 @@
<h3 id="chat_name"></h3>
<p id="last_interaction_time"></p>
</div>
<div id="chat_flo_id_card" class="card">
<h4 id="chat_type"></h4>
<div class="copy-row grid">
<h4 id="chat_flo_id" class="copy"></h4>
<svg class="icon" onclick="copyToClipboard(this, 'Copied FLO ID')" viewBox="0 0 64 64">
<title>Copy</title>
<rect x="16" y="16" width="48" height="48" rx="6" />
<path d="M.5,47.52V6.5a6,6,0,0,1,6-6h41" />
</svg>
</div>
</div>
<div id="group_description_card" class="card hide-completely">
<h4>Group description</h4>
<p id="group_description"></p>
@ -1199,7 +1212,6 @@
// render elements
const render = {
mailCard(floID, ref, subject, timestamp, content, markUnread){
console.log(timestamp)
let card = getRef('mail_card_template').content.cloneNode(true),
cardContainer = card.firstElementChild
let mailSummery = content.split(' ')
@ -1305,8 +1317,11 @@
else if(type === 'group'){
lastMessage.time = floGlobals.groups[floID].created
}
let lastText = document.createElement('p')
lastText.textContent = lastMessage.message
lastText.classList.add('last-message')
cardContainer.append(lastText)
cardContainer.innerHTML += `
<p class="last-message">${lastMessage.message}</p>
<h5 class="time">${getFormatedTime(lastMessage.time, true)}</h5>
<svg class="icon menu" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<circle cx="5.59" cy="32" r="5.59"/>
@ -1341,24 +1356,24 @@
}
if(message){
if(updateChatCard && activeChat.isGroup && sender === myFloID) return
cardContainer.id = `${floID}_${timestamp}`
if(unconfirmed)
cardContainer.classList.add('unconfirmed')
cardContainer.classList.add(category)
if(sender && sender !== myFloID){
let senderName = document.createElement('div')
senderName.classList.add('sender-name')
senderName.style.color = contactColor(sender)
senderName.textContent = floGlobals.contacts[sender] || sender
cardContainer.prepend(senderName)
messageContent = cardContainer.children[1]
messageTime = cardContainer.children[2]
if(sender){
if(sender !== myFloID && lastSender !== sender){
let senderName = document.createElement('div')
senderName.classList.add('sender-name')
senderName.style.color = contactColor(sender)
senderName.textContent = floGlobals.contacts[sender] || sender
cardContainer.prepend(senderName)
messageContent = cardContainer.children[1]
messageTime = cardContainer.children[2]
}
lastSender = sender
}
if(isValidUrl(message)){
@ -1385,6 +1400,7 @@
messageTime.textContent = finalHours
if(currentFloID !== floID){
currentDate = null
lastSender = null
currentFloID = floID
renderedDates.clear()
}
@ -1404,6 +1420,7 @@
}
else if(admin){
if(newMembers.length){
const cards = document.createDocumentFragment()
const {admin} = floGlobals.groups[groupID]
newMembers.forEach(member => {
let eventCard = document.createElement('p')
@ -1414,14 +1431,21 @@
else
eventMessage = `${floGlobals.contacts[admin] || admin} added ${member}`
eventCard.textContent = eventMessage
return eventCard
cards.append(eventCard)
})
return cards
}
else if(name){
let eventCard = document.createElement('p')
eventCard.classList.add('group-event-card')
eventCard.textContent = `Changed group name to '${name}'`
return eventCard
}
}
},
}
let currentDate, currentFloID, renderedDates = new Map()
let currentDate, currentFloID, renderedDates = new Map(), lastSender
const isValidUrl = (url) => {
try {
@ -1457,7 +1481,6 @@
function renderDirectUI(data) {
console.log('called DM')
renderMessages(data.messages, {updateChatCard: true});
renderMailList(data.mails)
//let order = Object.keys(data.messages).map(a => a.split('_')).sort((a, b) => a[0] - b[0]).map(a => a[1])
@ -1471,15 +1494,15 @@
}
function renderGroupUI(data){
console.log('called grouu')
renderMessages(data.messages, {updateChatCard: true});
}
window.addEventListener('focus', e => {
if(activeChat.chatCard && activeChat.chatCard.classList.contains('active'))
setTimeout(() => {
activeChat.chatCard.classList.remove('unread')
}, 2000)
if(activeChat.chatCard){
if(!chatScrollInfo.isScrolledUp){
scrollToBottom()
}
}
})
window.addEventListener('blur', e => {
console.log('blured')
@ -1547,12 +1570,12 @@
chatScrollInfo['scrollTop'] = this.scrollTop
chatScrollInfo['scrollheight'] = this.scrollHeight
if((this.scrollHeight > this.clientHeight) && (this.scrollHeight - this.clientHeight - this.scrollTop >= 100)){
chatScrollInfo['scrolledUp'] = true
chatScrollInfo['isScrolledUp'] = true
getRef('scroll_to_bottom').classList.add('no-transformations')
}
else{
chatScrollInfo['scrolledUp'] = false
getRef('scroll_to_bottom').classList.remove('no-transformations')
chatScrollInfo['isScrolledUp'] = false
getRef('scroll_to_bottom').classList.remove('no-transformations', 'new-message')
}
}, {passive: true})
@ -1648,7 +1671,7 @@
getRef('emoji_toggle').classList.remove('active')
getRef('emoji_picker').classList.add('hide-completely')
getRef('scroll_to_bottom').setAttribute('style', `top: calc(${getRef('messages_container').getBoundingClientRect().height}px - 1.5rem`)
if(!chatScrollInfo.scrolledUp)
if(!chatScrollInfo.isScrolledUp)
scrollToBottom()
}
})
@ -1683,6 +1706,7 @@
createRipple(e, contact)
contact.classList.remove('unread')
if(activeChat['chatCard'] === contact && window.innerWidth > 640) return
showChatDetails(false)
document.title = `FLO Messenger`
getRef('chat').classList.remove('hide-completely')
viewConversation(contact)
@ -1879,7 +1903,7 @@
isEmojiPickerOpen = false
else
isEmojiPickerOpen = true
if(!chatScrollInfo.scrolledUp)
if(!chatScrollInfo.isScrolledUp)
scrollToBottom()
}
@ -2219,6 +2243,11 @@
}
function scrollToBottom(){
if(activeChat.chatCard){
messenger.removeMark(activeChat.receiver, 'unread')
activeChat.chatCard.classList.remove('unread')
}
getRef('scroll_to_bottom').classList.remove('new-message')
getRef('messages_container').scrollTo(0, getRef('messages_container').scrollHeight)
}
@ -2253,6 +2282,7 @@
let {floID, groupID, sender, message, time, category} = messages[i]
//Stops message from rendering in wrong chat window
if(activeChat['receiver'] && ( activeChat['receiver'] === floID || activeChat['receiver'] === groupID)){
if(updateChatCard && activeChat.isGroup && message && sender === myFloID) return
frag.append(render.messageBubble({...messages[i], updateChatCard}))
}
const contact = getRef('chat_container').querySelector(`.chat[flo-id='${floID}']`)
@ -2284,6 +2314,24 @@
finalMessage = message
chatCard.querySelector('.last-message').textContent = finalMessage
chatCard.querySelector('.time').textContent = getFormatedTime(time, true)
if(activeChat.receiver === (floID || groupID)){
if(chatScrollInfo.isScrolledUp)
getRef('scroll_to_bottom').classList.add('new-message')
else{
if(document.hasFocus()){
messenger.removeMark((floID || groupID), 'unread')
setTimeout(() => {
document.title = 'FLO Messenger'
activeChat.chatCard.classList.remove('unread')
}, 1000);
}
}
}
if(!document.hasFocus() && navigator.onLine) {
getRef('notification_sound').currentTime = 0;
getRef('notification_sound').play();
}
}
}
}
@ -2291,11 +2339,12 @@
if(!lazyLoad && !reRender){
endIndex = messages.length
getRef('messages_container').append(frag)
if(!chatScrollInfo['scrolledUp'])
if(!chatScrollInfo['isScrolledUp'])
scrollToBottom()
}
if(reRender || lazyLoad){
currentDate = null
lastSender = null
chatScrollInfo['scrollTop'] = getRef('messages_container').scrollTop
chatScrollInfo['scrollHeight'] = getRef('messages_container').scrollHeight
getRef('messages_container').prepend(frag)
@ -2335,7 +2384,9 @@
name = contact.getAttribute('name'),
textColor = contact.getAttribute('text-color'),
backgroundColor = contact.getAttribute('background-color')
activeChat['receiver'] = floID
getRef("chat_flo_id").textContent = floID
activeChat['isGroup'] = floGlobals.groups[floID] ? true : false
if(activeChat.isGroup){
getRef("receiver_initial").innerHTML = `
@ -2348,9 +2399,10 @@
getRef("chat_name").textContent = floGlobals.groups[floID].name;
getRef("last_interaction_time").textContent = `Created ${getFormatedTime(floGlobals.groups[floID].created)}`;
getRef("chat_type").textContent = `Group FLO ID`;
getRef('group_members_list').innerHTML = ''
floGlobals.groups[floID].members.forEach(member => {
console.log(render.contactCard(member, floGlobals.contacts[member] || '', 'contact', {contactOnly: true}))
frag.append(render.contactCard(member, floGlobals.contacts[member] || '', 'contact', {contactOnly: true}))
})
getRef('group_members_list').append(frag)
@ -2366,6 +2418,8 @@
getRef("chat_name").textContent = floGlobals.contacts[floID] || floID || ' ';
getRef("last_interaction_time").textContent = ``;
getRef("chat_type").textContent = `FLO ID`;
getRef("group_description_card").classList.add('hide-completely')
getRef("group_members_card").classList.add('hide-completely')
}
@ -2378,7 +2432,7 @@
renderMessages(await messenger.getChat(floID),{markUnread: false, reRender: true})
messenger.removeMark(floID, "unread");
if(this.scrollHeight <= this.clientHeight){
chatScrollInfo['scrolledUp'] = false
chatScrollInfo['isScrolledUp'] = false
getRef('scroll_to_bottom').classList.remove('no-transformations')
}
}
@ -2636,6 +2690,18 @@
}
}
async function deleteChat(){
if(await confirmation('Delete chat?', `Are you sure to delete this chat?`, 'No', "Yes")){
messenger.rmChat(clickedContact.floID).then(result => {
clickedContact.card.remove()
clickedContact.card = ''
hidePopup()
getRef('chat').classList.add('hide-completely')
notify('Chat deleted', 'success')
})
}
}
</script>
<script id="init_lib" version="1.0.1">