From 2206248143c2ce582afc976162f90cf1328eb61c Mon Sep 17 00:00:00 2001 From: d11e9 Date: Tue, 5 Apr 2016 16:50:11 +0100 Subject: [PATCH 01/14] Enable extension to sync files using chrome.storage.sync --- assets/js/app.js | 32 ++++++++++++++++++++++++++++++++ background.js | 11 ++++++++--- index.html | 1 + manifest.json | 14 +++++++++----- 4 files changed, 50 insertions(+), 8 deletions(-) diff --git a/assets/js/app.js b/assets/js/app.js index 2f399832ed..28dd3ad1dc 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -51,6 +51,36 @@ } + // ----------------- storage -------------------- + + function syncStorage() { + + var obj = {} + + function check(key){ + chrome.storage.sync.get( key, function(resp){ + console.log("comparing to cloud", resp) + if (obj[key] !== resp[key] && confirm("Overwrite '" + fileNameFromKey(key) + "' from cloud storage?")) { + console.log("Overwriting", key ) + localStorage.setItem( key, resp[key] ); + updateFiles(); + } + }) + } + + for (var y in window.localStorage) { + console.log("checking", y) + obj[y] = window.localStorage.getItem(y); + if (y.indexOf(SOL_CACHE_FILE_PREFIX) !== 0) continue; + check(y) + } + + } + + window.syncStorage = syncStorage; + if (chrome && chrome.storage && chrome.storage.sync) syncStorage() + + // ----------------- editor ---------------------- @@ -801,4 +831,6 @@ return funABI; }; + syncStorage() + }); \ No newline at end of file diff --git a/background.js b/background.js index a5052296e1..488d0da4d7 100644 --- a/background.js +++ b/background.js @@ -1,5 +1,10 @@ chrome.browserAction.onClicked.addListener(function(tab) { - chrome.tabs.create({'url': chrome.extension.getURL('index.html')}, function(tab) { - // tab opened - }); + + chrome.storage.sync.set({"chrome-app-sync": true}); + + + chrome.tabs.create({'url': chrome.extension.getURL('index.html')}, function(tab) { + // tab opened + }); + }); diff --git a/index.html b/index.html index ab0e5fbb6b..158a04b710 100644 --- a/index.html +++ b/index.html @@ -33,6 +33,7 @@ + diff --git a/manifest.json b/manifest.json index 2daea8ae5e..cf8d330c71 100644 --- a/manifest.json +++ b/manifest.json @@ -5,24 +5,28 @@ "description": "Realtime compiler and runtime", "devtools_page": "devtools.html", "update_url": "https://chriseth.github.io/browser-solidity/", - "version": "1.0", + "version": "1.1", "manifest_version": 2, "background": { "scripts": ["background.js"], "persistent": true }, + "icons": { + "32": "icon.png" + }, + "browser_action": { "default_icon": "icon.png" }, "permissions": [ + "storage", "tabs", "activeTab", "https://ajax.googleapis.com/", - "webRequest", - "webRequestBlocking", - "\u003Call_urls>", - "storage" + "webRequest", + "webRequestBlocking", + "\u003Call_urls>" ] } From 9ed734c3583f6156d7b30a51cad6b87b437dee71 Mon Sep 17 00:00:00 2001 From: d11e9 Date: Tue, 5 Apr 2016 17:52:57 +0100 Subject: [PATCH 02/14] separate sessions for files, maintains selection and undo stack --- assets/js/app.js | 52 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/assets/js/app.js b/assets/js/app.js index 28dd3ad1dc..cd7b875fdc 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -55,16 +55,28 @@ function syncStorage() { + if (!chrome || !chrome.storage || !chrome.storage.sync) return; + var obj = {} + var done = false; + var count = 0 + var dont = 0; function check(key){ chrome.storage.sync.get( key, function(resp){ - console.log("comparing to cloud", resp) - if (obj[key] !== resp[key] && confirm("Overwrite '" + fileNameFromKey(key) + "' from cloud storage?")) { + console.log("comparing to cloud", key, resp) + if (typeof resp[key] != 'undefined' && obj[key] !== resp[key] && confirm("Overwrite '" + fileNameFromKey(key) + "'? Click Ok to overwrite local file with file from cloud. Cancel will push your local file to the cloud.")) { console.log("Overwriting", key ) - localStorage.setItem( key, resp[key] ); + localStorage.setItem( key, resp[key] ); updateFiles(); + } else { + console.log( "add to obj", obj, key) + obj[key] = localStorage[key]; } + done++ + if (done >= count) chrome.storage.sync.set( obj, function(){ + console.log( "updated cloud files with: ", obj, this, arguments) + }) }) } @@ -72,16 +84,18 @@ console.log("checking", y) obj[y] = window.localStorage.getItem(y); if (y.indexOf(SOL_CACHE_FILE_PREFIX) !== 0) continue; + count++; check(y) } + } window.syncStorage = syncStorage; - if (chrome && chrome.storage && chrome.storage.sync) syncStorage() + syncStorage() + - // ----------------- editor ---------------------- var SOL_CACHE_FILE_PREFIX = 'sol-cache-file-'; @@ -89,7 +103,7 @@ var SOL_CACHE_FILE = null; var editor = ace.edit("input"); - var session = editor.getSession(); + var sessions = {}; var Range = ace.require('ace/range').Range; var errMarkerId = null; @@ -106,11 +120,22 @@ SOL_CACHE_FILE = getFiles()[0]; - editor.setValue( window.localStorage[SOL_CACHE_FILE], -1); + var files = getFiles(); + for (var x in files) + sessions[files[x]] = newEditorSession(files[x]) + + editor.setSession( sessions[SOL_CACHE_FILE] ); editor.resize(true); - session.setMode("ace/mode/javascript"); - session.setTabSize(4); - session.setUseSoftTabs(true); + + + + function newEditorSession(filename) { + var s = new ace.EditSession(window.localStorage[filename]) + s.setMode("ace/mode/javascript"); + s.setTabSize(4); + s.setUseSoftTabs(true); + return s; + } @@ -283,7 +308,7 @@ if (SOL_CACHE_FILE) { var active = fileTabFromKey(SOL_CACHE_FILE); active.addClass('active'); - editor.setValue( window.localStorage[SOL_CACHE_FILE] || '', -1); + editor.setSession( sessions[SOL_CACHE_FILE] ); editor.focus(); } $('#input').toggle( !!SOL_CACHE_FILE ); @@ -308,6 +333,7 @@ for (var f in localStorage ) { if (f.indexOf( SOL_CACHE_FILE_PREFIX, 0 ) === 0) { files.push(f); + if (!sessions[f]) sessions[f] = newEditorSession(f); } } return files; @@ -393,6 +419,7 @@ function onResize() { editor.resize(); + var session = editor.getSession(); session.setUseWrapMode(document.querySelector('#editorWrap').checked); if(session.getUseWrapMode()) { var characterWidth = editor.renderer.characterWidth; @@ -607,6 +634,9 @@ loadVersion('soljson-latest.js'); editor.getSession().on('change', onChange); + editor.on('changeSession', function(){ + editor.getSession().on('change', onChange); + }) document.querySelector('#optimize').addEventListener('change', compile); From cf7ac73156ee346b395f7e02d6126a2d592d81c6 Mon Sep 17 00:00:00 2001 From: d11e9 Date: Wed, 6 Apr 2016 17:25:50 +0100 Subject: [PATCH 03/14] fix file tab navigation to allow many files --- assets/css/browser-solidity.css | 144 +++++++++++++------- assets/js/app.js | 227 +++++++++++++++++++++----------- index.html | 43 +++--- 3 files changed, 274 insertions(+), 140 deletions(-) diff --git a/assets/css/browser-solidity.css b/assets/css/browser-solidity.css index 3f4e3d9f0f..916663c84a 100644 --- a/assets/css/browser-solidity.css +++ b/assets/css/browser-solidity.css @@ -5,52 +5,99 @@ body { font-weight: normal; } #editor { + position: absolute; top: 0; - left: 0px; + left: 0; width: auto; - bottom: 0px; + bottom: 0; right: 37em; } + +.scroller { + position: absolute; + z-index: 999; + text-align: center; + cursor: pointer; + display: none; + padding: 0 0.9em; + vertical-align: middle; + background-color: rgba(255,255,255,0.8); + height: 100%; +} + +.scroller i { + line-height: 3em; +} + +.scroller-right { + right: 0; +} + +.scroller-left { + left: 0; +} + +.files-wrapper { + position: absolute; + overflow: hidden; + top: 0; + left: 3em; + right: 3em; +} + #files { + list-style: none; + margin: 0; font-size: 15px; height: 2.5em; box-sizing: border-box; line-height: 2em; padding: 0.5em 0 0; + position: relative; + left: 0; + top:0; + min-width:3000px; + border-bottom: 0 none; } -#files .file, -#files .newFile { +#files .file { display: inline-block; padding: 0 0.6em; box-sizing: border-box; - background-color: #f0f0f0; + background-color: #F4F6FF; cursor: pointer; - margin-right: 0.5em; + border-right: 0.5em solid white; position: relative; + display:table-cell; + text-align: center; + vertical-align: middle; + color: #999; } -#files .newFile, -#files .toggleRHP { - background-color: #B1EAC5; +.newFile, +.toggleRHP { + display: block; + float: left; + margin-top: 0.5em; padding: 0.6em; font-weight: bold; cursor: pointer; color: black; } -#files .toggleRHP { +.toggleRHP { float: right; - width: 2em; - box-sizing: border-box; + position: absolute; + right: 0; } #files .file.active { + color: black; font-weight: bold; border-bottom: 0 none; - padding-right: 2.5em; + padding-right: 2em; } #files .file .remove { position: absolute; @@ -76,6 +123,8 @@ body { #files .file.active .remove { display: inline-block; } #input { + border-top: 3px solid #F4F6FF; + padding-top: 0.5em; font-size: 15px; position: absolute; top: 2.5em; @@ -93,42 +142,30 @@ body { right: 0; bottom: 0px; overflow: auto; - border-left: 3px solid #efefef; box-sizing: border-box; } #output { - border-top: 3px solid #efefef; display: block; } #header { - font-size: 14px; font-size: 12px; } -#header #helpButton { - float: left; - padding: 1.2em; - padding-left: 2.2em; - font-size: 1.5em; - cursor: pointer; - margin: auto; - color: #000; - outline: none; - -} - #header #solIcon { float: right; - height: 5.1em; + height: 100%; background-color: white; } #header #menu { + border-bottom: 3px solid #F4F6FF; overflow: hidden; - background-color: #efefef; - height: 5.1em; + height: 2em; + font-size: 1.25em; + padding-top: 0.5em; + box-sizing: content-box; } @@ -139,20 +176,26 @@ body { } #header #options li { - color: #aaa; float: left; - padding: 1.2em; - font-size: 1.5em; + padding: 0.5em 0.6em; + font-size: 1em; cursor: pointer; + background-color: transparent; + margin-right: 0.5em; } #header #options li.active { - color: black; + background-color: #F4F6FF; +} + +#header #options li a { + color: inherit; } #header #optionViews { clear: both; overflow: auto; + background-color: #F4F6FF; } #header #optionViews > div { display: none; @@ -259,11 +302,11 @@ body { #output .udapp { border: 0 none; box-shadow: none; - border-bottom: 3px solid #efefef; + border-bottom: 3px solid #F4F6FF; } -.row { +.crow { overflow: auto; display: block; clear: both; @@ -297,7 +340,9 @@ body { word-wrap: break-word; cursor: pointer; position: relative; - margin: 0.25em; + margin: 0.5em; + border-radius: 0.6em; + padding: 1em 1.5em; } .sol.error pre, @@ -306,25 +351,26 @@ body { margin: 0; font-size: 10px; border: 0 none; + padding: 0; + border-radius: 0; } .sol.error .close, .sol.warning .close { font-weight: bold; position: absolute; + color: rgba(0,0,0,0.5); top: 0; right: 0; padding: 0.5em; } .sol.error { - background-color: rgba(255, 0, 0, 0.5); - border: 1px solid #D00909; + background-color: rgba(255, 0, 0, 0.4); } .sol.warning { - background-color: rgba(210, 202, 36, 0.5); - border: 1px solid #BBB427; + background-color: rgba(210, 202, 36, 0.4); } #ghostbar { @@ -338,17 +384,23 @@ body { bottom: 0; } -#dragbar{ +#dragbar { background-color: transparent; position: absolute; - width: 10px; - right: -10px; - top: 0; + width: 1em; + right: -3px; + top: 3em; bottom: 0; cursor: col-resize; z-index: 999; + border-right: 3px solid #F4F6FF; } +#editor .ace-tm .ace_gutter, +#editor .ace-tm .ace_gutter-active-line, +#editor .ace-tm .ace_marker-layer .ace_active-line { + background-color: rgba(225, 229, 251, 0.5); +} input[readonly] { padding: .4em; diff --git a/assets/js/app.js b/assets/js/app.js index cd7b875fdc..ce52675bf2 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -51,51 +51,51 @@ } - // ----------------- storage -------------------- - - function syncStorage() { - - if (!chrome || !chrome.storage || !chrome.storage.sync) return; - - var obj = {} - var done = false; - var count = 0 - var dont = 0; - - function check(key){ - chrome.storage.sync.get( key, function(resp){ - console.log("comparing to cloud", key, resp) - if (typeof resp[key] != 'undefined' && obj[key] !== resp[key] && confirm("Overwrite '" + fileNameFromKey(key) + "'? Click Ok to overwrite local file with file from cloud. Cancel will push your local file to the cloud.")) { - console.log("Overwriting", key ) - localStorage.setItem( key, resp[key] ); - updateFiles(); - } else { - console.log( "add to obj", obj, key) - obj[key] = localStorage[key]; - } - done++ - if (done >= count) chrome.storage.sync.set( obj, function(){ - console.log( "updated cloud files with: ", obj, this, arguments) - }) - }) - } - - for (var y in window.localStorage) { - console.log("checking", y) - obj[y] = window.localStorage.getItem(y); - if (y.indexOf(SOL_CACHE_FILE_PREFIX) !== 0) continue; - count++; - check(y) - } - - - } - - window.syncStorage = syncStorage; - syncStorage() - - - + // ----------------- storage -------------------- + + function syncStorage() { + + if (!chrome || !chrome.storage || !chrome.storage.sync) return; + + var obj = {} + var done = false; + var count = 0 + var dont = 0; + + function check(key){ + chrome.storage.sync.get( key, function(resp){ + console.log("comparing to cloud", key, resp) + if (typeof resp[key] != 'undefined' && obj[key] !== resp[key] && confirm("Overwrite '" + fileNameFromKey(key) + "'? Click Ok to overwrite local file with file from cloud. Cancel will push your local file to the cloud.")) { + console.log("Overwriting", key ) + localStorage.setItem( key, resp[key] ); + updateFiles(); + } else { + console.log( "add to obj", obj, key) + obj[key] = localStorage[key]; + } + done++ + if (done >= count) chrome.storage.sync.set( obj, function(){ + console.log( "updated cloud files with: ", obj, this, arguments) + }) + }) + } + + for (var y in window.localStorage) { + console.log("checking", y) + obj[y] = window.localStorage.getItem(y); + if (y.indexOf(SOL_CACHE_FILE_PREFIX) !== 0) continue; + count++; + check(y) + } + + + } + + window.syncStorage = syncStorage; + syncStorage() + + + // ----------------- editor ---------------------- var SOL_CACHE_FILE_PREFIX = 'sol-cache-file-'; @@ -103,7 +103,8 @@ var SOL_CACHE_FILE = null; var editor = ace.edit("input"); - var sessions = {}; + var sessions = {}; + var Range = ace.require('ace/range').Range; var errMarkerId = null; @@ -120,22 +121,21 @@ SOL_CACHE_FILE = getFiles()[0]; - var files = getFiles(); - for (var x in files) - sessions[files[x]] = newEditorSession(files[x]) - - editor.setSession( sessions[SOL_CACHE_FILE] ); + + var files = getFiles(); + for (var x in files) + sessions[files[x]] = newEditorSession(files[x]) + + editor.setSession( sessions[SOL_CACHE_FILE] ); editor.resize(true); - - - - function newEditorSession(filename) { - var s = new ace.EditSession(window.localStorage[filename]) - s.setMode("ace/mode/javascript"); - s.setTabSize(4); - s.setUseSoftTabs(true); - return s; - } + + function newEditorSession(filekey) { + var s = new ace.EditSession(window.localStorage[filekey], "ace/mode/javascript") + s.setTabSize(4); + s.setUseSoftTabs(true); + aces[filekey] = s; + return s; + } @@ -143,7 +143,9 @@ $('#options li').click(function(ev){ var $el = $(this); - var cls = /[a-z]+View/.exec( $el.get(0).className )[0]; + var match = /[a-z]+View/.exec( $el.get(0).className ); + if (!match) return; + var cls = match[0]; if (!$el.hasClass('active')) { $el.parent().find('li').removeClass('active'); $('#optionViews').attr('class', '').addClass(cls); @@ -196,7 +198,7 @@ $('#gist').click(function(){ if (confirm("Are you sure you want to publish all your files anonymously as a public gist on github.com?")) { - + var files = {}; var filesArr = getFiles(); var description = "Created using soleditor: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://chriseth.github.io/browser-solidity/?gist="; @@ -225,6 +227,7 @@ // ----------------- file selector------------- + var $filesEl = $('#files'); $filesEl.on('click','.newFile', function() { while (window.localStorage[SOL_CACHE_UNTITLED + untitledCount]) @@ -308,16 +311,17 @@ if (SOL_CACHE_FILE) { var active = fileTabFromKey(SOL_CACHE_FILE); active.addClass('active'); - editor.setSession( sessions[SOL_CACHE_FILE] ); + editor.setSession( sessions[SOL_CACHE_FILE] ); editor.focus(); } $('#input').toggle( !!SOL_CACHE_FILE ); $('#output').toggle( !!SOL_CACHE_FILE ); + reAdjust(); } function fileTabTemplate(key) { var name = fileNameFromKey(key); - return $(''+name+''); + return $('
  • '+name+'
  • '); } function fileKey( name ) { @@ -333,7 +337,7 @@ for (var f in localStorage ) { if (f.indexOf( SOL_CACHE_FILE_PREFIX, 0 ) === 0) { files.push(f); - if (!sessions[f]) sessions[f] = newEditorSession(f); + if (!sessions[f]) sessions[f] = newEditorSession(f); } } return files; @@ -341,6 +345,68 @@ updateFiles(); + + var hidWidth; + + function widthOfList (){ + var itemsWidth = 0; + $('.file').each(function(){ + var itemWidth = $(this).outerWidth(); + itemsWidth += itemWidth; + }); + return itemsWidth; + }; + + function widthOfHidden(){ + return (($('.files-wrapper').outerWidth()) - widthOfList() - getLeftPosi()); + }; + + function widthOfVisible(){ + return $('.files-wrapper').outerWidth(); + }; + + function getLeftPosi(){ + return $('#files').position().left; + }; + + function reAdjust (){ + + console.log("left start: ", getLeftPosi()) + console.log("outer width: ", widthOfVisible(), "content width: ", widthOfList(), " left+vis: ", getLeftPosi() + widthOfVisible()) + if (widthOfList() + getLeftPosi() > + widthOfVisible()) { + console.log( "show right scroll") + $('.scroller-right').fadeIn('fast'); + } else { + console.log( "hide right scroll") + $('.scroller-right').fadeOut('fast'); + } + + if (getLeftPosi()<0) { + console.log( "show left scroll") + $('.scroller-left').fadeIn('fast'); + } else { + console.log( "hide left scroll") + $('.scroller-left').fadeOut('fast'); + $('#files').animate({left: getLeftPosi() + "px"},'slow'); + } + } + + $('.scroller-right').click(function() { + var delta = (getLeftPosi() - 200) + console.log(delta) + $('#files').animate({left: delta + "px"},'slow',function(){ + reAdjust(); + }); + }); + + $('.scroller-left').click(function() { + var delta = Math.min( (getLeftPosi() + 200), 0 ) + console.log(delta) + $('#files').animate({left: delta + "px"},'slow',function(){ + reAdjust(); + }); + }); + // ----------------- version selector------------- // var soljsonSources is provided by bin/list.js @@ -395,6 +461,7 @@ dragging = false; setEditorSize(delta); window.localStorage.setItem(EDITOR_SIZE_CACHE_KEY, delta); + reAdjust(); } }); @@ -408,10 +475,11 @@ var hidingRHP = false; $('.toggleRHP').click(function(){ - hidingRHP = !hidingRHP; - setEditorSize( hidingRHP ? 0 : window.localStorage[EDITOR_SIZE_CACHE_KEY] ); - $('.toggleRHP').toggleClass('hiding', hidingRHP); - if (!hidingRHP) compile(); + hidingRHP = !hidingRHP; + setEditorSize( hidingRHP ? 0 : window.localStorage[EDITOR_SIZE_CACHE_KEY] ); + $('.toggleRHP i').toggleClass('fa-angle-double-right', !hidingRHP); + $('.toggleRHP i').toggleClass('fa-angle-double-left', hidingRHP); + if (!hidingRHP) compile(); }); @@ -419,7 +487,7 @@ function onResize() { editor.resize(); - var session = editor.getSession(); + var session = editor.getSession(); session.setUseWrapMode(document.querySelector('#editorWrap').checked); if(session.getUseWrapMode()) { var characterWidth = editor.renderer.characterWidth; @@ -429,6 +497,7 @@ session.setWrapLimit(parseInt(contentWidth / characterWidth, 10)); } } + reAdjust(); } window.onresize = onResize; onResize(); @@ -634,9 +703,9 @@ loadVersion('soljson-latest.js'); editor.getSession().on('change', onChange); - editor.on('changeSession', function(){ - editor.getSession().on('change', onChange); - }) + editor.on('changeSession', function(){ + editor.getSession().on('change', onChange); + }) document.querySelector('#optimize').addEventListener('change', compile); @@ -756,9 +825,9 @@ $txOrigin.empty(); for( var a in accounts) { $txOrigin.append($('