diff --git a/www/canvas/index.html b/www/canvas/index.html new file mode 100644 index 000000000..850524185 --- /dev/null +++ b/www/canvas/index.html @@ -0,0 +1,73 @@ + + + + + + + + + + + + +

Welcome to CryptCanvas!

+

Zero Knowledge Realtime Collaborative Canvas Editing

+ +
+ + +
 
+
+ + + + + diff --git a/www/canvas/main.js b/www/canvas/main.js new file mode 100644 index 000000000..ce0336002 --- /dev/null +++ b/www/canvas/main.js @@ -0,0 +1,108 @@ +require.config({ paths: { + 'json.sortify': '/bower_components/json.sortify/dist/JSON.sortify' +}}); + +define([ + '/api/config?cb=' + Math.random().toString(16).substring(2), + '/common/RealtimeTextarea.js', + '/common/messages.js', + '/common/crypto.js', + '/common/TextPatcher.js', + '/bower_components/fabric.js/dist/fabric.min.js', + 'json.sortify', + '/bower_components/jquery/dist/jquery.min.js', + '/customize/pad.js' +], function (Config, Realtime, Messages, Crypto, TextPatcher, Fabric, JSONSortify) { + var module = window.APP = { }; + var $ = module.$ = window.jQuery; + var Fabric = module.Fabric = window.fabric; + + $(window).on('hashchange', function() { + window.location.reload(); + }); + if (window.location.href.indexOf('#') === -1) { + window.location.href = window.location.href + '#' + Crypto.genKey(); + return; + } + + /* Initialize Fabric */ + var canvas = module.canvas = new Fabric.Canvas('canvas'); + var $canvas = $('canvas'); + + var $width = $('#width'); + var updateBrushWidth = function () { + canvas.freeDrawingBrush.width = Number($width.val()); + }; + updateBrushWidth(); + + $width.on('change', updateBrushWidth); + + var palette = ['red', 'blue', 'green', 'white', 'black', 'purple', 'gray']; + var $colors = $('#colors'); + $colors.html(function (i, val) { + return palette.map(function (c) { + return ""; + }).join(""); + }); + + $('.palette').on('click', function () { + var color = $(this).css('background-color'); + canvas.freeDrawingBrush.color = color; + }); + + var setEditable = function (bool) { + canvas.isDrawingMode = bool; + $canvas.css('border-color', bool? 'black': 'red'); + }; + + var key = Crypto.parseKey(window.location.hash.substring(1)); + var initializing = true; + + var config = module.config = { + websocketURL: Config.websocketURL + '_old', + userName: Crypto.rand64(8), + channel: key.channel, + cryptKey: key.cryptKey + }; + + var onInit = config.onInit = function (info) { }; + + var onRemote = config.onRemote = function () { + if (initializing) { return; } + var userDoc = module.realtime.getUserDoc(); + canvas.loadFromJSON(userDoc); + canvas.renderAll(); + }; + + var onLocal = config.onLocal = function () { + if (initializing) { return; } + var content = JSONSortify(canvas.toDatalessJSON()); + module.patchText(content); + }; + + var onReady = config.onReady = function (info) { + var realtime = module.realtime = info.realtime; + module.patchText = TextPatcher.create({ + realtime: realtime + }); + + setEditable(true); + initializing = false; + onRemote(); + }; + + var onAbort = config.onAbort = function (info) { + setEditable(false); + window.alert("Server Connection Lost"); + }; + + var rt = Realtime.start(config); + + canvas.on('mouse:up', onLocal); + + $('#clear').on('click', function () { + canvas.clear(); + }); + + +});