diff --git a/src/brackets.js b/src/brackets.js index 27c543879c9..7629622cfd7 100644 --- a/src/brackets.js +++ b/src/brackets.js @@ -257,6 +257,16 @@ define(function (require, exports, module) { ); } + brackets.app.getRemoteDebuggingPort(function (err, remote_debugging_port){ + if (remote_debugging_port && remote_debugging_port > 0) { + var InfoBar = require('widgets/infobar'); + InfoBar.showInfoBar({ + type: "warning", + title: `${Strings.REMOTE_DEBUGGING_ENABLED} ${remote_debugging_port}`, + description: "" + }); + } + }); // Use quiet scrollbars if we aren't on Lion. If we're on Lion, only // use native scroll bars when the mouse is not plugged in or when // using the "Always" scroll bar setting. diff --git a/src/document/DocumentCommandHandlers.js b/src/document/DocumentCommandHandlers.js index ed875376d9f..bb0889d1844 100644 --- a/src/document/DocumentCommandHandlers.js +++ b/src/document/DocumentCommandHandlers.js @@ -1642,28 +1642,31 @@ define(function (require, exports, module) { if (brackets.inBrowser) { result.resolve(); } else { - var port = brackets.app.getRemoteDebuggingPort ? brackets.app.getRemoteDebuggingPort() : 9234; - Inspector.getDebuggableWindows("127.0.0.1", port) - .fail(result.reject) - .done(function (response) { - var page = response[0]; - if (!page || !page.webSocketDebuggerUrl) { - result.reject(); - return; - } - var _socket = new WebSocket(page.webSocketDebuggerUrl); - // Disable the cache - _socket.onopen = function _onConnect() { - _socket.send(JSON.stringify({ id: 1, method: "Network.setCacheDisabled", params: { "cacheDisabled": true } })); - }; - // The first message will be the confirmation => disconnected to allow remote debugging of Brackets - _socket.onmessage = function _onMessage(e) { - _socket.close(); - result.resolve(); - }; - // In case of an error - _socket.onerror = result.reject; - }); + brackets.app.getRemoteDebuggingPort(function (err, port){ + if (port && port > 0) { + Inspector.getDebuggableWindows("127.0.0.1", port) + .fail(result.reject) + .done(function (response) { + var page = response[0]; + if (!page || !page.webSocketDebuggerUrl) { + result.reject(); + return; + } + var _socket = new WebSocket(page.webSocketDebuggerUrl); + // Disable the cache + _socket.onopen = function _onConnect() { + _socket.send(JSON.stringify({ id: 1, method: "Network.setCacheDisabled", params: { "cacheDisabled": true } })); + }; + // The first message will be the confirmation => disconnected to allow remote debugging of Brackets + _socket.onmessage = function _onMessage(e) { + _socket.close(); + result.resolve(); + }; + // In case of an error + _socket.onerror = result.reject; + }); + } + }); } return result.promise(); diff --git a/src/htmlContent/infobar-template.html b/src/htmlContent/infobar-template.html new file mode 100644 index 00000000000..ab73c367b52 --- /dev/null +++ b/src/htmlContent/infobar-template.html @@ -0,0 +1,13 @@ +
+
+ +
+
+

{{title}}  {{{description}}}

+
+ {{^buttons}} +
+ +
+ {{/buttons}} +
\ No newline at end of file diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index dc74e2f354c..7f7646b8804 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -897,5 +897,8 @@ define({ "REFERENCES_NO_RESULTS" : "No References available for current cursor position", "CMD_FIND_DOCUMENT_SYMBOLS" : "Find Document Symbols", - "CMD_FIND_PROJECT_SYMBOLS" : "Find Project Symbols" + "CMD_FIND_PROJECT_SYMBOLS" : "Find Project Symbols", + + // Remote debugging enabled + "REMOTE_DEBUGGING_ENABLED" : "Remote debugging enabled on localhost:" }); diff --git a/src/styles/brackets_shared.less b/src/styles/brackets_shared.less index 7c7dd2cabcf..94665a160d8 100644 --- a/src/styles/brackets_shared.less +++ b/src/styles/brackets_shared.less @@ -57,3 +57,5 @@ // Styling for scrollbars @import url("brackets_scrollbars.less"); + +@import url("infobar-styles.less"); diff --git a/src/styles/images/infobar-alert.svg b/src/styles/images/infobar-alert.svg new file mode 100644 index 00000000000..2390583d92f --- /dev/null +++ b/src/styles/images/infobar-alert.svg @@ -0,0 +1,10 @@ + + + + + + diff --git a/src/styles/images/infobar-checkmarkcircle.svg b/src/styles/images/infobar-checkmarkcircle.svg new file mode 100644 index 00000000000..fc0706d5d99 --- /dev/null +++ b/src/styles/images/infobar-checkmarkcircle.svg @@ -0,0 +1,10 @@ + + + + + + diff --git a/src/styles/images/infobar-info.svg b/src/styles/images/infobar-info.svg new file mode 100644 index 00000000000..5b23b6491fd --- /dev/null +++ b/src/styles/images/infobar-info.svg @@ -0,0 +1,10 @@ + + + + + + diff --git a/src/styles/infobar-styles.less b/src/styles/infobar-styles.less new file mode 100644 index 00000000000..246cda67b77 --- /dev/null +++ b/src/styles/infobar-styles.less @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2019 - present Adobe Systems Incorporated. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +/*info Bar*/ +#info-bar-template { + display: block; + background-color: #105F9C; + box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.53); + height: 38px; + width: 100%; + position: absolute; + z-index: 15; + left: 0px; + bottom: 25px; + outline: none; + overflow: hidden; +} + +#info-bar-template #icon-container { + width: auto; + height: auto; + padding: 11px; + float: left; +} +#info-bar-template #icon-container #info-icon { + background: url("images/infobar-info.svg") no-repeat 0 0; + width: 16px; + height: 16px; + display: block; +} + +#info-bar-template #content-container { + padding: 10px 7px; + float: left; + max-width: 78%; +} + +#info-bar-template #content-container #info-content { + margin: 0px !important; /*Check if this important is necessary*/ + line-height: 18px; + font-size: 14px; + font-family: 'SourceSansPro'; + color: #FFFFFF; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +#info-bar-template #content-container #info-content #heading{ + font-weight: bold; +} +/*For focussed link of brackets.io*/ +#info-bar-template #content-container #info-content #description a:focus{ + box-shadow: none; +} + +#info-bar-template #content-container #info-content #description a{ + text-decoration: underline; + color: #FFFFFF; +} + +#info-bar-template #close-icon-container { + height: auto; + padding: 9px; + position: fixed; + float: right; + text-align: center; + width: auto; + min-width: 66px; + right: 30px; + background-color: #105F9C; +} + +#info-bar-template #close-icon-container #close-icon { + display: block; + color: white; + font-size: 18px; + line-height: 18px; + text-decoration: none; + width: 18px; + height: 18px; + background-color: transparent; + border: none; + padding: 0px; /*This is needed to center the icon*/ + float: right; +} + +#info-bar-template #close-icon-container #close-icon:hover { + background-color: rgba(255, 255, 255 ,0.16); + border-radius: 50%; +} + +#info-bar-template #close-icon-container #close-icon:focus { + background-color: rgba(255, 255, 255 ,0.16); + border-radius: 50%; + border: 1px solid #C3E3FF; + outline: 0; +} + +#info-bar-template #close-icon-container #close-icon:focus:active { + background-color: rgba(255, 255, 255 ,0.32); + border: none; +} + +/*Warning Message in info Bar*/ +#info-bar-template.warning, #info-bar-template.warning #close-icon-container { + background-color: #DA7A12; +} + +.dark #info-bar-template.warning, .dark #info-bar-template.warning #close-icon-container { + background-color: #E6851A; +} + +#info-bar-template.warning #icon-container #info-icon, +#info-bar-template.error #icon-container #info-icon { + background: url("images/infobar-alert.svg") no-repeat 0 0; +} + +/*Error message in info Bar*/ +#info-bar-template.error, #info-bar-template.error #close-icon-container { + background-color: #D7373F; +} + +.dark #info-bar-template.error, .dark #info-bar-template.error #close-icon-container{ + background-color: #E4484F; +} +/*Success message in info Bar*/ +#info-bar-template.success, #info-bar-template.success #close-icon-container { + background-color: #278E6B; +} + +.dark #info-bar-template.success, .dark #info-bar-template.success #close-icon-container { + background-color: #2E9D77; +} + +#info-bar-template.success #icon-container #info-icon{ + background: url("images/infobar-checkmarkcircle.svg") no-repeat 0 0; +} diff --git a/src/widgets/infobar.js b/src/widgets/infobar.js new file mode 100644 index 00000000000..4a266d63332 --- /dev/null +++ b/src/widgets/infobar.js @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2018 - present Adobe Systems Incorporated. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +define(function (require, exports, module) { + "use strict"; + + var MainViewManager = require("view/MainViewManager"), + Mustache = require("thirdparty/mustache/mustache"), + EventDispatcher = require("utils/EventDispatcher"), + InfoBarHtml = require("text!htmlContent/infobar-template.html"), + _ = require("thirdparty/lodash"); + + EventDispatcher.makeEventDispatcher(exports); + + // Key handlers for buttons in UI + var ESC_KEY = 27; // keycode for escape key + + /** + * Generates the json to be used by Mustache for rendering + * @param {object} msgObj - json object containing message information to be displayed + * @returns {object} - the generated json object + */ + function generateJsonForMustache(msgObj) { + var msgJsonObj = {}; + if (msgObj.type) { + msgJsonObj.type = "'" + msgObj.type + "'"; + } + msgJsonObj.title = msgObj.title; + msgJsonObj.description = msgObj.description; + return msgJsonObj; + } + /** + * Removes and cleans up the info bar from DOM + */ + function cleanInfoBar() { + var $infoBar = $('#info-bar-template'); + if ($infoBar.length > 0) { + $infoBar.remove(); + } + $(window.document).off("keydown.InfoBarTemplateDoc"); + $(window).off('resize.InfoBarTemplate'); + } + + /** + * Displays the Info Bar UI + * @param {object} msgObj - json object containing message info to be displayed + * + */ + function showInfoBar(msgObj) { + var jsonToMustache = generateJsonForMustache(msgObj), + $infoBarElement = $(Mustache.render(InfoBarHtml, jsonToMustache)); + + cleanInfoBar(); //Remove an already existing info bar, if any + $infoBarElement.prependTo(".content"); + + var $infoBar = $('#info-bar-template'), + $infoContent = $infoBar.find('#info-content'), + $contentContainer = $infoBar.find('#content-container'), + $iconContainer = $infoBar.find('#icon-container'), + $closeIconContainer = $infoBar.find('#close-icon-container'), + $heading = $infoBar.find('#heading'), + $description = $infoBar.find('#description'), + $closeIcon = $infoBar.find('#close-icon'); + + if ($infoContent.length > 0) { + if ($infoContent[0].scrollWidth > $infoContent.innerWidth()) { + //Text has over-flown, show the info content as tooltip message + if ($contentContainer.length > 0 && + $heading.length > 0 && + $description.length > 0) { + $contentContainer.attr("title", $heading.text() + $description.text()); + } + } + } + // Content Container Width between Icon Container and Button Container or Close Icon Container + // will be assigned when window will be rezied. + var resizeContentContainer = function () { + if($infoContent.length > 0 && $contentContainer.length > 0 && $infoBar.length > 0) { + var newWidth = $infoBar.outerWidth() - 38; + if($iconContainer.length > 0) { + newWidth = newWidth - $iconContainer.outerWidth(); + } + if($closeIconContainer.length > 0) { + newWidth = newWidth - $closeIconContainer.outerWidth(); + } + + $contentContainer.css({ + "maxWidth": newWidth + }); + } + }; + + resizeContentContainer(); + $(window).on('resize.InfoBarTemplate', _.debounce(resizeContentContainer, 150)); + + //Event handlers on the Info Bar + // Click and key handlers on Close button + if ($closeIcon.length > 0) { + $closeIcon.click(function () { + cleanInfoBar(); + MainViewManager.focusActivePane(); + }); + } + $(window.document).on("keydown.InfoBarTemplateDoc", function (event) { + var code = event.which; + if (code === ESC_KEY) { + // Keyboard input of Esc key on Info Bar dismisses and removes the bar + cleanInfoBar(); + MainViewManager.focusActivePane(); + event.stopImmediatePropagation(); + } + }); + } + exports.showInfoBar = showInfoBar; +});