|
|
|
@ -42,6 +42,11 @@ var username = null; ///< username, only used during registration |
|
|
|
|
var filecontent = new Array(); ///< temporary storage for attachments
|
|
|
|
|
var socket = io.connect(); |
|
|
|
|
|
|
|
|
|
/// Padding for numbers in dates
|
|
|
|
|
function pad(n) { |
|
|
|
|
return n<10 ? '0'+n : n |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var reboottimer = null; |
|
|
|
|
/// Show error messsage
|
|
|
|
|
/** Fades in an error message and logs to console. |
|
|
|
@ -177,7 +182,6 @@ function backup() { |
|
|
|
|
var download = document.createElement('a'); |
|
|
|
|
download.href = 'data:attachment/text,'+encodeURI(JSON.stringify(localStorage)); |
|
|
|
|
download.target = '_blank'; |
|
|
|
|
function pad(n) {return n<10 ? '0'+n : n} |
|
|
|
|
var now = new Date(); |
|
|
|
|
download.download = |
|
|
|
|
pad(now.getFullYear())+pad(now.getMonth()+1)+pad(now.getDate())+ |
|
|
|
@ -194,7 +198,7 @@ function backup() { |
|
|
|
|
/// Upload Profile Backup
|
|
|
|
|
function restore(evt) { |
|
|
|
|
if (!window.FileReader) |
|
|
|
|
return error("your browser dows not support file upload", true); |
|
|
|
|
return error("your browser does not support file upload", true); |
|
|
|
|
for (var i=0, f; f=evt.target.files[i]; ++i) { |
|
|
|
|
var file = f; |
|
|
|
|
var reader = new FileReader(); |
|
|
|
@ -327,10 +331,18 @@ function clearmessage() { |
|
|
|
|
$("#message").prop(":disabled", false); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function guessfilename(mimetype, user, date) { |
|
|
|
|
if (!user) user = userid(); |
|
|
|
|
if (!date) date = new Date(); |
|
|
|
|
var ext = mimetype.replace(/.*\/(x-)?/i, ""); |
|
|
|
|
return pad(date.getFullYear())+pad(date.getMonth()+1)+pad(date.getDate()) |
|
|
|
|
+"-"+ext+"-"+user+"@"+window.location.hostname+'.'+ext; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Display Image Attachments
|
|
|
|
|
function attachments(files, id) { |
|
|
|
|
function attachments(files, id, from, date) { |
|
|
|
|
if (files) files.forEach(function(file) { |
|
|
|
|
console.log(file); |
|
|
|
|
if (!file.name) file.name = guessfilename(file.type, from, date); |
|
|
|
|
var img = document.createElement('img'); |
|
|
|
|
img.title = file.name; |
|
|
|
|
if (file.type.match('^image/')) { |
|
|
|
@ -340,12 +352,106 @@ function attachments(files, id) { |
|
|
|
|
} |
|
|
|
|
var a = document.createElement('a'); |
|
|
|
|
a.href = file.content; |
|
|
|
|
a.download = file.name; |
|
|
|
|
a.target = '_blank'; |
|
|
|
|
a.appendChild(img); |
|
|
|
|
$(id).append(a);
|
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// function getUserMedia() {
|
|
|
|
|
// return navigator.mediaDevices.getUserMedia || navigator.getUserMedia
|
|
|
|
|
// || navigator.webkitGetUserMedia || navigator.mozGetUserMedia
|
|
|
|
|
// || navigator.msGetUserMedia;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
var mediarecorder = null; |
|
|
|
|
var mediastream = null; |
|
|
|
|
function record() { |
|
|
|
|
mediarecorder = mediastream.record(); |
|
|
|
|
} |
|
|
|
|
function done() { |
|
|
|
|
mediarecorder.getRecordedData(function(videoblob) { |
|
|
|
|
previewfile(videoblob, "video/webm"); |
|
|
|
|
}); |
|
|
|
|
mediarecorder = null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function abort() { |
|
|
|
|
mediarecorder = null; |
|
|
|
|
mediastream.getTracks().forEach(function(track) {track.stop()}); |
|
|
|
|
mediastream = null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Record Video from builtin camera
|
|
|
|
|
function recordvideo() { |
|
|
|
|
$("#videorecorder").show(); |
|
|
|
|
if (mediastream) { |
|
|
|
|
mediarecorder = mediastream.record(); |
|
|
|
|
} |
|
|
|
|
try { |
|
|
|
|
navigator.mediaDevices.getUserMedia({audio: true, video: true}) |
|
|
|
|
.then(function(stream) { |
|
|
|
|
console.log(stream); |
|
|
|
|
mediastream = stream; |
|
|
|
|
var video = $("#videorecorder video"); |
|
|
|
|
video.attr("src", window.URL.createObjectURL(mediastream)); |
|
|
|
|
}).catch(function() { |
|
|
|
|
error("capture video failed", false); |
|
|
|
|
}); |
|
|
|
|
} catch (e) { |
|
|
|
|
console.log(e); |
|
|
|
|
error("cannot access camera", true); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function previewfile(content, type, name) { |
|
|
|
|
if (!name) name = guessfilename(type); |
|
|
|
|
if (type.match('^image/')) { |
|
|
|
|
var img = document.createElement("img"); |
|
|
|
|
img.onload = function() { // resize image to maximum 400px
|
|
|
|
|
var MAX = 400; |
|
|
|
|
var width = img.width; |
|
|
|
|
var height = img.height; |
|
|
|
|
if (width > MAX) { |
|
|
|
|
height *= MAX / width; |
|
|
|
|
width = MAX; |
|
|
|
|
} |
|
|
|
|
if (height > MAX) { |
|
|
|
|
width *= MAX / height; |
|
|
|
|
height = MAX; |
|
|
|
|
} |
|
|
|
|
var canvas = document.createElement("canvas"); |
|
|
|
|
canvas.width = width; |
|
|
|
|
canvas.height = height; |
|
|
|
|
var ctx = canvas.getContext("2d"); |
|
|
|
|
ctx.drawImage(img, 0, 0, width, height); |
|
|
|
|
img.onload = function() { |
|
|
|
|
filecontent.push({name: name, type: type, content: img.src}); |
|
|
|
|
$("#preview").append(img); |
|
|
|
|
success('image is ready to be sent'); |
|
|
|
|
} |
|
|
|
|
img.title = name; |
|
|
|
|
img.src = canvas.toDataURL(file.type); |
|
|
|
|
} |
|
|
|
|
img.src=content; |
|
|
|
|
} else if (type.match('^video/')) { |
|
|
|
|
filecontent.push({name: name, type: type, content: content}); |
|
|
|
|
var video = document.createElement("video"); |
|
|
|
|
video.setAttribute("controls", "controls"); |
|
|
|
|
video.setAttribute("src", content); |
|
|
|
|
video.setAttribute("title", name); |
|
|
|
|
$("#preview").append(video); |
|
|
|
|
} else { |
|
|
|
|
filecontent.push({name: name, type: type, content: content}); |
|
|
|
|
var img = document.createElement("img"); |
|
|
|
|
img.src = "images/Document_sans_PICOL-PIctorial-COmmunication-Language.svg"; |
|
|
|
|
img.title = name; |
|
|
|
|
$("#preview").append(img); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Upload Attachment
|
|
|
|
|
/** Prepares attachment to be sent in a message. If the attachment is |
|
|
|
|
an image, it resizes the image to 400px on the lager side. |
|
|
|
@ -358,47 +464,12 @@ function fileupload(evt) { |
|
|
|
|
return error("your browser does not support file upload", true); |
|
|
|
|
for (var i=0, f; f=evt.target.files[i]; ++i) { |
|
|
|
|
var file = f; |
|
|
|
|
console.log(file); |
|
|
|
|
var reader = new FileReader(); |
|
|
|
|
reader.onload = function(evt) { |
|
|
|
|
if (evt.target.error) return error("error reading file", true); |
|
|
|
|
if (evt.target.readyState==0) return notice("waiting for data …"); |
|
|
|
|
if (evt.target.readyState==1) return notice("loading data …"); |
|
|
|
|
if (file.type.match('^image/')) { |
|
|
|
|
var img = document.createElement("img"); |
|
|
|
|
img.onload = function() { |
|
|
|
|
var MAX = 400; |
|
|
|
|
var width = img.width; |
|
|
|
|
var height = img.height; |
|
|
|
|
if (width > MAX) { |
|
|
|
|
height *= MAX / width; |
|
|
|
|
width = MAX; |
|
|
|
|
} |
|
|
|
|
if (height > MAX) { |
|
|
|
|
width *= MAX / height; |
|
|
|
|
height = MAX; |
|
|
|
|
} |
|
|
|
|
var canvas = document.createElement("canvas"); |
|
|
|
|
canvas.width = width; |
|
|
|
|
canvas.height = height; |
|
|
|
|
var ctx = canvas.getContext("2d"); |
|
|
|
|
ctx.drawImage(img, 0, 0, width, height); |
|
|
|
|
img.onload = function() { |
|
|
|
|
filecontent.push({name:file.name, type: file.type, content: img.src}); |
|
|
|
|
$("#preview").append(img); |
|
|
|
|
success('image of type '+file.type+' is ready to be sent'); |
|
|
|
|
} |
|
|
|
|
img.title = file.name; |
|
|
|
|
img.src = canvas.toDataURL(file.type); |
|
|
|
|
} |
|
|
|
|
img.src=evt.target.result; |
|
|
|
|
} else { |
|
|
|
|
filecontent.push({name:file.name, type: file.type, content: evt.target.result}); |
|
|
|
|
var img = document.createElement("img"); |
|
|
|
|
img.src = "images/Document_sans_PICOL-PIctorial-COmmunication-Language.svg"; |
|
|
|
|
img.title = file.name; |
|
|
|
|
$("#preview").append(img); |
|
|
|
|
} |
|
|
|
|
previewfile(evt.target.result, file.type, file.name); |
|
|
|
|
} |
|
|
|
|
reader.readAsDataURL(file); |
|
|
|
|
} |
|
|
|
@ -491,13 +562,13 @@ function messages(msgs) { |
|
|
|
|
return setTimeout(function() {emit("messages");}, 1000); // try again later
|
|
|
|
|
status("allmessages"); |
|
|
|
|
notice("load messages, please wait …"); |
|
|
|
|
msgs.forEach(function(msg) {message(msg, false);}); |
|
|
|
|
msgs.forEach(function(msg) {message(msg, true);}); |
|
|
|
|
status("chat"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Received a message from server
|
|
|
|
|
function message(m, signaling=true) { |
|
|
|
|
if (signaling) console.log("rcv-> message("+m.user+")"); |
|
|
|
|
function message(m, internal) { |
|
|
|
|
if (!internal) console.log("rcv-> message("+m.user+")"); |
|
|
|
|
if (!password || !privateKey()) return; |
|
|
|
|
var key=openpgp.key.readArmored(m.pubkey); |
|
|
|
|
if (key.err) return error("key of sender unreadable", true); |
|
|
|
@ -517,17 +588,19 @@ function message(m, signaling=true) { |
|
|
|
|
'</span><span class="sender">'+ |
|
|
|
|
'<a href="javascript:void(0)" '+ |
|
|
|
|
'onclick="setreceiver(this.innerHTML)">'+ |
|
|
|
|
m.user+ |
|
|
|
|
'</a>'+(message.receiver?" → "+message.receiver:"")+ |
|
|
|
|
htmlenc(m.user)+ |
|
|
|
|
'</a>'+(message.receiver?' → <a href="javascript:void(0)" '+ |
|
|
|
|
'onclick="setreceiver(this.innerHTML)">' |
|
|
|
|
+htmlenc(message.receiver)+'</a>':"")+ |
|
|
|
|
'</span></div>'+ |
|
|
|
|
'<div class="text">'+ |
|
|
|
|
message.text+ |
|
|
|
|
htmlenc(message.text)+ |
|
|
|
|
'</div></div><div class="clear"/>'); |
|
|
|
|
// show attachments
|
|
|
|
|
attachments(message.files, '#id'+m.id+' .text'); |
|
|
|
|
attachments(message.files, '#id'+m.id+' .text', m.user, new Date(m.time)); |
|
|
|
|
// calculate and show emoticons
|
|
|
|
|
$('#id'+m.id).emoticonize(); |
|
|
|
|
if (signaling) beep(m.user); |
|
|
|
|
if (!internal) beep(m.user); |
|
|
|
|
}) |
|
|
|
|
.catch(function(e) { |
|
|
|
|
// not for me
|
|
|
|
@ -593,6 +666,7 @@ function setpw(pwd) { |
|
|
|
|
setpw() continues automatically. No submit is required by the |
|
|
|
|
user. */ |
|
|
|
|
function getpwd() { |
|
|
|
|
if (password) return; |
|
|
|
|
$("#removeKey").show(); |
|
|
|
|
status("getpwd"); |
|
|
|
|
} |
|
|
|
|