diff --git a/core/agplv3-88x31.png b/core/agplv3-88x31.png deleted file mode 100644 index 7a472a0d..00000000 Binary files a/core/agplv3-88x31.png and /dev/null differ diff --git a/core/client.js b/core/client.js index a97fbd5d..788da5ca 100644 --- a/core/client.js +++ b/core/client.js @@ -8,8 +8,30 @@ var gSendKeyEvents = false; var gSendDeviceOrientationEvents = false; var gGeolocatorWatch; +var gEditor; +var gBackup; + var kMaxCommandHistory = 16; +window.addEventListener("keydown", function(event) { + if (event.keyCode == 69 && event.altKey) { + if (!editing()) { + edit(); + event.preventDefault(); + } + } else if (event.keyCode == 83 && (event.altKey || event.ctrlKey)) { + if (editing()) { + save(); + event.preventDefault(); + } + } else if (event.keyCode == 66 && event.altKey) { + if (editing()) { + closeEditor(); + event.preventDefault(); + } + } +}); + function keydown(event) { if (event.keyCode == 13) { gCommandHistory.push(document.getElementById("input").value); @@ -32,9 +54,181 @@ function keydown(event) { input.value = gCommandHistory.shift(); event.preventDefault(); } - } else if (event.keyCode == 69 && event.altKey) { - window.location.href = url() + "/edit"; - event.preventDefault(); + } +} + +function ensureLoaded(nodes, callback) { + if (!nodes.length) { + callback(); + return; + } + + var search = nodes.shift(); + var head = document.head; + var found = false; + for (var i = 0; i < head.childNodes.length; i++) { + if (head.childNodes[i].tagName == search.tagName) { + var match = true; + for (var attribute in search.attributes) { + if (head.childNodes[i].attributes[attribute].value != search.attributes[attribute]) { + match = false; + } + } + if (match) { + found = true; + break; + } + } + } + if (found) { + ensureLoaded(nodes, callback); + } else { + var node = document.createElement(search.tagName); + node.onreadystatechange = node.onload = function() { + ensureLoaded(nodes, callback); + }; + for (var attribute in search.attributes) { + node.setAttribute(attribute, search.attributes[attribute]); + } + head.insertBefore(node, head.firstChild); + } +} + +function editing() { + return document.getElementById("editPane").style.display != 'none'; +} + +function edit() { + if (editing()) { + return; + } + + ensureLoaded([ + {tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/codemirror.min.js"}}, + {tagName: "link", attributes: {rel: "stylesheet", href: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/theme/base16-dark.min.css"}}, + {tagName: "link", attributes: {rel: "stylesheet", href: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/search/matchesonscrollbar.min.css"}}, + {tagName: "link", attributes: {rel: "stylesheet", href: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/dialog/dialog.min.css"}}, + {tagName: "link", attributes: {rel: "stylesheet", href: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/codemirror.min.css"}}, + {tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/edit/trailingspace.min.js"}}, + {tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/dialog/dialog.min.js"}}, + {tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/search/search.min.js"}}, + {tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/search/searchcursor.min.js"}}, + {tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/search/jump-to-line.min.js"}}, + {tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/search/matchesonscrollbar.min.js"}}, + {tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/addon/scroll/annotatescrollbar.min.js"}}, + {tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.12.0/mode/javascript/javascript.min.js"}}, + ], function() { + load(); + }); + +} + +function load() { + var request = new XMLHttpRequest(); + request.addEventListener("loadend", function() { + if (request.status == 200) { + document.getElementById("editPane").style.display = 'flex'; + if (!gEditor) { + gEditor = CodeMirror.fromTextArea(document.getElementById("editor"), { + 'theme': 'base16-dark', + 'lineNumbers': true, + 'tabSize': 4, + 'indentUnit': 4, + 'indentWithTabs': true, + 'showTrailingSpace': true, + }); + } + gEditor.setValue(request.responseText); + gEditor.focus(); + gBackup = request.responseText; + } + }); + request.addEventListener("error", function() { + alert("Error loading source."); + closeEditor(); + }); + request.addEventListener("timeout", function() { + alert("Timed out loading source."); + closeEditor(); + }); + request.addEventListener("abort", function() { + alert("Loading source aborted."); + closeEditor(); + }); + request.open("GET", url() + "/view"); + request.send(); +} + +function closeEditor() { + document.getElementById("editPane").style.display = 'none'; +} + +function revert() { + gEditor.setValue(gBackup); +} + +function explodePath() { + return /^\/~([^\/]+)\/([^\/]+)(.*)/.exec(window.location.pathname); +} + +function packageOwner() { + return explodePath()[1]; +} + +function packageName() { + return explodePath()[2]; +} + +function save(newName) { + document.getElementById("save").disabled = true; + document.getElementById("saveAs").disabled = true; + + var contents = gEditor.getValue(); + var run = document.getElementById("run").checked; + + var request = new XMLHttpRequest(); + + var always = function() { + document.getElementById("save").disabled = false; + document.getElementById("saveAs").disabled = false; + }; + + request.addEventListener("error", function() { + alert("Error saving: " + request.responseText); + always(); + }); + request.addEventListener("loadend", function() { + if (request.status == 200) { + gBackup = contents; + if (run) { + if (newName) { + window.location.href = "/~" + packageOwner() + "/" + newName + hash(); + } else { + reconnect(); + } + } + } else { + alert("Unable to save: " + request.responseText); + } + always(); + }); + request.addEventListener("timeout", function() { + alert("Timed out saving: " + request.responseText); + always(); + }); + request.addEventListener("abort", function() { + alert("Save aborted: " + request.responseText); + always(); + }); + request.open("POST", newName ? newName + "/save" : packageName() + "/save", true); + request.setRequestHeader("Content-Type", "text/plain"); + request.send(contents); +} + +function saveAs() { + var newName = prompt("Save as:", packageName()); + if (newName) { + save(newName); } } @@ -553,6 +747,16 @@ function submitButton() { send({event: "submit", value: data}); } +function reconnect() { + let oldSocket = gSocket; + gSocket = null + oldSocket.onclose = function() {} + oldSocket.onmessage = function() {} + oldSocket.close(); + split(document.getElementById("terminals"), [{name: "terminal_"}]); + connectSocket(); +} + function connectSocket() { if (!gSocket || gSocket.readyState == gSocket.CLOSED) { gSocket = new WebSocket( diff --git a/core/edit.html b/core/edit.html deleted file mode 100644 index a84b3b25..00000000 --- a/core/edit.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - Web Terminal - - - - - - - - - - - - - - - - - - - - - - - diff --git a/core/editor.js b/core/editor.js deleted file mode 100644 index db9c2a10..00000000 --- a/core/editor.js +++ /dev/null @@ -1,118 +0,0 @@ -var gBackup; -var gEditor; - -window.addEventListener("load", function() { - gEditor = CodeMirror.fromTextArea(document.getElementById("editor"), { - 'theme': 'base16-dark', - 'lineNumbers': true, - 'tabSize': 4, - 'indentUnit': 4, - 'indentWithTabs': true, - 'showTrailingSpace': true, - }); - gBackup = gEditor.getValue(); - gEditor.focus(); -}); - -window.addEventListener("keydown", function(event) { - if (event.keyCode == 83 && event.altKey) { - save(); - } else if (event.keyCode == 66 && event.altKey) { - back(); - } -}); - -function explodePath() { - return /^\/~([^\/]+)\/([^\/]+)(.*)/.exec(window.location.pathname); -} - -function packageOwner() { - return explodePath()[1]; -} - -function packageName() { - return explodePath()[2]; -} - -function back(uri) { - if (uri) { - window.location.pathname = uri; - } else { - window.location.pathname = "/~" + packageOwner() + "/" + packageName(); - } -} - -function save(newName) { - document.getElementById("save").disabled = true; - document.getElementById("saveAs").disabled = true; - - var contents = gEditor.getValue(); - var run = document.getElementById("run").checked; - - var request = new XMLHttpRequest(); - - var always = function() { - document.getElementById("save").disabled = false; - document.getElementById("saveAs").disabled = false; - }; - - request.addEventListener("error", function() { - alert("Error saving: " + request.responseText); - always(); - }); - request.addEventListener("loadend", function() { - if (request.status == 200) { - gBackup = contents; - if (run) { - back(request.responseText); - } - } else { - alert("Unable to save: " + request.responseText); - } - always(); - }); - request.addEventListener("timeout", function() { - alert("Timed out saving: " + request.responseText); - always(); - }); - request.addEventListener("abort", function() { - alert("Save aborted: " + request.responseText); - always(); - }); - request.open("POST", newName ? "../" + newName + "/save" : "save", true); - request.setRequestHeader("Content-Type", "text/plain"); - request.send(contents); -} - -function saveAs() { - var newName = prompt("Save as:", packageName()); - if (newName) { - save(newName); - } -} - -function revert() { - gEditor.setValue(gBackup); -} - -function addLicense() { - var contents = "/*\n" + - "\n" + - "Copyright (C) \n".replace("", new Date().getFullYear()) + - "\n" + - "This program is free software: you can redistribute it and/or modify\n" + - "it under the terms of the GNU Affero General Public License as published by\n" + - "the Free Software Foundation, either version 3 of the License, or\n" + - "(at your option) any later version.\n" + - "\n" + - "This program is distributed in the hope that it will be useful,\n" + - "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + - "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + - "GNU Affero General Public License for more details.\n" + - "\n" + - "You should have received a copy of the GNU Affero General Public License\n" + - "along with this program. If not, see .\n" + - "*/\n\n" + - gEditor.getValue(); - gEditor.setValue(contents); -} diff --git a/core/index.html b/core/index.html index 822d3617..9734ed7e 100644 --- a/core/index.html +++ b/core/index.html @@ -12,17 +12,31 @@ 😎 Tilde Friends home - edit + edit view source about update available! refresh to update -
-
- > - +
+ +
+
+
+ > + +
+
diff --git a/core/style.css b/core/style.css index 180cbf2f..8f399b21 100644 --- a/core/style.css +++ b/core/style.css @@ -102,11 +102,6 @@ a:active, .command:active { padding: 0; } -.CodeMirror-scroll { - height: 100%; - padding: 0; -} - .cm-tab { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAYAAAAkuj5RAAAAAXNSR0IArs4c6QAAAGFJREFUSMft1LsRQFAQheHPowAKoACx3IgEKtaEHujDjORSgWTH/ZOdnZOcM/sgk/kFFWY0qV8foQwS4MKBCS3qR6ixBJvElOobYAtivseIE120FaowJPN75GMu8j/LfMwNjh4HUpwg4LUAAAAASUVORK5CYII=); background-position: right; diff --git a/core/terminal.js b/core/terminal.js index 547db2ec..9b47072c 100644 --- a/core/terminal.js +++ b/core/terminal.js @@ -7,7 +7,6 @@ var kStaticFiles = [ {uri: '/favicon.png', path: 'favicon.png', type: 'image/png'}, {uri: '/client.js', path: 'client.js', type: 'text/javascript; charset=UTF-8'}, {uri: '/editor.js', path: 'editor.js', type: 'text/javascript; charset=UTF-8'}, - {uri: '/agplv3-88x31.png', path: 'agplv3-88x31.png', type: 'image/png'}, {uri: '/robots.txt', path: 'robots.txt', type: 'text/plain; charset=UTF-8'}, ];