sb.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  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());
  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. resizeCanvas(video, 'sb-canvas');
  87. }
  88. function sendData(data) {
  89. var formData = new FormData();
  90. var msg = "";
  91. formData.append("selfie", new Blob([data]), "selfie.jpeg");
  92. fetch("/publish/", {
  93. method: "POST",
  94. body: formData
  95. }).then(function(response) {
  96. if (response.status !== 200) {
  97. msg = response.status;
  98. console.log(msg);
  99. iziToast.error({
  100. "title": "😭 something wrong sending the data 😭",
  101. "message": msg,
  102. "titleSize": "3em",
  103. "messageSize": "2em",
  104. "close": false,
  105. "drag": false,
  106. "pauseOnHover": false,
  107. "position": "topCenter"
  108. });
  109. }
  110. cancelPhoto();
  111. return response.json();
  112. }).then(function(json) {
  113. json = json || {};
  114. console.log(json);
  115. if (json && json.success) {
  116. msg = "❤ ❤ ❤ photo sent successfully! ❤ ❤ ❤";
  117. console.log(msg);
  118. iziToast.destroy();
  119. iziToast.success({
  120. "title": msg,
  121. "titleSize": "3em",
  122. "messageSize": "2em",
  123. "close": false,
  124. "drag": false,
  125. "pauseOnHover": false,
  126. "position": "topCenter"
  127. });
  128. } else {
  129. msg = json.message;
  130. console.log(msg);
  131. iziToast.error({
  132. "title": "😭 backend error 😭",
  133. "message": msg,
  134. "titleSize": "3em",
  135. "messageSize": "2em",
  136. "close": false,
  137. "drag": false,
  138. "pauseOnHover": false,
  139. "position": "topCenter"
  140. });
  141. }
  142. }).catch(function(err) {
  143. console.log(msg);
  144. iziToast.error({
  145. "title": "😭 error connecting to the server 😭",
  146. "message": err,
  147. "titleSize": "3em",
  148. "messageSize": "2em",
  149. "close": false,
  150. "drag": false,
  151. "pauseOnHover": false,
  152. "position": "topCenter"
  153. });
  154. cancelPhoto();
  155. });
  156. }
  157. function cancelPhoto() {
  158. console.log("cancel photo");
  159. document.querySelector("#send-photo-btn").classList.add("disabled");
  160. document.querySelector("#cancel-photo-btn").classList.add("disabled");
  161. var canvas = document.querySelector("#sb-canvas");
  162. var context = canvas.getContext("2d");
  163. context.clearRect(0, 0, canvas.width, canvas.height);
  164. Countdown.stop();
  165. }
  166. function isBlank(canvas) {
  167. var blank = document.createElement("canvas");
  168. blank.width = canvas.width;
  169. blank.height = canvas.height;
  170. return canvas.toDataURL() == blank.toDataURL();
  171. }
  172. function sendPhoto() {
  173. console.log("send photo");
  174. Countdown.stop();
  175. var canvas = document.querySelector("#sb-canvas");
  176. if (!canvas || isBlank(canvas)) {
  177. var msg = "I cowardly refuse to send a blank image.";
  178. console.log(msg);
  179. iziToast.warning({
  180. "title": msg,
  181. "titleSize": "3em",
  182. "messageSize": "2em",
  183. "close": false,
  184. "drag": false,
  185. "pauseOnHover": false,
  186. "position": "topCenter"
  187. });
  188. return;
  189. }
  190. return sendData(canvas.toDataURL("image/jpeg"));
  191. }
  192. function _takePhoto(message) {
  193. console.log("take photo");
  194. var video = document.querySelector("#sb-video");
  195. if (!(video.offsetWidth && video.offsetHeight)) {
  196. var msg = "missing video";
  197. console.log(msg);
  198. iziToast.warning({
  199. "title": msg,
  200. "message": "please grant camera permissions",
  201. "titleSize": "3em",
  202. "messageSize": "2em",
  203. "close": false,
  204. "drag": false,
  205. "pauseOnHover": false,
  206. "position": "topCenter"
  207. });
  208. return;
  209. }
  210. var canvas = document.querySelector("#sb-canvas");
  211. var context = canvas.getContext("2d");
  212. canvas.width = video.offsetWidth;
  213. canvas.height = video.offsetHeight;
  214. /*
  215. var tmpCanvas = document.createElement("canvas");
  216. tmpCanvas.width = video.offsetWidth;
  217. tmpCanvas.height = video.offsetHeight;
  218. var tmpContext = tmpCanvas.getContext("2d");
  219. var tmpRatio = (tmpCanvas.height / tmpCanvas.width);
  220. tmpContext.drawImage(video, 0, 0, video.offsetWidth, video.offsetHeight);
  221. canvas.width = canvas.offsetWidth;
  222. canvas.height = canvas.offsetHeight;
  223. canvas.style.height = parseInt(canvas.offsetWidth * tmpRatio);
  224. var scale = canvas.width / tmpCanvas.width;
  225. context.scale(scale, scale);
  226. context.drawImage(tmpCanvas, 0, 0);
  227. */
  228. context.drawImage(video, 0, 0, video.offsetWidth, video.offsetHeight);
  229. document.querySelector("#send-photo-btn").classList.remove("disabled");
  230. document.querySelector("#cancel-photo-btn").classList.remove("disabled");
  231. iziToast.question({
  232. "title": "do you like what you see?",
  233. "message": message || "press \"share photo\" to publish!",
  234. "titleSize": "3em",
  235. "messageSize": "2em",
  236. "close": false,
  237. "drag": false,
  238. "pauseOnHover": false,
  239. "position": "topCenter"
  240. });
  241. Countdown.start(5, cancelPhoto);
  242. }
  243. function takePhoto(msg) {
  244. window.setTimeout(function() { _takePhoto(msg); }, 1000);
  245. }
  246. function initCamera() {
  247. console.log("request camera permission");
  248. document.querySelector("#canvas-container").style.display = "block";
  249. var videoObj = {
  250. "video": {
  251. width: 800,
  252. height: 600
  253. },
  254. "audio": false
  255. };
  256. navigator.mediaDevices.getUserMedia(videoObj).then(function(stream) {
  257. runCamera(stream);
  258. document.querySelector("#init-btn").style.display = "none";
  259. document.querySelector("#take-photo-btn").classList.remove("disabled");
  260. }).catch(function(err) {
  261. console.log("unable to open camera");
  262. console.log(err);
  263. iziToast.error({
  264. "title": "unable to open camera",
  265. "message": "please reload this page: " + err,
  266. "titleSize": "3em",
  267. "messageSize": "2em",
  268. "close": false,
  269. "drag": false,
  270. "pauseOnHover": false,
  271. "position": "topCenter"
  272. });
  273. });
  274. }
  275. function resizeCanvas(el, canvasID) {
  276. var canvas = document.getElementById(canvasID);
  277. canvas.width = el.offsetWidth;
  278. canvas.height = el.offsetHeighth;
  279. }