Added messaging feature
Now users can send and receive messages directly. The messages are stored only in the browser IDB. The messages are encrypted and signed by sender.
This commit is contained in:
parent
a1a9e03d17
commit
cd31d9c267
@ -111,7 +111,7 @@ var encrypt = {
|
||||
var senderPublicKeyString = {};
|
||||
senderDerivedKey = this.deriveSharedKeySender(
|
||||
receiverCompressedPublicKey, senderECKeyData.privateKey);
|
||||
console.log("senderDerivedKey", senderDerivedKey);
|
||||
//console.log("senderDerivedKey", senderDerivedKey);
|
||||
let senderKey = senderDerivedKey.XValue + senderDerivedKey.YValue;
|
||||
let secret = Crypto.AES.encrypt(data, senderKey);
|
||||
return {
|
||||
@ -136,7 +136,7 @@ var encrypt = {
|
||||
|
||||
receiverDerivedKey = this.deriveReceiverSharedKey(senderPublicKeyString,
|
||||
receiverECKeyData.privateKey);
|
||||
console.log("receiverDerivedKey", receiverDerivedKey);
|
||||
//console.log("receiverDerivedKey", receiverDerivedKey);
|
||||
|
||||
let receiverKey = receiverDerivedKey.XValue + receiverDerivedKey.YValue;
|
||||
let decryptMsg = Crypto.AES.decrypt(secret, receiverKey);
|
||||
@ -258,22 +258,6 @@ function logout(){
|
||||
location.reload();
|
||||
}
|
||||
|
||||
function listProfiles(){
|
||||
console.log("listProfiles");
|
||||
var profileList = document.getElementById("profileList");
|
||||
profileList.innerHTML = "";
|
||||
for (p in profiles){
|
||||
var element = document.createElement("div");
|
||||
element.setAttribute("class", "media");
|
||||
element.innerHTML = `<a href="profile.html?floID=${p}"><div class="media-body">
|
||||
<h5 class="media-heading">${profiles[p].name}</h5>
|
||||
<small>@${p}</small>
|
||||
</div></a>`
|
||||
profileList.appendChild(element);
|
||||
}
|
||||
//document.getElementById("profileInfo").style.display = "none";
|
||||
}
|
||||
|
||||
var supernodeKBucket;
|
||||
var superNodeList;
|
||||
/*Kademlia DHT K-bucket implementation as a binary tree.*/
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
<a href="profile.html"><span class="glyphicon glyphicon-user"></span> Profiles</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#"><span class="glyphicon glyphicon-envelope"></span> Messages</a>
|
||||
<a href="msg.html"><span class="glyphicon glyphicon-envelope"></span> Messages</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@ -49,27 +49,30 @@
|
||||
<div class="col-sm-3">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<a href="#"><img class="img-responsive" alt="" src="http://placehold.it/800x500"></a>
|
||||
<h5>
|
||||
<div id="profileName"></div>
|
||||
<small id="profileFloID"></small>
|
||||
</h5>
|
||||
<div class="row">
|
||||
<div class="col-xs-3">
|
||||
<h5>
|
||||
<small>TWEETS</small>
|
||||
<a href="#">-</a>
|
||||
</h5>
|
||||
<div class="col-xs-3">
|
||||
<h5>
|
||||
<small>TWEETS</small>
|
||||
<a href="#" id="tweetCount">-</a>
|
||||
</h5>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<h5>
|
||||
<small>FOLLOWING</small>
|
||||
<a href="#" id="followingCount">-</a>
|
||||
</h5>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<h5>
|
||||
<small>FOLLOWERS</small>
|
||||
<a href="#" id="followersCount">-</a>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<h5>
|
||||
<small>FOLLOWING</small>
|
||||
<a href="#">-</a>
|
||||
</h5>
|
||||
</div>
|
||||
<div class="col-xs-5">
|
||||
<h5>
|
||||
<small>FOLLOWERS</small>
|
||||
<a href="#">-</a>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -116,6 +116,11 @@ function getDatafromAPI(){
|
||||
var objectStore4 = db.createObjectStore("lastTweet");
|
||||
var objectStore5 = db.createObjectStore("followers");
|
||||
var objectStore6 = db.createObjectStore("following");
|
||||
var objectStore7 = event.target.result.createObjectStore("messages",{ keyPath: 'msgID' });
|
||||
objectStore7.createIndex('time', 'time', { unique: false });
|
||||
objectStore7.createIndex('text', 'text', { unique: false });
|
||||
objectStore7.createIndex('floID', 'floID', { unique: false });
|
||||
objectStore7.createIndex('type', 'type', { unique: false });
|
||||
};
|
||||
idb.onsuccess = function(event) {
|
||||
var db = event.target.result;
|
||||
@ -322,6 +327,10 @@ function initselfWebSocket(){
|
||||
db.close();
|
||||
};
|
||||
selfWebsocket.send(`U${data.floID}`);
|
||||
}else if(data.message && data.to == selfID){
|
||||
var msg = encrypt.decryptMessage(data.secret,data.pubVal)
|
||||
if(encrypt.verify(msg,data.sign,profiles[data.from].pubKey))
|
||||
storeMsg({time:data.time,floID:data.from,text:msg,type:'R'});
|
||||
}else if(data.fromSuperNode && following.includes(data.floID)){
|
||||
var tid = data.tid;
|
||||
data = JSON.parse(data.data);
|
||||
@ -370,6 +379,24 @@ function initselfWebSocket(){
|
||||
};
|
||||
}
|
||||
|
||||
function listProfiles(){
|
||||
console.log("listProfiles");
|
||||
document.getElementById("profileName").innerHTML=profiles[selfID].name;
|
||||
document.getElementById("profileFloID").innerHTML='@'+selfID;
|
||||
var profileList = document.getElementById("profileList");
|
||||
profileList.innerHTML = "";
|
||||
for (p in profiles){
|
||||
var element = document.createElement("div");
|
||||
element.setAttribute("class", "media");
|
||||
element.innerHTML = `<a href="profile.html?floID=${p}"><div class="media-body">
|
||||
<h5 class="media-heading">${profiles[p].name}</h5>
|
||||
<small>@${p}</small>
|
||||
</div></a>`
|
||||
profileList.appendChild(element);
|
||||
}
|
||||
//document.getElementById("profileInfo").style.display = "none";
|
||||
}
|
||||
|
||||
function postTweet(){
|
||||
var tweetBox = document.getElementById("tweetBox");
|
||||
var tweet = tweetBox.value;
|
||||
@ -403,6 +430,20 @@ function storeTweet(data,tid){
|
||||
};
|
||||
}
|
||||
|
||||
function storeMsg(data){
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = function(event) {
|
||||
console.log("Error in opening IndexedDB!");
|
||||
};
|
||||
idb.onsuccess = function(event) {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("messages", "readwrite").objectStore("messages");
|
||||
data.msgID = `${data.time}_${data.floID}`;
|
||||
obs.add(data);
|
||||
db.close();
|
||||
};
|
||||
}
|
||||
|
||||
function sendTweetToSuperNode(data,tid){
|
||||
kBucketObj.determineClosestSupernode(selfID).then(result=>{
|
||||
var superNodeWS = new WebSocket("ws://"+profiles[result[0].floID].onionAddr+"/ws");
|
||||
@ -480,7 +521,7 @@ function createTweetElement(floID,time,tweet){
|
||||
element.innerHTML = `
|
||||
<div class="media-body">
|
||||
<h4 class="media-heading">${profiles[floID].name} <small>@${floID}</small></h4>
|
||||
<p>${tweet}</p>
|
||||
<p>${tweet.replace(/\n/g, "<br/>")}</p>
|
||||
<ul class="nav nav-pills nav-pills-custom">
|
||||
<li><a href="#"><span class="glyphicon glyphicon-share-alt"></span></a></li>
|
||||
<li><a href="#"><span class="glyphicon glyphicon-retweet"></span></a></li>
|
||||
|
||||
123
app/web/msg.html
Normal file
123
app/web/msg.html
Normal file
@ -0,0 +1,123 @@
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>FLO Twitter</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<!-- Font Awesome File -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||
|
||||
<script type="text/javascript" src="registerID.js"></script>
|
||||
<script type="text/javascript" src="app.js"></script>
|
||||
<script type="text/javascript" src="msg.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body onload = "initMsgs();">
|
||||
|
||||
<div class="navbar navbar-default navbar-static-top">
|
||||
<div class="container">
|
||||
<div class="navbar-collapse navbar-collapse-1 collapse" aria-expanded="true">
|
||||
<ul class="nav navbar-nav">
|
||||
<li>
|
||||
<a href="home.html"><span class="glyphicon glyphicon-home"></span> Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="profile.html"><span class="glyphicon glyphicon-user"></span> Profiles</a>
|
||||
</li>
|
||||
<li class="active">
|
||||
<a href="msg.html"><span class="glyphicon glyphicon-envelope"></span> Messages</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="navbar-form navbar-right">
|
||||
<div class="form-group has-feedback">
|
||||
<input type="text" class="form-control-nav" id="search" aria-describedby="search1">
|
||||
<span class="glyphicon glyphicon-search form-control-feedback" aria-hidden="true"></span>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-default btn-sm" onclick="logout()">
|
||||
<span class="glyphicon glyphicon-log-out"> </span> Log out
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<h5>
|
||||
<div id="profileName"></div>
|
||||
<small id="profileFloID"></small>
|
||||
</h5>
|
||||
<div class="row">
|
||||
<div class="col-xs-3">
|
||||
<h5>
|
||||
<small>TWEETS</small>
|
||||
<a href="#" id="tweetCount">-</a>
|
||||
</h5>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<h5>
|
||||
<small>FOLLOWING</small>
|
||||
<a href="#" id="followingCount">-</a>
|
||||
</h5>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<h5>
|
||||
<small>FOLLOWERS</small>
|
||||
<a href="#" id="followersCount">-</a>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default panel-custom">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading">
|
||||
<div class="media">
|
||||
<div class="media-heading">
|
||||
<span id="recipient_floID">Select Contact<br/><small>@floID</small></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body" id="msgsContainer">
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<input class="form-control" rows="1" id="sendMsgInput" placeholder="Type message" autocomplete="off" ></input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3">
|
||||
|
||||
<div class="panel panel-default panel-custom">
|
||||
<div class="panel-footer">
|
||||
<h3 class="panel-title">
|
||||
Profiles
|
||||
</h3>
|
||||
</div>
|
||||
<div class="panel-body" id="profileList">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
210
app/web/msg.js
Normal file
210
app/web/msg.js
Normal file
@ -0,0 +1,210 @@
|
||||
var profiles;
|
||||
var receiverID,selfID,privKey;
|
||||
var selfwebsocket,receiverWebSocket,recStat;
|
||||
|
||||
function initMsgs(){
|
||||
if( sessionStorage.profiles === undefined || sessionStorage.privKey === undefined || sessionStorage.selfID === undefined || sessionStorage.serverPass === undefined){
|
||||
alert("Login credentials failed! Returning to home page!");
|
||||
window.location.href = "home.html";
|
||||
return;
|
||||
}
|
||||
profiles = JSON.parse(sessionStorage.profiles);
|
||||
console.log(profiles);
|
||||
privKey = encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.privKey));
|
||||
selfID = sessionStorage.selfID;
|
||||
superNodeList = JSON.parse(sessionStorage.superNodeList);
|
||||
kBucketObj.launchKBucket().then(function(result){
|
||||
console.log(result)
|
||||
initselfWebSocket();
|
||||
readMsgfromIDB().then(function(result){
|
||||
listProfiles();
|
||||
document.getElementById("sendMsgInput").addEventListener("keyup",function(event){
|
||||
if(event.keyCode === 13){
|
||||
event.preventDefault();
|
||||
sendMsg();
|
||||
}
|
||||
});
|
||||
}).catch(function(error){
|
||||
console.log(error);
|
||||
});
|
||||
}).catch(function(error){
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
function listProfiles(){
|
||||
console.log("listProfiles");
|
||||
document.getElementById("profileName").innerHTML=profiles[selfID].name;
|
||||
document.getElementById("profileFloID").innerHTML='@'+selfID;
|
||||
var profileList = document.getElementById("profileList");
|
||||
profileList.innerHTML = "";
|
||||
for (p in profiles){
|
||||
var element = document.createElement("div");
|
||||
element.setAttribute("class", "media");
|
||||
element.innerHTML = `<a href="javascript:changeReceiver('${p}');"><div class="media-body">
|
||||
<h5 class="media-heading">${profiles[p].name}</h5>
|
||||
<small>@${p}</small>
|
||||
</div></a>`
|
||||
profileList.appendChild(element);
|
||||
}
|
||||
}
|
||||
|
||||
function initselfWebSocket(){
|
||||
selfWebsocket = new WebSocket("ws://"+location.host+"/ws");
|
||||
selfWebsocket.onopen = function(evt){
|
||||
console.log("Connecting");
|
||||
var serverPass = encrypt.retrieveShamirSecret(JSON.parse(sessionStorage.serverPass));
|
||||
selfWebsocket.send("$"+serverPass);
|
||||
};
|
||||
selfWebsocket.onclose = function(evt){
|
||||
console.log("DISCONNECTED");
|
||||
};
|
||||
selfWebsocket.onmessage = function(evt){
|
||||
console.log(evt.data);
|
||||
if(evt.data[0] == '$')
|
||||
return;
|
||||
try{
|
||||
data = JSON.parse(evt.data);
|
||||
if(data.follow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onsuccess = function(event) {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("followers", "readwrite").objectStore("followers");
|
||||
obs.add(data.sign,data.floID);
|
||||
db.close();
|
||||
};
|
||||
selfWebsocket.send(`F${data.floID}-${data.sign}`);
|
||||
}else if(data.unfollow && encrypt.verify(selfID, data.sign, profiles[data.floID].pubKey)){
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onsuccess = function(event) {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("followers", "readwrite").objectStore("followers");
|
||||
obs.delete(data.floID);
|
||||
db.close();
|
||||
};
|
||||
selfWebsocket.send(`U${data.floID}`);
|
||||
}else if(data.message && data.to == selfID){
|
||||
var msg = encrypt.decryptMessage(data.secret,data.pubVal)
|
||||
if(encrypt.verify(msg,data.sign,profiles[data.from].pubKey)){
|
||||
createMsgElement(data.from,data.time,msg,'R')
|
||||
storeMsg({time:data.time,floID:data.from,text:msg,type:'R'});
|
||||
}
|
||||
}
|
||||
}catch(error){
|
||||
console.log(error.message)
|
||||
}
|
||||
};
|
||||
selfWebsocket.onerror = function(evt){
|
||||
console.log(evt);
|
||||
};
|
||||
}
|
||||
|
||||
function readMsgfromIDB(){
|
||||
return new Promise(
|
||||
function(resolve,reject){
|
||||
var disp = document.getElementById("msgsContainer");
|
||||
for(floID in profiles){
|
||||
var element = document.createElement('div');
|
||||
element.setAttribute("id", floID);
|
||||
element.style.display = 'none';
|
||||
disp.appendChild(element);
|
||||
}
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = function(event) {
|
||||
reject("Error in opening IndexedDB!");
|
||||
};
|
||||
idb.onsuccess = function(event) {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("messages", "readwrite").objectStore("messages");
|
||||
obs.openCursor().onsuccess = function(event) {
|
||||
var cursor = event.target.result;
|
||||
if(cursor) {
|
||||
createMsgElement(cursor.value.floID,cursor.value.time,cursor.value.text,cursor.value.type);
|
||||
cursor.continue();
|
||||
} else {
|
||||
console.log('Entries all displayed.');
|
||||
resolve("Read Msg from IDB");
|
||||
}
|
||||
};
|
||||
db.close();
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function changeReceiver(floID){
|
||||
try{
|
||||
if(receiverID !== undefined)
|
||||
document.getElementById(receiverID).style.display = 'none';
|
||||
if(receiverWebSocket !== undefined && receiverWebSocket.readyState === WebSocket.OPEN)
|
||||
receiverWebSocket.close();
|
||||
}catch(e){
|
||||
console.log(e);
|
||||
}
|
||||
console.log(floID);
|
||||
receiverID = floID;
|
||||
document.getElementById('recipient_floID').innerHTML = `${profiles[receiverID].name}<br><small>@${receiverID}<small>`;
|
||||
recStat = false;
|
||||
document.getElementById(receiverID).style.display = 'block';
|
||||
try{
|
||||
receiverWebSocket = new WebSocket("ws://"+profiles[receiverID].onionAddr+"/ws");
|
||||
receiverWebSocket.onopen = function(ev){ recStat = true; };
|
||||
receiverWebSocket.onerror = function(ev) { recStat = false;};
|
||||
receiverWebSocket.onclose = function(ev) { recStat = false; };
|
||||
}catch(e){
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
function sendMsg(){
|
||||
if(receiverID === undefined){
|
||||
alert("Select a contact and send message");
|
||||
return;
|
||||
}
|
||||
var inp = document.getElementById('sendMsgInput')
|
||||
var msg = inp.value
|
||||
inp.value = ""
|
||||
console.log(msg)
|
||||
var time = Date.now()
|
||||
var sign = encrypt.sign(msg,privKey)
|
||||
var msgEncrypt = encrypt.encryptMessage(msg,profiles[receiverID].pubKey)
|
||||
var data = JSON.stringify({message:true,from:selfID,to:receiverID,time:time,secret:msgEncrypt.secret,sign:sign,pubVal:msgEncrypt.senderPublicKeyString});
|
||||
|
||||
if(recStat)
|
||||
receiverWebSocket.send(data);
|
||||
else{
|
||||
var SNdata = JSON.stringify({viaSuperNodeMsg:true,from:selfID,to:receiverID,data:data})
|
||||
sendDataToSuperNode(receiverID,SNdata)
|
||||
}
|
||||
console.log(`sentMsg : ${data}`);
|
||||
createMsgElement(receiverID,time,msg,'S')
|
||||
storeMsg({time:time,floID:receiverID,text:msg,type:'S'});
|
||||
}
|
||||
|
||||
function createMsgElement(floID,time,msg,type){
|
||||
var msgField = document.getElementById(floID);
|
||||
var element = document.createElement("div");
|
||||
element.setAttribute("class", "media");
|
||||
element.innerHTML = `
|
||||
<div class="media-body">
|
||||
<div class="msg-${type}">
|
||||
<span class="message-text">${msg}</span><br/>
|
||||
<small class="timestamp pull-right">${getTime(time)}</small>
|
||||
</div>
|
||||
</div>`;
|
||||
msgField.appendChild(element);
|
||||
}
|
||||
|
||||
function storeMsg(data){
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = function(event) {
|
||||
console.log("Error in opening IndexedDB!");
|
||||
};
|
||||
idb.onsuccess = function(event) {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("messages", "readwrite").objectStore("messages");
|
||||
data.msgID = `${data.time}_${data.floID}`;
|
||||
obs.add(data);
|
||||
db.close();
|
||||
};
|
||||
}
|
||||
@ -27,7 +27,7 @@
|
||||
<a href="profile.html"><span class="glyphicon glyphicon-user"></span> Profiles</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#"><span class="glyphicon glyphicon-envelope"></span> Messages</a>
|
||||
<a href="msg.html"><span class="glyphicon glyphicon-envelope"></span> Messages</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@ -49,8 +49,7 @@
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body" id="profileInfo">
|
||||
<a href="#"><img class="img-responsive" alt="" src="http://placehold.it/800x500"></a>
|
||||
<div class="panel-body">
|
||||
<h5>
|
||||
<div id="profileName"></div>
|
||||
<small id="profileFloID"></small>
|
||||
|
||||
@ -98,6 +98,22 @@ function displayTweetFromIDB(floID){
|
||||
);
|
||||
}
|
||||
|
||||
function listProfiles(){
|
||||
console.log("listProfiles");
|
||||
var profileList = document.getElementById("profileList");
|
||||
profileList.innerHTML = "";
|
||||
for (p in profiles){
|
||||
var element = document.createElement("div");
|
||||
element.setAttribute("class", "media");
|
||||
element.innerHTML = `<a href="profile.html?floID=${p}"><div class="media-body">
|
||||
<h5 class="media-heading">${profiles[p].name}</h5>
|
||||
<small>@${p}</small>
|
||||
</div></a>`
|
||||
profileList.appendChild(element);
|
||||
}
|
||||
//document.getElementById("profileInfo").style.display = "none";
|
||||
}
|
||||
|
||||
function createTweetElement(floID,time,tweet){
|
||||
var tweetDisplay = document.getElementById("profileBody");
|
||||
var element = document.createElement("div");
|
||||
@ -105,7 +121,7 @@ function createTweetElement(floID,time,tweet){
|
||||
element.innerHTML = `
|
||||
<div class="media-body">
|
||||
<h4 class="media-heading">${profiles[floID].name} <small>@${floID}</small></h4>
|
||||
<p>${tweet}</p>
|
||||
<span>${tweet}</span>
|
||||
<ul class="nav nav-pills nav-pills-custom">
|
||||
<li><a href="#"><span class="glyphicon glyphicon-share-alt"></span></a></li>
|
||||
<li><a href="#"><span class="glyphicon glyphicon-retweet"></span></a></li>
|
||||
@ -164,6 +180,20 @@ function storeTweet(data,id){
|
||||
};
|
||||
}
|
||||
|
||||
function storeMsg(data){
|
||||
var idb = indexedDB.open("FLO_Tweet");
|
||||
idb.onerror = function(event) {
|
||||
console.log("Error in opening IndexedDB!");
|
||||
};
|
||||
idb.onsuccess = function(event) {
|
||||
var db = event.target.result;
|
||||
var obs = db.transaction("messages", "readwrite").objectStore("messages");
|
||||
data.msgID = `${data.time}_${data.floID}`;
|
||||
obs.add(data);
|
||||
db.close();
|
||||
};
|
||||
}
|
||||
|
||||
function pingSuperNodeforNewTweets(floID){
|
||||
getLastTweetCount(floID).then(function(result){
|
||||
var data = JSON.stringify({reqNewTweets:true,floID:floID,tid:result,requestor:selfID})
|
||||
@ -242,6 +272,10 @@ function initselfWebSocket(){
|
||||
db.close();
|
||||
};
|
||||
selfWebsocket.send(`U${data.floID}`);
|
||||
}else if(data.message && data.to == selfID){
|
||||
var msg = encrypt.decryptMessage(data.secret,data.pubVal)
|
||||
if(encrypt.verify(msg,data.sign,profiles[data.from].pubKey))
|
||||
storeMsg({time:data.time,floID:data.from,text:msg,type:'R'});
|
||||
}else if(data.fromSuperNode && data.floID == profileID){
|
||||
var tid = data.tid;
|
||||
data = JSON.parse(data.data);
|
||||
|
||||
@ -49,4 +49,33 @@ div.panel-heading{
|
||||
|
||||
.timestamp{
|
||||
color : grey;
|
||||
}
|
||||
|
||||
#msgsContainer{
|
||||
overflow-y: auto;
|
||||
height: calc(100% - 220px);
|
||||
}
|
||||
|
||||
.msg-R{
|
||||
float: left;
|
||||
width: auto !important;
|
||||
height: auto;
|
||||
background: lightcyan;
|
||||
border-radius: 10px 10px 10px 0;
|
||||
padding: 4px 10px 7px !important;
|
||||
font-size: 12px;
|
||||
display: inline-block;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.msg-S {
|
||||
float: right;
|
||||
width: auto !important;
|
||||
height: auto;
|
||||
background: lightcyan;
|
||||
border-radius: 10px 10px 0 10px;
|
||||
padding: 4px 10px 7px !important;
|
||||
font-size: 12px;
|
||||
display: inline-block;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user