sb.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. var Countdown = {
  2. _timeout: null,
  3. _stepCb: null,
  4. _timeoutCb: null,
  5. running: false,
  6. seconds: 5,
  7. _initial_seconds: 5,
  8. start: function(seconds, timeoutCb, stepCb) {
  9. Countdown.stop();
  10. Countdown.seconds = Countdown._initial_seconds = seconds || 5;
  11. Countdown._timeoutCb = timeoutCb || Countdown._timeoutCb;
  12. Countdown._stepCb = stepCb || Countdown._stepCb;
  13. Countdown.running = true;
  14. Countdown._step();
  15. },
  16. stop: function() {
  17. if (Countdown._timeout) {
  18. window.clearTimeout(Countdown._timeout);
  19. }
  20. Countdown.running = false;
  21. },
  22. restart: function() {
  23. Countdown.start(Countdown._initial_seconds);
  24. },
  25. _step: function() {
  26. if (Countdown._stepCb) {
  27. Countdown._stepCb();
  28. }
  29. if (Countdown.seconds === 0) {
  30. if (Countdown._timeoutCb) {
  31. Countdown._timeoutCb();
  32. }
  33. Countdown.stop();
  34. } else {
  35. Countdown._decrement();
  36. }
  37. },
  38. _decrement: function() {
  39. Countdown.seconds = Countdown.seconds - 1;
  40. Countdown._timeout = window.setTimeout(function() {
  41. Countdown._step();
  42. }, 1000);
  43. }
  44. };
  45. function uuidv4() {
  46. return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
  47. (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
  48. );
  49. }
  50. var UUID = uuidv4();
  51. function getWSPath() {
  52. var loc = window.location, new_uri;
  53. if (loc.protocol === "https:") {
  54. new_uri = "wss:";
  55. } else {
  56. new_uri = "ws:";
  57. }
  58. new_uri += "//" + loc.host + "/ws?uuid=" + UUID;
  59. return new_uri;
  60. }
  61. var WS = new WebSocket(getWSPath(), ['soap', 'xmpp']);
  62. WS.onerror = function(error) {
  63. console.log('WebSocket Error ' + error);
  64. };
  65. WS.onmessage = function(e) {
  66. console.log("received message on websocket: " + e.data);
  67. var jdata = JSON.parse(e.data);
  68. if (!(jdata && jdata.source == "button" && jdata.action == "clicked")) {
  69. return;
  70. }
  71. if (!Countdown.running) {
  72. takePhoto("press again to publish!");
  73. } else {
  74. sendPhoto();
  75. }
  76. };
  77. function runCamera(stream) {
  78. console.log("initialize the camera");
  79. var video = document.querySelector("#sb-video");
  80. var container = document.querySelector("#canvas-container");
  81. container.width = video.videoWidth;
  82. video.onloadedmetadata = function() {
  83. video.play();
  84. };
  85. video.srcObject = stream;
  86. }
  87. function sendData(data) {
  88. var formData = new FormData();
  89. var msg = "";
  90. formData.append("selfie", new Blob([data]), "selfie.jpeg");
  91. fetch("/publish/", {
  92. method: "POST",
  93. body: formData
  94. }).then(function(response) {
  95. if (response.status !== 200) {
  96. msg = response.status;
  97. console.log(msg);
  98. iziToast.error({
  99. "title": "😭 something wrong sending the data 😭",
  100. "message": msg,
  101. "titleSize": "3em",
  102. "messageSize": "2em",
  103. "close": false,
  104. "drag": false,
  105. "pauseOnHover": false,
  106. "position": "topCenter"
  107. });
  108. }
  109. cancelPhoto();
  110. return response.json();
  111. }).then(function(json) {
  112. json = json || {};
  113. console.log(json);
  114. if (json && json.success) {
  115. msg = "❤ ❤ ❤ photo sent successfully! ❤ ❤ ❤";
  116. console.log(msg);
  117. iziToast.destroy();
  118. iziToast.success({
  119. "title": msg,
  120. "titleSize": "3em",
  121. "messageSize": "2em",
  122. "close": false,
  123. "drag": false,
  124. "pauseOnHover": false,
  125. "position": "topCenter"
  126. });
  127. } else {
  128. msg = json.message;
  129. console.log(msg);
  130. iziToast.error({
  131. "title": "😭 backend error 😭",
  132. "message": msg,
  133. "titleSize": "3em",
  134. "messageSize": "2em",
  135. "close": false,
  136. "drag": false,
  137. "pauseOnHover": false,
  138. "position": "topCenter"
  139. });
  140. }
  141. }).catch(function(err) {
  142. console.log(msg);
  143. iziToast.error({
  144. "title": "😭 error connecting to the server 😭",
  145. "message": err,
  146. "titleSize": "3em",
  147. "messageSize": "2em",
  148. "close": false,
  149. "drag": false,
  150. "pauseOnHover": false,
  151. "position": "topCenter"
  152. });
  153. cancelPhoto();
  154. });
  155. }
  156. function cancelPhoto() {
  157. console.log("cancel photo");
  158. document.querySelector("#send-photo-btn").classList.add("disabled");
  159. document.querySelector("#cancel-photo-btn").classList.add("disabled");
  160. var canvas = document.querySelector("#sb-canvas");
  161. var context = canvas.getContext("2d");
  162. context.clearRect(0, 0, canvas.width, canvas.height);
  163. Countdown.stop();
  164. }
  165. function isBlank(canvas) {
  166. var blank = document.createElement("canvas");
  167. blank.width = canvas.width;
  168. blank.height = canvas.height;
  169. return canvas.toDataURL() == blank.toDataURL();
  170. }
  171. function sendPhoto() {
  172. console.log("send photo");
  173. Countdown.stop();
  174. var canvas = document.querySelector("#sb-canvas");
  175. if (!canvas || isBlank(canvas)) {
  176. var msg = "I cowardly refuse to send a blank image.";
  177. console.log(msg);
  178. iziToast.warning({
  179. "title": msg,
  180. "titleSize": "3em",
  181. "messageSize": "2em",
  182. "close": false,
  183. "drag": false,
  184. "pauseOnHover": false,
  185. "position": "topCenter"
  186. });
  187. return;
  188. }
  189. return sendData(canvas.toDataURL("image/jpeg"));
  190. }
  191. function _takePhoto(message) {
  192. console.log("take photo");
  193. var video = document.querySelector("#sb-video");
  194. if (!(video.offsetWidth && video.offsetHeight)) {
  195. var msg = "missing video";
  196. console.log(msg);
  197. iziToast.warning({
  198. "title": msg,
  199. "message": "please grant camera permissions",
  200. "titleSize": "3em",
  201. "messageSize": "2em",
  202. "close": false,
  203. "drag": false,
  204. "pauseOnHover": false,
  205. "position": "topCenter"
  206. });
  207. return;
  208. }
  209. var canvas = document.querySelector("#sb-canvas");
  210. var context = canvas.getContext("2d");
  211. canvas.width = video.offsetWidth;
  212. canvas.height = video.offsetHeight;
  213. /*
  214. var tmpCanvas = document.createElement("canvas");
  215. tmpCanvas.width = video.offsetWidth;
  216. tmpCanvas.height = video.offsetHeight;
  217. var tmpContext = tmpCanvas.getContext("2d");
  218. var tmpRatio = (tmpCanvas.height / tmpCanvas.width);
  219. tmpContext.drawImage(video, 0, 0, video.offsetWidth, video.offsetHeight);
  220. canvas.width = canvas.offsetWidth;
  221. canvas.height = canvas.offsetHeight;
  222. canvas.style.height = parseInt(canvas.offsetWidth * tmpRatio);
  223. var scale = canvas.width / tmpCanvas.width;
  224. context.scale(scale, scale);
  225. context.drawImage(tmpCanvas, 0, 0);
  226. */
  227. context.drawImage(video, 0, 0, video.offsetWidth, video.offsetHeight);
  228. document.querySelector("#send-photo-btn").classList.remove("disabled");
  229. document.querySelector("#cancel-photo-btn").classList.remove("disabled");
  230. iziToast.question({
  231. "title": "do you like what you see?",
  232. "message": message || "press \"share photo\" to publish!",
  233. "titleSize": "3em",
  234. "messageSize": "2em",
  235. "close": false,
  236. "drag": false,
  237. "pauseOnHover": false,
  238. "position": "topCenter"
  239. });
  240. Countdown.start(5, cancelPhoto);
  241. }
  242. function takePhoto(msg) {
  243. window.setTimeout(function() { _takePhoto(msg); }, 1000);
  244. }
  245. function initCamera() {
  246. console.log("request camera permission");
  247. document.querySelector("#canvas-container").style.display = "block";
  248. var videoObj = {
  249. "video": {
  250. width: 800,
  251. height: 600
  252. },
  253. "audio": false
  254. };
  255. navigator.mediaDevices.getUserMedia(videoObj).then(function(stream) {
  256. runCamera(stream);
  257. document.querySelector("#init-btn").style.display = "none";
  258. document.querySelector("#take-photo-btn").classList.remove("disabled");
  259. }).catch(function(err) {
  260. console.log("unable to open camera");
  261. console.log(err);
  262. iziToast.error({
  263. "title": "unable to open camera",
  264. "message": "please reload this page: " + err,
  265. "titleSize": "3em",
  266. "messageSize": "2em",
  267. "close": false,
  268. "drag": false,
  269. "pauseOnHover": false,
  270. "position": "topCenter"
  271. });
  272. });
  273. }