diff --git a/app/app.js b/app/app.js
index f79f89f..1d0a5cd 100644
--- a/app/app.js
+++ b/app/app.js
@@ -161,13 +161,13 @@ var floOpt = {
var floID = key.getBitcoinAddress();
return floID;
},
- signData: function (msg, privateKeyHex) {
+ signData: function (data, privateKeyHex) {
var key = new Bitcoin.ECKey(privateKeyHex);
key.setCompressed(true);
var privateKeyArr = key.getBitcoinPrivateKeyByteArray();
privateKey = BigInteger.fromByteArrayUnsigned(privateKeyArr);
- var messageHash = Crypto.SHA256(msg);
+ var messageHash = Crypto.SHA256(data);
var messageHashBigInteger = new BigInteger(messageHash);
var messageSign = Bitcoin.ECDSA.sign(messageHashBigInteger, key.priv);
@@ -175,8 +175,8 @@ var floOpt = {
var sighex = Crypto.util.bytesToHex(messageSign);
return sighex;
},
- verifyData: function (msg, signatureHex, publicKeyHex) {
- var msgHash = Crypto.SHA256(msg);
+ verifyData: function (data, signatureHex, publicKeyHex) {
+ var msgHash = Crypto.SHA256(data);
var messageHashBigInteger = new BigInteger(msgHash);
var sigBytes = Crypto.util.hexToBytes(signatureHex);
@@ -326,10 +326,19 @@ function broadcastTx(signedTxHash) {
return result;
}
+function resetForm(formID) {
+ var formEl = document.getElementById(formID);
+ formEl.reset()
+ var labelSpans = formEl.querySelectorAll('span');
+ for (var i = 0; i < labelSpans.length; i++)
+ labelSpans[i].textContent = '';
+}
+
function userDataStartUp() {
console.log("StartUp");
-
- document.getElementById("sendMsgInput").addEventListener("keydown", (event) => {
+ resetForm("replyForm");
+ //Initiate Event Handling
+ document.getElementById("msgInput").addEventListener("keydown", (event) => {
if (event.keyCode === 13 && !event.shiftKey) {
event.preventDefault();
sendMsg();
@@ -337,6 +346,12 @@ function userDataStartUp() {
});
document.getElementById("searchContact").addEventListener("input", searchContact, true);
document.getElementById("searchList").addEventListener("input", searchChecklist, true);
+ document.getElementById('fileInput').onchange = function () {
+ var fileName = this.value.split("\\").pop();
+ this.nextSibling.textContent = fileName;
+ };
+
+ //Start Program
getDatafromAPI().then(result => {
console.log(result);
getContactsfromIDB().then(result => {
@@ -453,7 +468,7 @@ function getDatafromAPI() {
var objectStore3 = db.createObjectStore("messages", {
keyPath: 'time'
});
- objectStore3.createIndex('text', 'text', {
+ objectStore3.createIndex('msgData', 'msgData', {
unique: false
});
objectStore3.createIndex('floID', 'floID', {
@@ -813,13 +828,13 @@ function initselfWebSocket() {
function processIncomingData(data) {
if (data.directMsg !== undefined) {
- var msg = floOpt.decryptData(data.directMsg.msgCipher.secret, data.directMsg.msgCipher.pubVal, privKey)
- if (!floOpt.verifyData(msg, data.directMsg.sign, contacts[data.from].pubKey))
+ var msgData = floOpt.decryptData(data.directMsg.msgCipher.secret, data.directMsg.msgCipher.pubVal, privKey)
+ if (!floOpt.verifyData(msgData, data.directMsg.sign, contacts[data.from].pubKey))
return
var msgInfo = {
time: Date.now(),
floID: data.from,
- text: msg,
+ msgData: msgData,
type: "R"
}
createMsgElement(msgInfo);
@@ -827,14 +842,14 @@ function processIncomingData(data) {
} else if (data.groupMsg !== undefined && data.groupMsg.group in groups) {
if (!(groups[data.groupMsg.group].members.includes(data.from)))
return
- var msg = floOpt.decryptData(data.groupMsg.msgCipher.secret, data.groupMsg.msgCipher.pubVal, groups[data.groupMsg.group].privKey);
- if (!floOpt.verifyData(msg, data.groupMsg.sign, contacts[data.from].pubKey))
+ var msgData = floOpt.decryptData(data.groupMsg.msgCipher.secret, data.groupMsg.msgCipher.pubVal, groups[data.groupMsg.group].privKey);
+ if (!floOpt.verifyData(msgData, data.groupMsg.sign, contacts[data.from].pubKey))
return
var msgInfo = {
time: Date.now(),
groupID: data.groupMsg.group,
sender: data.from,
- text: msg,
+ msgData: msgData,
type: "R"
}
createMsgElement(msgInfo);
@@ -898,28 +913,36 @@ function createMsgElement(msgInfo) {
R: 'receiver'
};
if (!msgInfo.groupID) {
- var msgEl = document.getElementById(msgInfo.floID);
+ var msgCon = document.getElementById(msgInfo.floID);
var msghd = '';
} else {
- var msgEl = document.getElementById(msgInfo.groupID);
- var msghd = `${msgInfo.sender}
`;
+ var msgCon = document.getElementById(msgInfo.groupID);
+ var msghd = `${msgInfo.sender}`;
}
- if (!msgEl)
+ if (!msgCon)
return;
- var msgdiv = document.createElement('div');
- msgdiv.setAttribute("class", "row message-body");
- msgdiv.innerHTML = `
+ var msgData = JSON.parse(msgInfo.msgData);
+ var msgEl = document.createElement('div');
+ msgEl.setAttribute("class", "row message-body");
+ msgEl.innerHTML = `
-
- ${msghd}
+ ${msghd}
+
+
${getTime(msgInfo.time)}
`;
- msgdiv.querySelector("pre").textContent = msgInfo.text;
- msgEl.appendChild(msgdiv);
+ msgEl.querySelector("pre").textContent = msgData.text;
+ if (msgData.file) {
+ var fileEl = msgEl.querySelector("i");
+ fileEl.textContent = ` ${msgData.file.name} (${getFileSize(msgData.file.size)})`;
+ fileEl.setAttribute("onclick", `downloadFile(${msgInfo.time})`);
+ fileEl.setAttribute("class", "fa fa-arrow-circle-down");
+ }
+ msgCon.appendChild(msgEl);
} catch (e) {
console.log(e);
}
@@ -1057,30 +1080,83 @@ function getTime(time) {
return tmp;
}
+function getFileSize(size){
+ var filesizeUnits = ['B','kB','MB','GB','TB'];
+ for(var i = 0;i
{
+ console.log(msgData);
+ var time = Date.now();
+ var sign = floOpt.signData(msgData, privKey);
+ if (msgType === 'direct')
+ sendDirectMsg(msgData, time, sign);
+ else if (msgType === 'group')
+ sendGroupMsg(msgData, time, sign);
+ }).catch(error => {
+ console.log(error);
+ })
}
-function sendDirectMsg(msg, time, sign) {
+function getfileData(fileInput) {
+ return new Promise((resolve, reject) => {
+ try {
+ var files = document.getElementById(fileInput).files;
+ if (files.length == 0)
+ resolve(null);
+ else {
+ var reader = new FileReader();
+ reader.onload = (event) => {
+ var fileBytes = Crypto.charenc.Binary.stringToBytes(event.target.result);
+ resolve({
+ name: files[0].name,
+ size: files[0].size,
+ content: Crypto.util.bytesToBase64(fileBytes)
+ });
+ };
+ reader.onerror = (event) => {
+ reject("File could not be read! Code " + event.target.error.code);
+ };
+ reader.readAsBinaryString(files[0]);
+ }
+ } catch (e) {
+ reject(e);
+ }
+ });
+}
+
+function getReplyInputs() {
+ return new Promise((resolve, reject) => {
+ getfileData('fileInput').then(fileData => {
+ var msgData = {
+ text: document.getElementById('msgInput').value,
+ file: fileData
+ };
+ resetForm('replyForm');
+ resolve(JSON.stringify(msgData));
+ }).catch(error => {
+ reject(error);
+ });
+ });
+}
+
+function sendDirectMsg(msgData, time, sign) {
var data = JSON.stringify({
from: selfID,
to: receiverID,
directMsg: {
time: time,
- msgCipher: floOpt.encryptData(msg, contacts[receiverID].pubKey),
+ msgCipher: floOpt.encryptData(msgData, contacts[receiverID].pubKey),
sign: sign
}
});
@@ -1092,20 +1168,20 @@ function sendDirectMsg(msg, time, sign) {
var msgInfo = {
time: time,
floID: receiverID,
- text: msg,
+ msgData: msgData,
type: "S"
}
createMsgElement(msgInfo);
storeMsg(msgInfo);
}
-function sendGroupMsg(msg, time, sign) {
+function sendGroupMsg(msgData, time, sign) {
var data = {
from: selfID,
groupMsg: {
group: receiverID,
time: time,
- msgCipher: floOpt.encryptData(msg, groups[receiverID].pubKey),
+ msgCipher: floOpt.encryptData(msgData, groups[receiverID].pubKey),
sign: sign
}
};
@@ -1121,7 +1197,7 @@ function sendGroupMsg(msg, time, sign) {
time: time,
sender: selfID,
groupID: receiverID,
- text: msg,
+ msgData: msgData,
type: "S"
}
createMsgElement(msgInfo);
@@ -1468,6 +1544,7 @@ function customCheckList(userList, ignoreList, okBtnVal = "Ok", okBtnType = "suc
grpNameInput.style.display = (okBtnVal === "Create Group" ? "block" : "none");
grpNameInput.value = '';
var userChecklist = document.getElementById('userChecklist');
+ userChecklist.innerHTML = '';
for (var i = 0; i < userList.length; i++) {
if (ignoreList.includes(userList[i]))
continue;
@@ -1528,4 +1605,25 @@ function searchChecklist() {
} catch (e) {
console.log(e);
}
+}
+
+function downloadFile(msgID) {
+ var idb = indexedDB.open("FLO_Chat");
+ idb.onerror = (event) => {
+ console.log("Error in opening IndexedDB!");
+ };
+ idb.onsuccess = (event) => {
+ var db = event.target.result;
+ var msgReq = db.transaction('messages', "readwrite").objectStore('messages').get(msgID);
+ msgReq.onsuccess = (event) => {
+ var file = JSON.parse(event.target.result.msgData).file;
+ var tmpEl = document.createElement('a');
+ tmpEl.setAttribute('href', 'data:application/octet-stream;charset=utf-8;base64,' + file.content);
+ tmpEl.setAttribute('download', file.name);
+ tmpEl.style.display = 'none';
+ document.body.appendChild(tmpEl);
+ tmpEl.click();
+ document.body.removeChild(tmpEl);
+ }
+ }
}
\ No newline at end of file
diff --git a/app/index.html b/app/index.html
index 4312e62..92b984e 100644
--- a/app/index.html
+++ b/app/index.html
@@ -105,23 +105,32 @@
diff --git a/app/styles.css b/app/styles.css
index 7564d93..6d529ad 100644
--- a/app/styles.css
+++ b/app/styles.css
@@ -89,7 +89,8 @@ body {
height: 60px;
width: 100%;
background-color: #eee;
- z-index: 1000;
+ z-index: 1;
+ overflow: visible;
}
.heading-name {
@@ -174,17 +175,6 @@ body {
background-color: #f2f2f2;
}
-.sideBar-avatar {
- text-align: center;
- padding: 0 !important;
-}
-
-.avatar-icon img {
- border-radius: 50%;
- height: 49px;
- width: 49px;
-}
-
.sideBar-main {
padding: 0 !important;
}
@@ -321,7 +311,7 @@ body {
}
.message-body {
- margin: 0 !important;
+ margin: 5px 0px !important;
padding: 0 !important;
width: auto;
height: auto;
@@ -349,6 +339,15 @@ body {
word-break: break-word;
}
+.message-text i {
+ border: 0.5px solid rgba(0, 0, 0, 0.3);
+ border-radius: 5px;
+ background-color: rgba(0, 0, 0, 0.1);
+ padding: 5px;
+ display: block;
+ cursor: pointer;
+}
+
.message-time {
margin: 0 !important;
font-size: 12px;
@@ -360,7 +359,7 @@ body {
.receiver {
float: left;
width: auto !important;
- padding: 4px 10px 7px !important;
+ padding: 5px 10px 2px !important;
border-radius: 10px 10px 10px 0;
background: #ffffff;
font-size: 12px;
@@ -373,7 +372,7 @@ body {
height: auto;
background: #dcf8c6;
border-radius: 10px 10px 0 10px;
- padding: 4px 10px 7px !important;
+ padding: 5px 10px 2px !important;
font-size: 12px;
}
@@ -390,6 +389,7 @@ body {
.reply-icon {
padding: 5px !important;
+ overflow: visible;
}
.reply-icon i {
@@ -414,7 +414,6 @@ body {
box-shadow: none;
height: 100%;
font-size: 16px;
- overflow: hidden;
}
.reply-main textarea:focus {
@@ -424,103 +423,6 @@ body {
box-shadow: none;
}
-@media screen and (max-width: 700px) {
- .app {
- top: 0;
- height: 100%;
- }
-
- .heading {
- height: 70px;
- background-color: #009688;
- }
-
- .fa-2x {
- font-size: 2.3em !important;
- }
-
- .heading-icon {
- padding: 5px !important;
- }
-
- .heading-icon i {
- color: #fff;
- cursor: pointer;
- }
-
- .sideBar {
- height: calc(100% - 130px);
- }
-
- .sideBar-body {
- height: 80px;
- }
-
- .sideBar-main {
- padding: 0 !important;
- }
-
- .sideBar-main .row {
- padding: 0 !important;
- margin: 0 !important;
- }
-
- .sideBar-name {
- padding: 10px 5px !important;
- }
-
- .name-meta {
- font-size: 16px;
- padding: 5% !important;
- }
-
- .sideBar-time {
- padding: 10px !important;
- }
-
- .time-meta {
- text-align: right;
- font-size: 14px;
- padding: 4% !important;
- color: rgba(0, 0, 0, .4);
- vertical-align: baseline;
- }
-
- /*Conversation*/
- .conversation {
- padding: 0 !important;
- margin: 0 !important;
- height: 100%;
- border-left: 1px solid rgba(0, 0, 0, .08);
- }
-
- .message {
- height: calc(100% - 140px);
- }
-
- .reply {
- height: 70px;
- }
-
- .reply-icon {
- padding: 5px 0 !important;
- }
-
- .reply-icon i {
- padding: 5px 2px !important;
- font-size: 1.8em !important;
- }
-
- .reply-main {
- padding: 2px 8px !important;
- }
-
- .reply-main input {
- padding: 8px !important;
- font-size: 18px;
- }
-}
-
.badgebox {
opacity: 0;
}
@@ -562,15 +464,17 @@ body {
.userChecklist-container {
margin-top: 25px;
- width: 300px;
- height: 400px;
+ padding: 5px;
+ width: 325px;
+ height: auto;
background-color: #eee;
display: inline-block;
+
}
#userChecklist {
height: 275px;
- overflow-y: auto;
+ overflow-y: scroll;
}
.dropdown-content {
@@ -579,7 +483,8 @@ body {
min-width: 150px;
z-index: 1;
cursor: pointer;
- margin-left: -75px;
+ margin-left: -100px;
+ overflow: inherit;
}
.dropdown-content li {
@@ -601,4 +506,18 @@ body {
#groupOptions {
display: none;
+ overflow: visible;
+}
+
+input.attach-file {
+ display: none;
+}
+
+input.attach-file+span {
+ color: #93918f;
+ font-size: 10px;
+}
+
+.hidden {
+ display: none;
}
\ No newline at end of file