-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Added Reverse Inspect in Live Preview using WebSockets, and now forwa… #13044
Conversation
…rd inspect brings the html element in focus to the viewport in Live Preview
…eview and also now port is read from preferences file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to have broken MultiBrowserLivePreview. At least using Firefox does throw some errors.
Also I thought that standard LivePreview was sort of deprecated and we should not add features to it.
@@ -130,7 +131,7 @@ define(function RemoteAgent(require, exports, module) { | |||
_stopKeepAliveInterval(); | |||
|
|||
// inject RemoteFunctions | |||
var command = "window._LD=" + RemoteFunctions + "(" + LiveDevelopment.config.experimental + ");"; | |||
var command = "window._LD=" + RemoteFunctions + "(" + LiveDevelopment.config.experimental + "," + PreferencesManager.get("livedev.wsPort") + ");"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#12949 will change this to pass a config object, maybe you can already change it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have run all tests related to Live Preview, and now MultiBrowserPreview is also working fine.
Regarding passing of config object, once #12949 is merged, I will do the respective changes.
@@ -319,6 +319,10 @@ function RemoteFunctions(experimental) { | |||
if (this.trigger) { | |||
_trigger(element, "highlight", 1); | |||
} | |||
|
|||
if (!window.event) { | |||
element.scrollIntoViewIfNeeded(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the current version of MDN, this function is supported only in Chrome, Opera and Safari.
I'm not familiar with LivePreview but this file is injected only in case of LivePreview with Chrome, or it is also used with MultiBrowserLivePreview?
In the second case, is it possible to change it to use scrollIntoView
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This script is injected in case of MultiBrowserLivePreview, for now the reverse-inspect doesn't work with the multibrowser, I will take up this task once this PR is merged.(I tried a hacky solution to make it work for multibrowser and it was working. I will raise another PR once I am done with proper solution)
Now, I am using window.scrollTo instead of scrollIntoViewIfNeeded.
I didn't use scrollIntoView because it aligns the element either to top or bottom, but I wanted to align it to center, so I have now used window.scrollTo which is supported by all browsers.
|
||
_ws.onmessage = function (evt) { | ||
var received_msg = evt.data; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you don't use it, remove it?
|
||
PreferencesManager.definePreference("livedev.wsPort", "number", 8125, { | ||
description: Strings.DESCRIPTION_LIVEDEV_WEBSOCKET_PORT | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since you are doing for LiveDevelopment, maybe you should do the same for MultiBrowserLivePreview too. See also #11957
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah once this is completed, I will try to do the same for multibrowser also.
// This transport provides a WebSocket connection between Brackets and a live browser preview. | ||
// This is just a thin wrapper around the Node extension (WebSocketTransportDomain) that actually | ||
// provides the WebSocket server and handles the communication. We also rely on an injected script in | ||
// the browser for the other end of the transport. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This probably should be a JSDoc.
false, // this command is synchronous in Node | ||
"Creates the WS server", | ||
[ | ||
{name: "port", type: "number", description: "Port on which server needs to listen"} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put every param on its own line.
{ | ||
"name": "brackets-livedev-server", | ||
"dependencies": { | ||
"ws": "~0.4.31" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can put it on the root package.json and update the shrinkwrap file.
Right now, I don't think this works.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, right now we have to run npm install
inside the node directory, to run this.
I am trying to figure out a way to move this to root package.json as suggested by you.
var marks = editor._codeMirror.getAllMarks(), | ||
i, | ||
markFound, | ||
position; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
position is not used.
markFound, | ||
position; | ||
|
||
for (i = 0; i < marks.length; i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can replace this for
with lodash
} | ||
if (markFound) { | ||
return markFound.find().from; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If markFound
can be false maybe you should add a return value, otherwise add a console.error
or something.
I'm not really familiar with LivePreview to judge the approach. However I left some comments. |
{name: "port", type: "number", description: "Port on which server needs to listen"} | ||
], | ||
[] | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIt: newline here
function onDocumentClick(event) { | ||
var element = event.target, | ||
currentDataId, | ||
newDataId; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: newline here
@@ -1362,6 +1369,7 @@ define(function LiveDevelopment(require, exports, module) { | |||
// wait for server (StaticServer, Base URL or file:) | |||
prepareServerPromise | |||
.done(function () { | |||
WebSocketTransport.createWebSocketServer(PreferencesManager.get("livedev.wsPort")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See @ficristo's comment above about the MultiBrowserLivePreview
👍
[ | ||
{name: "msg", type: "string", description: "JSON message from client page"} | ||
] | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Newline here
_domainManager = domainManager; | ||
if (!domainManager.hasDomain("webSocketTransport")) { | ||
domainManager.registerDomain("webSocketTransport", {major: 0, minor: 1}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Newline here
Left some small comments too, looking good so far 👍 |
if (element && element.hasAttribute('data-brackets-id')) { | ||
_ws.send(JSON.stringify({ | ||
type: "message", | ||
message: element.getAttribute('data-brackets-id') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The message is just the element id, correct? When sending messages in other direction (from Brackets to browser), the message has the format:
{ method: method, id: id, params: params }
It would be nice to do the same here so that's it's easier to add any new messages in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually in multi-browser also we are sending the message from browser to brackets in the same format(NodeSocketTransportRemote.js), that's why I also used the same format, so that in future when we implement the same thing for multi-browser, we can have the same message to interpret in the brackets side.
@@ -0,0 +1,64 @@ | |||
/* | |||
* Copyright (c) 2014 - present Adobe Systems Incorporated. All rights reserved. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copyright date for new files should be year that file was added (2017).
…ViewIfNeeded, added a check for port number in RemoteFunctions and some minor changes
I have fixed some issues related to MultiBrowserLivePreview as RemoteFunctions.js was also included in MultiBrowserLivePreview. I have run the tests also, on both Firefox and Chrome. |
@@ -22,15 +22,15 @@ | |||
*/ | |||
|
|||
/*jslint forin: true */ | |||
/*global Node */ | |||
/*global Node, document */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use window.document
instead of adding it as a global.
|
||
window.document.addEventListener("click", onDocumentClick); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is better to move this call in the onopen
callback below and
add a removeEventListener in the onclose
callback.
Otherwise the handler will be called also when the LivePreview is terminated.
There are still a couple of unanswered comments. |
@ficristo, I just uploaded new changes, regarding the testing part, I was thinking of writing tests once I am done with MultiBrowserLivePreview as well(I am almost done with it), then I will write tests for both of them. @petetnt @zaggino @marcelgerber @abose Please review |
…h instead of for loop in HTMLInstrumentation.js
54e1e83
to
aae3943
Compare
This does not work on distribution.
You have to adjust the |
Thanks @ficristo for pointing out. I have fixed this and also updated the PR :) |
I looked enough at this so approving but I see some failures on Live Preview tests, so please take a look. |
@ficristo Actually there is some problem with the timeout of the Live Preview tests, I increased the timeout and all the Live Preview tests are passing. |
@saurabh95 the increase of timeout should be part of this PR? |
@ficristo Actually without my changes also some LivePreview tests(the same ones) were failing and on increasing timeout they were passing, so I thought we can take change it in some other set of changes, as it is independent of this change? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with few comments
@@ -319,6 +336,14 @@ function RemoteFunctions(experimental) { | |||
if (this.trigger) { | |||
_trigger(element, "highlight", 1); | |||
} | |||
|
|||
if (!window.event && !isInViewport(element)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question: not sure why the window.event
check is needed here? Something to do with legacy IE's?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am checking if there is any window event (mostly click event) is there on the LivePreview instance, then we don't need to bring the element in viewport, as it is already present in the viewport.
@@ -38,7 +38,8 @@ | |||
"dependencies": { | |||
"anymatch": "1.3.0", | |||
"chokidar": "1.6.0", | |||
"lodash": "4.15.0" | |||
"lodash": "4.15.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lodash has 4.17.4 out now, but feel free to left as is
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good to be merged.
Great work @saurabh95. This is indeed a great addition, keep more coming 👍 |
Now you can click on any element in Live Preview and then corresponding HTML element will be highlighted and the cursor in code view will shift to the corresponding HTML element.
Features that need to be incorporated in this PR
I am currently working on these. Will update the PR soon.