diff --git a/www/assets/app.js b/www/assets/app.js index e1fb396..71ba823 100644 --- a/www/assets/app.js +++ b/www/assets/app.js @@ -1,581 +1,580 @@ (function() { - 'use strict'; + 'use strict'; - var app = angular.module('DockerPlay', ['ngMaterial']); + var app = angular.module('DockerPlay', ['ngMaterial']); - // Automatically redirects user to a new session when bypassing captcha. - // Controller keeps code/logic separate from the HTML - app.controller("BypassController", ['$scope', '$log', '$http', '$location', '$timeout', function($scope, $log, $http, $location, $timeout) { - setTimeout(function() { - document.getElementById("welcomeFormBypass").submit(); - }, 500); - }]); + // Automatically redirects user to a new session when bypassing captcha. + // Controller keeps code/logic separate from the HTML + app.controller("BypassController", ['$scope', '$log', '$http', '$location', '$timeout', function($scope, $log, $http, $location, $timeout) { + setTimeout(function() { + document.getElementById("welcomeFormBypass").submit(); + }, 500); + }]); - function SessionBuilderModalController($mdDialog, $scope) { - $scope.createBuilderTerminal(); + function SessionBuilderModalController($mdDialog, $scope) { + $scope.createBuilderTerminal(); - $scope.closeSessionBuilder = function() { - $mdDialog.cancel(); - } + $scope.closeSessionBuilder = function() { + $mdDialog.cancel(); + } + } + + app.controller('PlayController', ['$scope', '$log', '$http', '$location', '$timeout', '$mdDialog', '$window', 'TerminalService', 'KeyboardShortcutService', 'InstanceService', function($scope, $log, $http, $location, $timeout, $mdDialog, $window, TerminalService, KeyboardShortcutService, InstanceService) { + $scope.sessionId = window.location.pathname.replace('/p/', ''); + $scope.instances = []; + $scope.idx = {}; + $scope.selectedInstance = null; + $scope.isAlive = true; + $scope.ttl = '--:--:--'; + $scope.connected = true; + $scope.isInstanceBeingCreated = false; + $scope.newInstanceBtnText = '+ Add new instance'; + $scope.deleteInstanceBtnText = 'Delete'; + $scope.isInstanceBeingDeleted = false; + + var selectedKeyboardShortcuts = KeyboardShortcutService.getCurrentShortcuts(); + + angular.element($window).bind('resize', function() { + if ($scope.selectedInstance) { + $scope.resize($scope.selectedInstance.term.proposeGeometry()); + } + }); + + $scope.$on("settings:shortcutsSelected", function(e, preset) { + selectedKeyboardShortcuts = preset; + }); + + + $scope.showAlert = function(title, content, parent) { + $mdDialog.show( + $mdDialog.alert() + .parent(angular.element(document.querySelector(parent || '#popupContainer'))) + .clickOutsideToClose(true) + .title(title) + .textContent(content) + .ok('Got it!') + ); } - app.controller('PlayController', ['$scope', '$log', '$http', '$location', '$timeout', '$mdDialog', '$window', 'TerminalService', 'KeyboardShortcutService', 'InstanceService', function($scope, $log, $http, $location, $timeout, $mdDialog, $window, TerminalService, KeyboardShortcutService, InstanceService) { - $scope.sessionId = window.location.pathname.replace('/p/', ''); - $scope.instances = []; - $scope.idx = {}; - $scope.selectedInstance = null; - $scope.isAlive = true; - $scope.ttl = '--:--:--'; - $scope.connected = true; - $scope.isInstanceBeingCreated = false; + $scope.resize = function(geometry) { + $scope.socket.emit('viewport resize', geometry.cols, geometry.rows); + } + + KeyboardShortcutService.setResizeFunc($scope.resize); + + $scope.closeSession = function() { + $scope.socket.emit('session close'); + } + + $scope.upsertInstance = function(info) { + var i = info; + if (!$scope.idx[i.name]) { + $scope.instances.push(i); + i.buffer = ''; + $scope.idx[i.name] = i; + } else { + $scope.idx[i.name].ip = i.ip; + $scope.idx[i.name].hostname = i.hostname; + } + + return $scope.idx[i.name]; + } + + $scope.newInstance = function() { + updateNewInstanceBtnState(true); + $http({ + method: 'POST', + url: '/sessions/' + $scope.sessionId + '/instances', + data : { ImageName : InstanceService.getDesiredImage() } + }).then(function(response) { + var i = $scope.upsertInstance(response.data); + $scope.showInstance(i); + }, function(response) { + if (response.status == 409) { + $scope.showAlert('Max instances reached', 'Maximum number of instances reached') + } + }).finally(function() { + updateNewInstanceBtnState(false); + }); + } + + $scope.setSessionState = function(state) { + $scope.ready = state; + + if (!state) { + $mdDialog.show({ + controller: SessionBuilderModalController, + contentElement: '#builderDialog', + parent: angular.element(document.body), + clickOutsideToClose: false, + scope: $scope, + preserveScope: true + }); + } + } + + $scope.getSession = function(sessionId) { + $http({ + method: 'GET', + url: '/sessions/' + $scope.sessionId, + }).then(function(response) { + $scope.setSessionState(response.data.ready); + + if (response.data.created_at) { + $scope.expiresAt = moment(response.data.expires_at); + setInterval(function() { + $scope.ttl = moment.utc($scope.expiresAt.diff(moment())).format('HH:mm:ss'); + $scope.$apply(); + }, 1000); + } + var socket = io({ path: '/sessions/' + sessionId + '/ws' }); + + socket.on('session ready', function(ready) { + $scope.setSessionState(ready); + }); + + socket.on('session builder out', function(data) { + $scope.builderTerminal.write(data); + }); + + socket.on('terminal out', function(name, data) { + var instance = $scope.idx[name]; + + if (!instance) { + // instance is new and was created from another client, we should add it + $scope.upsertInstance({ name: name }); + instance = $scope.idx[name]; + } + if (!instance.term) { + instance.buffer += data; + } else { + instance.term.write(data); + } + }); + + socket.on('session end', function() { + $scope.showAlert('Session timed out!', 'Your session has expired and all of your instances have been deleted.', '#sessionEnd') + $scope.isAlive = false; + }); + + socket.on('viewport', function(rows, cols) { + }); + + socket.on('new instance', function(name, ip, hostname) { + $scope.upsertInstance({ name: name, ip: ip, hostname: hostname }); + $scope.$apply(function() { + if ($scope.instances.length == 1) { + $scope.showInstance($scope.instances[0]); + } + }); + }); + + socket.on('delete instance', function(name) { + $scope.removeInstance(name); + $scope.$apply(); + }); + + socket.on('viewport resize', function(cols, rows) { + // viewport has changed, we need to resize all terminals + + $scope.instances.forEach(function(instance) { + instance.term.resize(cols, rows); + }); + }); + + socket.on('connect_error', function() { + $scope.connected = false; + }); + socket.on('connect', function() { + $scope.connected = true; + }); + + socket.on('instance stats', function(name, mem, cpu, isManager, ports) { + $scope.idx[name].mem = mem; + $scope.idx[name].cpu = cpu; + $scope.idx[name].isManager = isManager; + $scope.idx[name].ports = ports; + $scope.$apply(); + }); + + $scope.socket = socket; + + var i = response.data; + for (var k in i.instances) { + var instance = i.instances[k]; + $scope.instances.push(instance); + $scope.idx[instance.name] = instance; + } + + // If instance is passed in URL, select it + let inst = $scope.idx[$location.hash()]; + if (inst) $scope.showInstance(inst); + }, function(response) { + if (response.status == 404) { + document.write('session not found'); + return + } + }); + } + + $scope.getProxyUrl = function(instance, port) { + var url = window.location.protocol + '//pwd' + instance.ip.replace(/\./g, '-') + '-' + port + '.' + window.location.host; + + return url; + } + + $scope.showInstance = function(instance) { + $scope.selectedInstance = instance; + $location.hash(instance.name); + if (!instance.creatingTerminal) { + if (!instance.term) { + $timeout(function() { + createTerminal(instance); + TerminalService.setFontSize(TerminalService.getFontSize()); + instance.term.focus(); + }, 0, false); + return + } + } + $timeout(function() { + instance.term.focus(); + }, 0, false); + } + + $scope.removeInstance = function(name) { + if ($scope.idx[name]) { + delete $scope.idx[name]; + $scope.instances = $scope.instances.filter(function(i) { + return i.name != name; + }); + if ($scope.instances.length) { + $scope.showInstance($scope.instances[0]); + } + } + } + + $scope.deleteInstance = function(instance) { + updateDeleteInstanceBtnState(true); + $http({ + method: 'DELETE', + url: '/sessions/' + $scope.sessionId + '/instances/' + instance.name, + }).then(function(response) { + $scope.removeInstance(instance.name); + }, function(response) { + console.log('error', response); + }).finally(function() { + updateDeleteInstanceBtnState(false); + }); + } + + $scope.getSession($scope.sessionId); + + $scope.createBuilderTerminal = function() { + var builderTerminalContainer = document.getElementById('builder-terminal'); + // For some reason the dialog DOM might not be ready, so we just keep trying + if (!builderTerminalContainer) { + setTimeout($scope.createBuilderTerminal, 100); + return; + } + let term = new Terminal({ + cursorBlink: false + }); + + term.open(builderTerminalContainer); + $scope.builderTerminal = term; + } + function createTerminal(instance, cb) { + if (instance.term) { + return instance.term; + } + + var terminalContainer = document.getElementById('terminal-' + instance.name); + + var term = new Terminal({ + cursorBlink: false + }); + + term.attachCustomKeydownHandler(function(e) { + // Ctrl + Alt + C + if (e.ctrlKey && e.altKey && (e.keyCode == 67)) { + document.execCommand('copy'); + return false; + } + }); + + term.attachCustomKeydownHandler(function(e) { + if (selectedKeyboardShortcuts == null) + return; + var presets = selectedKeyboardShortcuts.presets + .filter(function(preset) { return preset.keyCode == e.keyCode }) + .filter(function(preset) { return (preset.metaKey == undefined && !e.metaKey) || preset.metaKey == e.metaKey }) + .filter(function(preset) { return (preset.ctrlKey == undefined && !e.ctrlKey) || preset.ctrlKey == e.ctrlKey }) + .filter(function(preset) { return (preset.altKey == undefined && !e.altKey) || preset.altKey == e.altKey }) + .forEach(function(preset) { preset.action({ terminal : term })}); + }); + + term.open(terminalContainer); + + // Set geometry during the next tick, to avoid race conditions. + setTimeout(function() { + $scope.resize(term.proposeGeometry()); + }, 4); + + term.on('data', function(d) { + $scope.socket.emit('terminal in', instance.name, d); + }); + + instance.term = term; + + if (instance.buffer) { + term.write(instance.buffer); + instance.buffer = ''; + } + + if (cb) { + cb(); + } + } + + function updateNewInstanceBtnState(isInstanceBeingCreated) { + if (isInstanceBeingCreated === true) { + $scope.newInstanceBtnText = '+ Creating...'; + $scope.isInstanceBeingCreated = true; + } else { $scope.newInstanceBtnText = '+ Add new instance'; + $scope.isInstanceBeingCreated = false; + } + } + + function updateDeleteInstanceBtnState(isInstanceBeingDeleted) { + if (isInstanceBeingDeleted === true) { + $scope.deleteInstanceBtnText = 'Deleting...'; + $scope.isInstanceBeingDeleted = true; + } else { $scope.deleteInstanceBtnText = 'Delete'; $scope.isInstanceBeingDeleted = false; - - var selectedKeyboardShortcuts = KeyboardShortcutService.getCurrentShortcuts(); + } + } + }]) + .config(['$mdIconProvider', '$locationProvider', function($mdIconProvider, $locationProvider) { + $locationProvider.html5Mode({enabled: true, requireBase: false}); + $mdIconProvider.defaultIconSet('../assets/social-icons.svg', 24); + }]) + .component('settingsIcon', { + template : "settings", + controller : function($mdDialog) { + var $ctrl = this; + $ctrl.onClick = function() { + $mdDialog.show({ + controller : function() {}, + template : "", + parent: angular.element(document.body), + clickOutsideToClose : true + }) + } + } + }) + .component("settingsDialog", { + templateUrl : "settings-modal.html", + controller : function($mdDialog, KeyboardShortcutService, $rootScope, InstanceService, TerminalService) { + var $ctrl = this; + $ctrl.$onInit = function() { + $ctrl.keyboardShortcutPresets = KeyboardShortcutService.getAvailablePresets(); + $ctrl.selectedShortcutPreset = KeyboardShortcutService.getCurrentShortcuts(); + $ctrl.instanceImages = InstanceService.getAvailableImages(); + $ctrl.selectedInstanceImage = InstanceService.getDesiredImage(); + $ctrl.terminalFontSizes = TerminalService.getFontSizes(); + }; - angular.element($window).bind('resize', function() { - if ($scope.selectedInstance) { - $scope.resize($scope.selectedInstance.term.proposeGeometry()); - } - }); + $ctrl.currentShortcutConfig = function(value) { + if (value !== undefined) { + value = JSON.parse(value); + KeyboardShortcutService.setCurrentShortcuts(value); + $ctrl.selectedShortcutPreset = angular.copy(KeyboardShortcutService.getCurrentShortcuts()); + $rootScope.$broadcast('settings:shortcutsSelected', $ctrl.selectedShortcutPreset); + } + return JSON.stringify(KeyboardShortcutService.getCurrentShortcuts()); + }; - $scope.$on("settings:shortcutsSelected", function(e, preset) { - selectedKeyboardShortcuts = preset; - }); - - - $scope.showAlert = function(title, content, parent) { - $mdDialog.show( - $mdDialog.alert() - .parent(angular.element(document.querySelector(parent || '#popupContainer'))) - .clickOutsideToClose(true) - .title(title) - .textContent(content) - .ok('Got it!') - ); + $ctrl.currentDesiredInstanceImage = function(value) { + if (value !== undefined) { + InstanceService.setDesiredImage(value); + } + return InstanceService.getDesiredImage(value); + }; + $ctrl.currentTerminalFontSize = function(value) { + if (value !== undefined) { + // set font size + TerminalService.setFontSize(value); + return; } - $scope.resize = function(geometry) { - $scope.socket.emit('viewport resize', geometry.cols, geometry.rows); + return TerminalService.getFontSize(); + } + + $ctrl.close = function() { + $mdDialog.cancel(); + } + } + }) + .service("InstanceService", function($http) { + var instanceImages = []; + _prepopulateAvailableImages(); + + return { + getAvailableImages : getAvailableImages, + setDesiredImage : setDesiredImage, + getDesiredImage : getDesiredImage, + }; + + function getAvailableImages() { + return instanceImages; + } + + function getDesiredImage() { + var image = localStorage.getItem("settings.desiredImage"); + if (image == null) + return instanceImages[0]; + return image; + } + + function setDesiredImage(image) { + if (image === null) + localStorage.removeItem("settings.desiredImage"); + else + localStorage.setItem("settings.desiredImage", image); + } + + function _prepopulateAvailableImages() { + return $http + .get("/instances/images") + .then(function(response) { + instanceImages = response.data; + }); + } + + }) + .run(function(InstanceService) { /* forcing pre-populating for now */ }) + .service("KeyboardShortcutService", ['TerminalService', function(TerminalService) { + var resizeFunc; + + return { + getAvailablePresets : getAvailablePresets, + getCurrentShortcuts : getCurrentShortcuts, + setCurrentShortcuts : setCurrentShortcuts, + setResizeFunc : setResizeFunc + }; + + function setResizeFunc(f) { + resizeFunc = f; + } + + function getAvailablePresets() { + return [ + { name : "None", presets : [ + { description : "Toggle terminal fullscreen", command : "Alt+enter", altKey : true, keyCode : 13, action : function(context) { TerminalService.toggleFullscreen(context.terminal, resizeFunc); }} + ] }, + { + name : "Mac OSX", + presets : [ + { description : "Clear terminal", command : "Cmd+K", metaKey : true, keyCode : 75, action : function(context) { context.terminal.clear(); }}, + { description : "Toggle terminal fullscreen", command : "Alt+enter", altKey : true, keyCode : 13, action : function(context) { TerminalService.toggleFullscreen(context.terminal, resizeFunc); }} + ] } + ] + } - KeyboardShortcutService.setResizeFunc($scope.resize); + function getCurrentShortcuts() { + var shortcuts = localStorage.getItem("shortcut-preset-name"); + if (shortcuts == null) { + shortcuts = getDefaultShortcutPrefixName(); + if (shortcuts == null) + return null; + } - $scope.closeSession = function() { - $scope.socket.emit('session close'); - } + var preset = getAvailablePresets() + .filter(function(preset) { return preset.name == shortcuts; }); + if (preset.length == 0) + console.error("Unable to find preset with name '" + shortcuts + "'"); + return preset[0]; + return (shortcuts == null) ? null : JSON.parse(shortcuts); + } - $scope.upsertInstance = function(info) { - var i = info; - if (!$scope.idx[i.name]) { - $scope.instances.push(i); - i.buffer = ''; - $scope.idx[i.name] = i; - } else { - $scope.idx[i.name].ip = i.ip; - $scope.idx[i.name].hostname = i.hostname; - } + function setCurrentShortcuts(config) { + localStorage.setItem("shortcut-preset-name", config.name); + } - return $scope.idx[i.name]; - } - - $scope.newInstance = function() { - updateNewInstanceBtnState(true); - $http({ - method: 'POST', - url: '/sessions/' + $scope.sessionId + '/instances', - data : { ImageName : InstanceService.getDesiredImage() } - }).then(function(response) { - var i = $scope.upsertInstance(response.data); - $scope.showInstance(i); - }, function(response) { - if (response.status == 409) { - $scope.showAlert('Max instances reached', 'Maximum number of instances reached') - } - }).finally(function() { - updateNewInstanceBtnState(false); - }); - } - - $scope.setSessionState = function(state) { - $scope.ready = state; - - if (!state) { - $mdDialog.show({ - controller: SessionBuilderModalController, - templateUrl: "session-builder-modal.html", - parent: angular.element(document.body), - clickOutsideToClose: false, - scope: $scope, - preserveScope: true - }); - } - } - - $scope.getSession = function(sessionId) { - $http({ - method: 'GET', - url: '/sessions/' + $scope.sessionId, - }).then(function(response) { - $scope.setSessionState(response.data.ready); - - if (response.data.created_at) { - $scope.expiresAt = moment(response.data.expires_at); - setInterval(function() { - $scope.ttl = moment.utc($scope.expiresAt.diff(moment())).format('HH:mm:ss'); - $scope.$apply(); - }, 1000); - } - var socket = io({ path: '/sessions/' + sessionId + '/ws' }); - - socket.on('session ready', function(ready) { - $scope.setSessionState(ready); - }); - - socket.on('session builder out', function(data) { - $scope.builderTerminal.write(data); - }); - - socket.on('terminal out', function(name, data) { - var instance = $scope.idx[name]; - - if (!instance) { - // instance is new and was created from another client, we should add it - $scope.upsertInstance({ name: name }); - instance = $scope.idx[name]; - } - if (!instance.term) { - instance.buffer += data; - } else { - instance.term.write(data); - } - }); - - socket.on('session end', function() { - $scope.showAlert('Session timed out!', 'Your session has expired and all of your instances have been deleted.', '#sessionEnd') - $scope.isAlive = false; - }); - - socket.on('viewport', function(rows, cols) { - }); - - socket.on('new instance', function(name, ip, hostname) { - $scope.upsertInstance({ name: name, ip: ip, hostname: hostname }); - $scope.$apply(function() { - if ($scope.instances.length == 1) { - $scope.showInstance($scope.instances[0]); - } - }); - }); - - socket.on('delete instance', function(name) { - $scope.removeInstance(name); - $scope.$apply(); - }); - - socket.on('viewport resize', function(cols, rows) { - // viewport has changed, we need to resize all terminals - - $scope.instances.forEach(function(instance) { - instance.term.resize(cols, rows); - }); - }); - - socket.on('connect_error', function() { - $scope.connected = false; - }); - socket.on('connect', function() { - $scope.connected = true; - }); - - socket.on('instance stats', function(name, mem, cpu, isManager, ports) { - $scope.idx[name].mem = mem; - $scope.idx[name].cpu = cpu; - $scope.idx[name].isManager = isManager; - $scope.idx[name].ports = ports; - $scope.$apply(); - }); - - $scope.socket = socket; - - var i = response.data; - for (var k in i.instances) { - var instance = i.instances[k]; - $scope.instances.push(instance); - $scope.idx[instance.name] = instance; - } - - // If instance is passed in URL, select it - let inst = $scope.idx[$location.hash()]; - if (inst) $scope.showInstance(inst); - }, function(response) { - if (response.status == 404) { - document.write('session not found'); - return - } - }); - } - - $scope.getProxyUrl = function(instance, port) { - var url = window.location.protocol + '//pwd' + instance.ip.replace(/\./g, '-') + '-' + port + '.' + window.location.host; - - return url; - } - - $scope.showInstance = function(instance) { - $scope.selectedInstance = instance; - $location.hash(instance.name); - if (!instance.creatingTerminal) { - if (!instance.term) { - $timeout(function() { - createTerminal(instance); - TerminalService.setFontSize(TerminalService.getFontSize()); - instance.term.focus(); - }, 0, false); - return - } - } - $timeout(function() { - instance.term.focus(); - }, 0, false); - } - - $scope.removeInstance = function(name) { - if ($scope.idx[name]) { - delete $scope.idx[name]; - $scope.instances = $scope.instances.filter(function(i) { - return i.name != name; - }); - if ($scope.instances.length) { - $scope.showInstance($scope.instances[0]); - } - } - } - - $scope.deleteInstance = function(instance) { - updateDeleteInstanceBtnState(true); - $http({ - method: 'DELETE', - url: '/sessions/' + $scope.sessionId + '/instances/' + instance.name, - }).then(function(response) { - $scope.removeInstance(instance.name); - }, function(response) { - console.log('error', response); - }).finally(function() { - updateDeleteInstanceBtnState(false); - }); - } - - $scope.getSession($scope.sessionId); - - $scope.createBuilderTerminal = function() { - var builderTerminalContainer = document.getElementById('builder-terminal'); - // For some reason the dialog DOM might not be ready, so we just keep trying - if (!builderTerminalContainer) { - setTimeout($scope.createBuilderTerminal, 100); - return; - } - var term = new Terminal({ - cursorBlink: false - }); - - term.open(builderTerminalContainer); - term.resize(80, 24); - $scope.builderTerminal = term; - } - function createTerminal(instance, cb) { - if (instance.term) { - return instance.term; - } - - var terminalContainer = document.getElementById('terminal-' + instance.name); - - var term = new Terminal({ - cursorBlink: false - }); - - term.attachCustomKeydownHandler(function(e) { - // Ctrl + Alt + C - if (e.ctrlKey && e.altKey && (e.keyCode == 67)) { - document.execCommand('copy'); - return false; - } - }); - - term.attachCustomKeydownHandler(function(e) { - if (selectedKeyboardShortcuts == null) - return; - var presets = selectedKeyboardShortcuts.presets - .filter(function(preset) { return preset.keyCode == e.keyCode }) - .filter(function(preset) { return (preset.metaKey == undefined && !e.metaKey) || preset.metaKey == e.metaKey }) - .filter(function(preset) { return (preset.ctrlKey == undefined && !e.ctrlKey) || preset.ctrlKey == e.ctrlKey }) - .filter(function(preset) { return (preset.altKey == undefined && !e.altKey) || preset.altKey == e.altKey }) - .forEach(function(preset) { preset.action({ terminal : term })}); - }); - - term.open(terminalContainer); - - // Set geometry during the next tick, to avoid race conditions. - setTimeout(function() { - $scope.resize(term.proposeGeometry()); - }, 4); - - term.on('data', function(d) { - $scope.socket.emit('terminal in', instance.name, d); - }); - - instance.term = term; - - if (instance.buffer) { - term.write(instance.buffer); - instance.buffer = ''; - } - - if (cb) { - cb(); - } - } - - function updateNewInstanceBtnState(isInstanceBeingCreated) { - if (isInstanceBeingCreated === true) { - $scope.newInstanceBtnText = '+ Creating...'; - $scope.isInstanceBeingCreated = true; - } else { - $scope.newInstanceBtnText = '+ Add new instance'; - $scope.isInstanceBeingCreated = false; - } - } - - function updateDeleteInstanceBtnState(isInstanceBeingDeleted) { - if (isInstanceBeingDeleted === true) { - $scope.deleteInstanceBtnText = 'Deleting...'; - $scope.isInstanceBeingDeleted = true; - } else { - $scope.deleteInstanceBtnText = 'Delete'; - $scope.isInstanceBeingDeleted = false; - } - } - }]) - .config(['$mdIconProvider', '$locationProvider', function($mdIconProvider, $locationProvider) { - $locationProvider.html5Mode({enabled: true, requireBase: false}); - $mdIconProvider.defaultIconSet('../assets/social-icons.svg', 24); - }]) - .component('settingsIcon', { - template : "settings", - controller : function($mdDialog) { - var $ctrl = this; - $ctrl.onClick = function() { - $mdDialog.show({ - controller : function() {}, - template : "", - parent: angular.element(document.body), - clickOutsideToClose : true - }) - } - } - }) - .component("settingsDialog", { - templateUrl : "settings-modal.html", - controller : function($mdDialog, KeyboardShortcutService, $rootScope, InstanceService, TerminalService) { - var $ctrl = this; - $ctrl.$onInit = function() { - $ctrl.keyboardShortcutPresets = KeyboardShortcutService.getAvailablePresets(); - $ctrl.selectedShortcutPreset = KeyboardShortcutService.getCurrentShortcuts(); - $ctrl.instanceImages = InstanceService.getAvailableImages(); - $ctrl.selectedInstanceImage = InstanceService.getDesiredImage(); - $ctrl.terminalFontSizes = TerminalService.getFontSizes(); - }; - - $ctrl.currentShortcutConfig = function(value) { - if (value !== undefined) { - value = JSON.parse(value); - KeyboardShortcutService.setCurrentShortcuts(value); - $ctrl.selectedShortcutPreset = angular.copy(KeyboardShortcutService.getCurrentShortcuts()); - $rootScope.$broadcast('settings:shortcutsSelected', $ctrl.selectedShortcutPreset); - } - return JSON.stringify(KeyboardShortcutService.getCurrentShortcuts()); - }; - - $ctrl.currentDesiredInstanceImage = function(value) { - if (value !== undefined) { - InstanceService.setDesiredImage(value); - } - return InstanceService.getDesiredImage(value); - }; - $ctrl.currentTerminalFontSize = function(value) { - if (value !== undefined) { - // set font size - TerminalService.setFontSize(value); - return; - } - - return TerminalService.getFontSize(); - } - - $ctrl.close = function() { - $mdDialog.cancel(); - } - } - }) - .service("InstanceService", function($http) { - var instanceImages = []; - _prepopulateAvailableImages(); - - return { - getAvailableImages : getAvailableImages, - setDesiredImage : setDesiredImage, - getDesiredImage : getDesiredImage, - }; - - function getAvailableImages() { - return instanceImages; - } - - function getDesiredImage() { - var image = localStorage.getItem("settings.desiredImage"); - if (image == null) - return instanceImages[0]; - return image; - } - - function setDesiredImage(image) { - if (image === null) - localStorage.removeItem("settings.desiredImage"); - else - localStorage.setItem("settings.desiredImage", image); - } - - function _prepopulateAvailableImages() { - return $http - .get("/instances/images") - .then(function(response) { - instanceImages = response.data; - }); - } - - }) - .run(function(InstanceService) { /* forcing pre-populating for now */ }) - .service("KeyboardShortcutService", ['TerminalService', function(TerminalService) { - var resizeFunc; - - return { - getAvailablePresets : getAvailablePresets, - getCurrentShortcuts : getCurrentShortcuts, - setCurrentShortcuts : setCurrentShortcuts, - setResizeFunc : setResizeFunc - }; - - function setResizeFunc(f) { - resizeFunc = f; - } - - function getAvailablePresets() { - return [ - { name : "None", presets : [ - { description : "Toggle terminal fullscreen", command : "Alt+enter", altKey : true, keyCode : 13, action : function(context) { TerminalService.toggleFullscreen(context.terminal, resizeFunc); }} - ] }, - { - name : "Mac OSX", - presets : [ - { description : "Clear terminal", command : "Cmd+K", metaKey : true, keyCode : 75, action : function(context) { context.terminal.clear(); }}, - { description : "Toggle terminal fullscreen", command : "Alt+enter", altKey : true, keyCode : 13, action : function(context) { TerminalService.toggleFullscreen(context.terminal, resizeFunc); }} - ] - } - ] - } - - function getCurrentShortcuts() { - var shortcuts = localStorage.getItem("shortcut-preset-name"); - if (shortcuts == null) { - shortcuts = getDefaultShortcutPrefixName(); - if (shortcuts == null) - return null; - } - - var preset = getAvailablePresets() - .filter(function(preset) { return preset.name == shortcuts; }); - if (preset.length == 0) - console.error("Unable to find preset with name '" + shortcuts + "'"); - return preset[0]; - return (shortcuts == null) ? null : JSON.parse(shortcuts); - } - - function setCurrentShortcuts(config) { - localStorage.setItem("shortcut-preset-name", config.name); - } - - function getDefaultShortcutPrefixName() { - if (window.navigator.platform.toUpperCase().indexOf('MAC') >= 0) - return "Mac OSX"; - return "None"; - } - }]) - .service('TerminalService', ['$window', function($window) { - var fullscreen; - var fontSize = getFontSize(); - return { - getFontSizes : getFontSizes, - setFontSize : setFontSize, - getFontSize : getFontSize, - increaseFontSize : increaseFontSize, - decreaseFontSize : decreaseFontSize, - toggleFullscreen : toggleFullscreen - }; - function getFontSizes() { - var terminalFontSizes = []; - for (var i=3; i<40; i++) { - terminalFontSizes.push(i+'px'); - } - return terminalFontSizes; - }; - function getFontSize() { - if (!fontSize) { - return $('.terminal').css('font-size'); - } - return fontSize; - } - function setFontSize(value) { - fontSize = value; - var size = parseInt(value); - $('.terminal').css('font-size', value).css('line-height', (size + 2)+'px'); - //.css('line-height', value).css('height', value); - angular.element($window).trigger('resize'); - } - function increaseFontSize() { - var sizes = getFontSizes(); - var size = getFontSize(); - var i = sizes.indexOf(size); - if (i == -1) { - return; - } - if (i+1 > sizes.length) { - return; - } - setFontSize(sizes[i+1]); - } - function decreaseFontSize() { - var sizes = getFontSizes(); - var size = getFontSize(); - var i = sizes.indexOf(size); - if (i == -1) { - return; - } - if (i-1 < 0) { - return; - } - setFontSize(sizes[i-1]); - } - function toggleFullscreen(terminal, resize) { - if(fullscreen) { - terminal.toggleFullscreen(); - resize(fullscreen); - fullscreen = null; - } else { - fullscreen = terminal.proposeGeometry(); - terminal.toggleFullscreen(); - angular.element($window).trigger('resize'); - } - } - }]); + function getDefaultShortcutPrefixName() { + if (window.navigator.platform.toUpperCase().indexOf('MAC') >= 0) + return "Mac OSX"; + return "None"; + } + }]) + .service('TerminalService', ['$window', function($window) { + var fullscreen; + var fontSize = getFontSize(); + return { + getFontSizes : getFontSizes, + setFontSize : setFontSize, + getFontSize : getFontSize, + increaseFontSize : increaseFontSize, + decreaseFontSize : decreaseFontSize, + toggleFullscreen : toggleFullscreen + }; + function getFontSizes() { + var terminalFontSizes = []; + for (var i=3; i<40; i++) { + terminalFontSizes.push(i+'px'); + } + return terminalFontSizes; + }; + function getFontSize() { + if (!fontSize) { + return $('.terminal').css('font-size'); + } + return fontSize; + } + function setFontSize(value) { + fontSize = value; + var size = parseInt(value); + $('.terminal').css('font-size', value).css('line-height', (size + 2)+'px'); + //.css('line-height', value).css('height', value); + angular.element($window).trigger('resize'); + } + function increaseFontSize() { + var sizes = getFontSizes(); + var size = getFontSize(); + var i = sizes.indexOf(size); + if (i == -1) { + return; + } + if (i+1 > sizes.length) { + return; + } + setFontSize(sizes[i+1]); + } + function decreaseFontSize() { + var sizes = getFontSizes(); + var size = getFontSize(); + var i = sizes.indexOf(size); + if (i == -1) { + return; + } + if (i-1 < 0) { + return; + } + setFontSize(sizes[i-1]); + } + function toggleFullscreen(terminal, resize) { + if(fullscreen) { + terminal.toggleFullscreen(); + resize(fullscreen); + fullscreen = null; + } else { + fullscreen = terminal.proposeGeometry(); + terminal.toggleFullscreen(); + angular.element($window).trigger('resize'); + } + } + }]); })(); diff --git a/www/index.html b/www/index.html index 3fc2ae3..48ef892 100644 --- a/www/index.html +++ b/www/index.html @@ -113,38 +113,37 @@ - + + + + + Close + + + + + +