diff --git a/build-in-docker.conf b/build-in-docker.conf index 4bc8840..865e76f 100644 --- a/build-in-docker.conf +++ b/build-in-docker.conf @@ -20,7 +20,8 @@ if test -n "${ANDROID_HOME}"; then envs+=("-e ANDROID_HOME=${ANDROID_HOME}") envs+=("-e HOME=${HOME}") envs+=("-e TERM=xterm") + envs+=("-e ANDROID_SDK_HOME=/workdir") dirs+=("-v ${ANDROID_HOME}:${ANDROID_HOME}:ro") dirs+=("-v ${HOME}/.gnupg:${HOME}/.gnupg:ro") - dirs+=("-v ${HOME}/.android:${HOME}/.android:ro") + #dirs+=("-v ${HOME}/.android:${HOME}/.android") fi diff --git a/nodejs/public/javascripts/safechat.js b/nodejs/public/javascripts/safechat.js index a1a407f..368b555 100644 --- a/nodejs/public/javascripts/safechat.js +++ b/nodejs/public/javascripts/safechat.js @@ -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) { ''+ ''+ - m.user+ - ''+(message.receiver?" → "+message.receiver:"")+ + htmlenc(m.user)+ + ''+(message.receiver?' → ' + +htmlenc(message.receiver)+'':"")+ ''+ '
'+ - message.text+ + htmlenc(message.text)+ '
'); // 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"); } diff --git a/nodejs/views/index.ejs b/nodejs/views/index.ejs index 9f5e49e..332fad2 100644 --- a/nodejs/views/index.ejs +++ b/nodejs/views/index.ejs @@ -50,10 +50,10 @@