This allows running them with `npm run gulp` and `npm run nw`
instead of having to type the whole path to the actual binaries.
Also, updated README to simplify the build instructions.
Current MSP handling groups callbacks by their MSP command
and when a response comes back it calls all the pending handlers
with the same response object.
This works fine when all MSP calls are either pure input or pure
output (e.g. the have a non-empty payload in just one direction).
However, we've had some calls that have a payload in both directions
for some time, like MSPV2_SETTING. For those MSP commands, the
response will depend on the request, so calling all handlers on
the first response received produces the wrong results. It's also
problematic on handlers that expect any kind of response, since the
DataView object is reused, but its offset was never reset which
would result in the second handler getting an empty response.
Change this strategy to call just the first pending handlers for
the MSP command received in the response. While this is still
a theoretical race condition (there's no guarantee a sequence of
the same command with different payloads will be replied in the
same order as they were issued to the FC), it's the best we can
do unless we add some kind of nonce/token system to each MSP
request, which would incur a significant overhead.
helper.defaultsDialog.init() was called from both onConnect()
and onValidFirmware(). Thanks to @dzikuvx for pointing out that
just the last call was enough.
Tab loading was relying on replacing the contents of '#content'
with the loading indicator, then replacing it with the loading tab
content and blocking rendering until the tab was ready by not
yielding. This is problematic for tabs that load some data
asynchronously, like PID and OSD.
Instead, put the loading indicator in front of everything else
and load new content inside '#content' next to the loading indicator
(but without showing it). Once the content and data are fully loaded
we fade out the loading indicator with a 0.4s long animation and
then we remove. This works for both synchronous and asynchonous
loading of tabs.