Siqi Liu dc3fce06ea Add Copy and Dismiss Button in RN Android Red Box
Summary:
Add "Copy" and "Dismiss" button when the RN Android redbox is shown, consistent with that in RN iOS.
  - "Copy" button copies all the messages shown in the redbox to the host system clipboard, the solution is posting redbox messages to packager and the the packager copies the messages onto the host clipboard.
  - "Dismiss" button always exits the redbox dialog.
  - Add shortcut as "Dismiss (ESC)" and "Reload (R, R).

Notice: Copy button is only supported on Mac OS by now (warning in packager on other platforms), because it's not easy for us to test on Windows or Linux. Will put the codes for other platforms on Github issues, hoping anyone could help test and add this feature, then send us a pull request.

Redbox Dialog in RN Android before:
{F61310489}
Redbox Dialog in RN Android now:
{F61659189}

Follow-up:
- We can adjust the button styles in redboxes.
- We can consider to add shortcut for "Copy" button.

Reviewed By: foghina

Differential Revision: D3392155

fbshipit-source-id: fc5dc2186718cac8706fb3c17d336160e61e3f4e
2016-06-30 08:13:22 -07:00

97 lines
3.6 KiB
JavaScript

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
const attachHMRServer = require('./util/attachHMRServer');
const connect = require('connect');
const cpuProfilerMiddleware = require('./middleware/cpuProfilerMiddleware');
const getDevToolsMiddleware = require('./middleware/getDevToolsMiddleware');
const http = require('http');
const loadRawBodyMiddleware = require('./middleware/loadRawBodyMiddleware');
const messageSocket = require('./util/messageSocket.js');
const openStackFrameInEditorMiddleware = require('./middleware/openStackFrameInEditorMiddleware');
const copyToClipBoardMiddleware = require('./middleware/copyToClipBoardMiddleware');
const path = require('path');
const ReactPackager = require('../../packager/react-packager');
const statusPageMiddleware = require('./middleware/statusPageMiddleware.js');
const indexPageMiddleware = require('./middleware/indexPage');
const systraceProfileMiddleware = require('./middleware/systraceProfileMiddleware.js');
const webSocketProxy = require('./util/webSocketProxy.js');
function runServer(args, config, readyCallback) {
var wsProxy = null;
var ms = null;
const packagerServer = getPackagerServer(args, config);
const app = connect()
.use(loadRawBodyMiddleware)
.use(connect.compress())
.use(getDevToolsMiddleware(args, () => wsProxy && wsProxy.isChromeConnected()))
.use(getDevToolsMiddleware(args, () => ms && ms.isChromeConnected()))
.use(openStackFrameInEditorMiddleware(args))
.use(copyToClipBoardMiddleware)
.use(statusPageMiddleware)
.use(systraceProfileMiddleware)
.use(cpuProfilerMiddleware)
.use(indexPageMiddleware)
.use(packagerServer.processRequest.bind(packagerServer));
args.projectRoots.forEach(root => app.use(connect.static(root)));
app.use(connect.logger())
.use(connect.errorHandler());
const serverInstance = http.createServer(app).listen(
args.port,
args.host,
function() {
attachHMRServer({
httpServer: serverInstance,
path: '/hot',
packagerServer,
});
wsProxy = webSocketProxy.attachToServer(serverInstance, '/debugger-proxy');
ms = messageSocket.attachToServer(serverInstance, '/message');
webSocketProxy.attachToServer(serverInstance, '/devtools');
readyCallback();
}
);
// Disable any kind of automatic timeout behavior for incoming
// requests in case it takes the packager more than the default
// timeout of 120 seconds to respond to a request.
serverInstance.timeout = 0;
}
function getPackagerServer(args, config) {
const transformModulePath = args.transformer ?
path.resolve(args.transformer) :
config.getTransformModulePath();
return ReactPackager.createServer({
nonPersistent: args.nonPersistent,
projectRoots: args.projectRoots,
blacklistRE: config.getBlacklistRE(),
cacheVersion: '3',
getTransformOptionsModulePath: config.getTransformOptionsModulePath,
transformModulePath: transformModulePath,
extraNodeModules: config.extraNodeModules,
assetRoots: args.assetRoots,
assetExts: [
'bmp', 'gif', 'jpg', 'jpeg', 'png', 'psd', 'svg', 'webp', // Image formats
'm4v', 'mov', 'mp4', 'mpeg', 'mpg', 'webm', // Video formats
'aac', 'aiff', 'caf', 'm4a', 'mp3', 'wav', // Audio formats
'html', 'pdf', // Document formats
],
resetCache: args.resetCache || args['reset-cache'],
verbose: args.verbose,
});
}
module.exports = runServer;