not really known
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

328 lines
11 KiB

  1. define(["sugar-web/env", "webL10n"], function (env, webL10n) {
  2. var connectedPeople = {};
  3. var xoLogo = '<?xml version="1.0" ?><!DOCTYPE svg PUBLIC \'-//W3C//DTD SVG 1.1//EN\' \'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\' [<!ENTITY stroke_color "#010101"><!ENTITY fill_color "#FFFFFF">]><svg enable-background="new 0 0 55 55" height="55px" version="1.1" viewBox="0 0 55 55" width="55px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"><g display="block" id="stock-xo_1_"><path d="M33.233,35.1l10.102,10.1c0.752,0.75,1.217,1.783,1.217,2.932 c0,2.287-1.855,4.143-4.146,4.143c-1.145,0-2.178-0.463-2.932-1.211L27.372,40.961l-10.1,10.1c-0.75,0.75-1.787,1.211-2.934,1.211 c-2.284,0-4.143-1.854-4.143-4.141c0-1.146,0.465-2.184,1.212-2.934l10.104-10.102L11.409,24.995 c-0.747-0.748-1.212-1.785-1.212-2.93c0-2.289,1.854-4.146,4.146-4.146c1.143,0,2.18,0.465,2.93,1.214l10.099,10.102l10.102-10.103 c0.754-0.749,1.787-1.214,2.934-1.214c2.289,0,4.146,1.856,4.146,4.145c0,1.146-0.467,2.18-1.217,2.932L33.233,35.1z" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5"/><circle cx="27.371" cy="10.849" fill="&fill_color;" r="8.122" stroke="&stroke_color;" stroke-width="3.5"/></g></svg>';
  4. var language;
  5. window.addEventListener('localized', function(e) {
  6. if (e.language != language) {
  7. setTimeout(function() {
  8. webL10n.language.code = language;
  9. }, 50);
  10. }
  11. });
  12. env.getEnvironment(function(err, environment) {
  13. var defaultLanguage = (typeof chrome != 'undefined' && chrome.app && chrome.app.runtime) ? chrome.i18n.getUILanguage() : navigator.language;
  14. language = environment.user ? environment.user.language : defaultLanguage;
  15. webL10n.language.code = language;
  16. });
  17. function generateXOLogoWithColor(color) {
  18. var coloredLogo = xoLogo;
  19. coloredLogo = coloredLogo.replace("#010101", color.stroke)
  20. coloredLogo = coloredLogo.replace("#FFFFFF", color.fill)
  21. return "data:image/svg+xml;base64," + btoa(coloredLogo);
  22. }
  23. function displayConnectedPeopleHtml() {
  24. var presenceUsersDiv = document.getElementById("presence-users");
  25. var html = "<hr><ul style='list-style: none; padding:0;'>"
  26. for (var key in connectedPeople) {
  27. html += "<li><img style='height:30px;' src='" + generateXOLogoWithColor(connectedPeople[key].colorvalue) + "'>" + connectedPeople[key].name + "</li>"
  28. }
  29. html += "</ul>"
  30. presenceUsersDiv.innerHTML = html
  31. }
  32. function displayConnectedPeople(users) {
  33. var presenceUsersDiv = document.getElementById("presence-users");
  34. if (!users || !presenceUsersDiv) {
  35. return;
  36. }
  37. connectedPeople = {};
  38. PaintApp.data.presence.listSharedActivityUsers(PaintApp.data.presence.getSharedInfo().id, function(usersConnected) {
  39. connectedPeople = {};
  40. for (var i = 0; i < usersConnected.length; i++) {
  41. var userConnected = usersConnected[i];
  42. connectedPeople[userConnected.networkId] = userConnected;
  43. }
  44. displayConnectedPeopleHtml();
  45. });
  46. }
  47. /* Function to handle user enter/exit */
  48. function onSharedActivityUserChanged(msg) {
  49. var userName = msg.user.name.replace('<', '&lt;').replace('>', '&gt;');
  50. var html = "<img style='height:30px;' src='" + generateXOLogoWithColor(msg.user.colorvalue) + "'>"
  51. if (msg.move === 1) {
  52. PaintApp.libs.humane.log(html + webL10n.get("PlayerJoin",{user: userName}))
  53. }
  54. if (msg.move === -1) {
  55. PaintApp.libs.humane.log(html + webL10n.get("PlayerLeave",{user: userName}))
  56. }
  57. PaintApp.data.presence.listSharedActivities(function(activities) {
  58. for (var i = 0; i < activities.length; i++) {
  59. if (activities[i].id === PaintApp.data.presence.getSharedInfo().id) {
  60. displayConnectedPeople(activities[i].users);
  61. }
  62. }
  63. });
  64. }
  65. function sendMessage(content) {
  66. var sharedId = window.top.sugar.environment.sharedId;
  67. if (!sharedId) {
  68. sharedId = PaintApp.data.presence.getSharedInfo().id
  69. }
  70. PaintApp.data.presence.sendMessage(sharedId, {
  71. user: PaintApp.data.presence.getUserInfo(),
  72. content: content
  73. });
  74. }
  75. /* Enabling an activity to be shared with the presenceObject */
  76. function shareActivity() {
  77. var activity = PaintApp.libs.activity;
  78. PaintApp.data.presence = activity.getPresenceObject(function(error, presence) {
  79. // Unable to join
  80. if (error) {
  81. console.log("error");
  82. return;
  83. }
  84. PaintApp.data.isShared = true;
  85. // Store settings
  86. userSettings = presence.getUserInfo();
  87. console.log("connected");
  88. // Not found, create a new shared activity
  89. if (!window.top.sugar.environment.sharedId) {
  90. presence.createSharedActivity('org.olpcfrance.PaintActivity', function(groupId) {});
  91. }
  92. // Show a disconnected message when the WebSocket is closed.
  93. presence.onConnectionClosed(function(event) {
  94. console.log(event);
  95. console.log("Connection closed");
  96. });
  97. // Display connection changed
  98. presence.onSharedActivityUserChanged(function(msg) {
  99. onSharedActivityUserChanged(msg);
  100. });
  101. // Handle messages received
  102. presence.onDataReceived(PaintApp.collaboration.onDataReceived);
  103. if (!PaintApp.data.isHost) {
  104. var lookForOtherUsersInterval = setInterval(function() {
  105. if (!PaintApp.data.presence.sharedInfo.users) {
  106. return;
  107. }
  108. displayConnectedPeople();
  109. if (!PaintApp.data.requestedData) {
  110. PaintApp.data.requestedData = true;
  111. sendMessage({
  112. action: "entranceToDataURLRequest " + PaintApp.data.presence.sharedInfo.users[0]
  113. })
  114. }
  115. clearInterval(lookForOtherUsersInterval)
  116. },
  117. 500);
  118. }
  119. });
  120. }
  121. function compress(data) {
  122. if (PaintApp.data.isCompressEnabled) {
  123. return PaintApp.libs.lzstring.compressToUTF16(data);
  124. }
  125. return data;
  126. }
  127. function decompress(data) {
  128. if (PaintApp.data.isCompressEnabled) {
  129. return PaintApp.libs.lzstring.decompressFromUTF16(data);
  130. }
  131. return data;
  132. }
  133. function handlePath(msg) {
  134. ctx = PaintApp.elements.canvas.getContext('2d');
  135. ctx.beginPath();
  136. ctx.strokeStyle = msg.content.data.strokeStyle;
  137. ctx.lineCap = msg.content.data.lineCap;
  138. ctx.lineWidth = msg.content.data.lineWidth;
  139. ctx.moveTo(msg.content.data.from.x, msg.content.data.from.y);
  140. ctx.lineTo(msg.content.data.to.x, msg.content.data.to.y);
  141. ctx.stroke();
  142. }
  143. function handleText(msg) {
  144. ctx = PaintApp.elements.canvas.getContext('2d');
  145. ctx.font = msg.content.data.font;
  146. ctx.fillStyle = msg.content.data.fillStyle;
  147. ctx.textAlign = msg.content.data.textAlign;
  148. ctx.fillText(msg.content.data.text, msg.content.data.left, msg.content.data.top);
  149. }
  150. function handleDrawImage(msg) {
  151. ctx = PaintApp.elements.canvas.getContext('2d');
  152. var img = new Image();
  153. img.onload = function() {
  154. ctx.drawImage(img, msg.content.data.left, msg.content.data.top, msg.content.data.width, msg.content.data.height);
  155. };
  156. img.src = msg.content.data.src;
  157. }
  158. function handleDrawStamp(msg) {
  159. var platform = 'webkit';
  160. var isFirefox = typeof InstallTrigger !== 'undefined';
  161. if (isFirefox) {
  162. platform = 'gecko';
  163. }
  164. ctx = PaintApp.elements.canvas.getContext('2d');
  165. var stampURL = msg.content.data.stampBase.replace('{platform}', platform);
  166. var url = window.location.href.split('/');
  167. url.pop();
  168. url = url.join('/') + '/' + stampURL;
  169. var request = new XMLHttpRequest();
  170. request.open('GET', url, true);
  171. request.onload = function(e) {
  172. if (request.status === 200 || request.status === 0) {
  173. var stamp = PaintApp.modes.Stamp.changeColors(request.responseText, msg.content.data.color.fill, msg.content.data.color.stroke);
  174. var img = new Image();
  175. img.onload = function() {
  176. ctx.drawImage(img, msg.content.data.left, msg.content.data.top, msg.content.data.width, msg.content.data.height);
  177. };
  178. img.src = 'data:image/svg+xml;base64,' + btoa(stamp);
  179. }
  180. };
  181. request.send(null);
  182. }
  183. function handleEntranceToDataURL(msg) {
  184. PaintApp.data.entranceToDataURL = true;
  185. PaintApp.clearCanvas();
  186. img = new Image();
  187. img.onload = function() {
  188. PaintApp.elements.canvas.getContext('2d').drawImage(img, 0, 0, msg.content.data.width, msg.content.data.height);
  189. };
  190. img.src = decompress(msg.content.data.src);
  191. }
  192. function handleToDataURL(msg) {
  193. PaintApp.clearCanvas();
  194. img = new Image();
  195. img.onload = function() {
  196. PaintApp.elements.canvas.getContext('2d').drawImage(img, 0, 0, msg.content.data.width, msg.content.data.height);
  197. };
  198. img.src = decompress(msg.content.data.src);
  199. }
  200. function handleClearCanvas(msg) {
  201. PaintApp.clearCanvas();
  202. }
  203. function handleSaveCanvas(msg) {
  204. if (PaintApp.data.isHost) {
  205. PaintApp.saveCanvas();
  206. }
  207. }
  208. function handleEntranceToDataURLRequest(msg) {
  209. try {
  210. PaintApp.data.presence.sendMessage(PaintApp.data.presence.getSharedInfo().id, {
  211. user: PaintApp.data.presence.getUserInfo(),
  212. content: {
  213. action: 'entranceToDataURL',
  214. data: {
  215. width: PaintApp.elements.canvas.width / window.devicePixelRatio,
  216. height: PaintApp.elements.canvas.height / window.devicePixelRatio,
  217. src: compress(PaintApp.elements.canvas.toDataURL())
  218. }
  219. }
  220. });
  221. } catch (e) {}
  222. }
  223. /* Handle data reception in shared activity */
  224. function onDataReceived(msg) {
  225. /* Ignore messages coming from ourselves */
  226. if (PaintApp.data.presence.getUserInfo().networkId === msg.user.networkId) {
  227. return;
  228. }
  229. PaintApp.tmp = msg;
  230. var userName = msg.user.name.replace('<', '&lt;').replace('>', '&gt;');
  231. var me = 'entranceToDataURLRequest ' + PaintApp.data.presence.getUserInfo().networkId
  232. switch (msg.content.action) {
  233. /* Request to draw points/line */
  234. case 'path':
  235. handlePath(msg)
  236. break;
  237. /* Request to draw text */
  238. case 'text':
  239. handleText(msg)
  240. break;
  241. /* Request to draw image */
  242. case 'drawImage':
  243. handleDrawImage(msg)
  244. break;
  245. /* Request to draw stamp */
  246. case 'drawStamp':
  247. handleDrawStamp(msg)
  248. break;
  249. case me:
  250. handleEntranceToDataURLRequest(msg)
  251. break;
  252. /* When entering inside the collaboration mode this message will be used to get the current paint */
  253. case 'entranceToDataURL':
  254. handleEntranceToDataURL(msg)
  255. break;
  256. /* Request to redraw the canvas */
  257. case 'toDataURL':
  258. handleToDataURL(msg)
  259. break;
  260. /* Request to clear the canvas */
  261. case 'clearCanvas':
  262. handleClearCanvas(msg)
  263. break;
  264. /* Request to save the canvas */
  265. case 'saveCanvas':
  266. handleSaveCanvas(msg)
  267. break;
  268. }
  269. }
  270. return {
  271. onDataReceived: onDataReceived,
  272. compress: compress,
  273. decompress: decompress,
  274. shareActivity: shareActivity,
  275. sendMessage: sendMessage,
  276. displayConnectedPeople: displayConnectedPeople
  277. }
  278. })