diff --git a/.travis.yml b/.travis.yml
index 192adcb3f..7b6681af0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -58,4 +58,4 @@ matrix:
script:
- cd iOS/Sample
- - xcodebuild clean build -workspace Sample.xcworkspace -scheme Pods-Sample
+ - xcodebuild clean build -workspace Sample.xcworkspace -scheme Pods-Sample -sdk iphonesimulator11.2
diff --git a/docs/getting-started.md b/docs/getting-started.md
index 3a9831f7c..6437a3a9d 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -63,23 +63,17 @@ public class MyApplication extends Application {
To integrate with an iOS app, you can use [CocoaPods](https://cocoapods.org). Add the mobile Sonar SDK and its dependencies to your `Podfile`:
```ruby
-platform :ios, '8.0'
-swift_version = '4.1'
+project 'MyApp.xcodeproj'
+source 'https://github.com/facebook/Sonar.git'
+source 'https://github.com/CocoaPods/Specs'
+# Uncomment the next line to define a global platform for your project
+swift_version = "4.1"
target 'MyApp' do
- pod 'RSocket', :podspec => 'https://raw.githubusercontent.com/facebook/Sonar/master/iOS/third-party-podspecs/RSocket.podspec'
- pod 'DoubleConversion', :podspec => 'https://raw.githubusercontent.com/facebook/Sonar/master/iOS/third-party-podspecs/DoubleConversion.podspec'
- pod 'glog', :podspec => 'https://raw.githubusercontent.com/facebook/Sonar/master/iOS/third-party-podspecs/glog.podspec'
- pod 'Folly', :podspec => 'https://raw.githubusercontent.com/facebook/Sonar/master/iOS/third-party-podspecs/Folly.podspec'
- pod 'PeerTalk', :podspec => 'https://raw.githubusercontent.com/facebook/Sonar/master/iOS/third-party-podspecs/PeerTalk.podspec'
- pod 'Yoga','~>1.8.1', :modular_headers => true
- pod 'Sonar', :podspec => 'https://raw.githubusercontent.com/facebook/Sonar/master/xplat/Sonar/Sonar.podspec'
- pod 'SonarKit', :podspec => 'https://raw.githubusercontent.com/facebook/Sonar/master/iOS/SonarKit.podspec'
- pod 'SonarKit/SonarKitLayoutComponentKitSupport', :podspec => 'https://raw.githubusercontent.com/facebook/Sonar/master/iOS/SonarKit.podspec'
- pod 'SonarKit/SKIOSNetworkPlugin', :podspec => 'https://raw.githubusercontent.com/facebook/Sonar/master/iOS/SonarKit.podspec'
- pod 'ComponentKit', :podspec => 'https://raw.githubusercontent.com/facebook/Sonar/master/iOS/third-party-podspecs/ComponentKit.podspec'
+ pod 'SonarKit', '~>0.0.1'
post_install do |installer|
+
installer.pods_project.targets.each do |target|
if ['YogaKit'].include? target.name
target.build_configurations.each do |config|
@@ -112,7 +106,7 @@ and install the dependencies by running `pod install`. When you open the Xcode w
```
-* We haven't released the dependency to CocoaPods, because we weren't able to successfully validate the podspec of SonarKit. You could help us out by fixing this [issue](https://github.com/facebook/Sonar/issues/11) by submitting a PR to the repo.
+* We haven't released the dependency to CocoaPods yet, here is the [issue](https://github.com/facebook/Sonar/issues/132) by which you can track.
* If you do not use CocoaPods as a dependency management tool then currently there is no way to integrate SonarKit other than manually including all the dependencies and building it.
* For Android, Sonar works with both emulators and physical devices connected through USB. However on iOS, we don't yet support physical devices.
* Also Sonar doesn't work with swift projects as its written in C++ and had C++ dependencies. But we are working on supporting sonar for swift projects. You can find this issue [here](https://github.com/facebook/Sonar/issues/13)
diff --git a/src/App.js b/src/App.js
index 8e2f6dfae..4c77e5e92 100644
--- a/src/App.js
+++ b/src/App.js
@@ -4,185 +4,41 @@
* LICENSE file in the root directory of this source tree.
* @format
*/
+
+import React from 'react';
import {FlexColumn, FlexRow} from 'sonar';
import {connect} from 'react-redux';
import {toggleBugDialogVisible} from './reducers/application.js';
import WelcomeScreen from './chrome/WelcomeScreen.js';
import SonarTitleBar from './chrome/SonarTitleBar.js';
-import BaseDevice from './devices/BaseDevice.js';
import MainSidebar from './chrome/MainSidebar.js';
-import {SonarBasePlugin} from './plugin.js';
-import Server from './server.js';
-import Client from './Client.js';
-import React from 'react';
-import BugReporter from './fb-stubs/BugReporter.js';
import BugReporterDialog from './chrome/BugReporterDialog.js';
import ErrorBar from './chrome/ErrorBar.js';
-import Logger from './fb-stubs/Logger.js';
import PluginContainer from './PluginContainer.js';
import PluginManager from './chrome/PluginManager.js';
-const electron = require('electron');
-const yargs = require('yargs');
-export type {Client};
-
-export type StatePluginInfo = {
- plugin: ?SonarBasePlugin<>,
- state: Object,
-};
-
-export type StateClientPlugins = {
- [pluginKey: string]: StatePluginInfo,
-};
-
-export type StatePlugins = {
- [appKey: string]: StateClientPlugins,
-};
-
-export type State = {
- activePluginKey: ?string,
- activeAppKey: ?string,
- plugins: StatePlugins,
- error: ?string,
-};
+import type Logger from './fb-stubs/Logger.js';
+import type BugReporter from './fb-stubs/BugReporter.js';
type Props = {
- devices: Array,
+ logger: Logger,
+ bugReporter: BugReporter,
leftSidebarVisible: boolean,
bugDialogVisible: boolean,
pluginManagerVisible: boolean,
selectedDeviceIndex: number,
- selectedApp: ?string,
+ error: ?string,
toggleBugDialogVisible: (visible?: boolean) => void,
};
-export class App extends React.Component {
- constructor() {
+export class App extends React.Component {
+ constructor(props: Props) {
performance.mark('init');
- super();
- this.initTracking();
-
- setupEnvironment();
- this.logger = new Logger();
- replaceGlobalConsole(this.logger);
- this.server = this.initServer();
-
- this.state = {
- activeAppKey: null,
- activePluginKey: null,
- error: null,
- devices: {},
- plugins: {},
- };
-
- this.bugReporter = new BugReporter(this.logger);
- this.commandLineArgs = yargs.parse(electron.remote.process.argv);
+ super(props);
}
- server: Server;
- bugReporter: BugReporter;
- logger: Logger;
- commandLineArgs: Object;
- _hasActivatedPreferredPlugin: boolean = false;
-
componentDidMount() {
- this.logger.trackTimeSince('init');
-
- // close socket before reloading
- window.addEventListener('beforeunload', () => {
- this.server.close();
- });
- }
-
- toJSON() {
- return null;
- }
-
- initServer(): Server {
- const server = new Server(this);
- server.addListener('new-client', client => {
- client.addListener('close', () => {
- this.setState(state => {
- this.forceUpdate();
- // TODO:
- //reducers.TeardownClient(this, state, {appKey: client.id}),
- });
- if (this.state.activeAppKey === client.id) {
- this.forceUpdate();
- }
- });
-
- client.addListener('plugins-change', () => {
- this.forceUpdate();
- });
- });
-
- server.addListener('clients-change', () => {
- this.forceUpdate();
- });
-
- server.addListener('error', err => {
- if (err.code === 'EADDRINUSE') {
- this.setState({
- error:
- "Couldn't start websocket server. " +
- 'Looks like you have multiple copies of Sonar running.',
- });
- } else {
- // unknown error
- this.setState({
- error: err.message,
- });
- }
- });
-
- return server;
- }
-
- initTracking = () => {
- electron.ipcRenderer.on('trackUsage', () => {
- // check if there's a plugin currently active
- const {activeAppKey, activePluginKey} = this.state;
- if (activeAppKey == null || activePluginKey == null) {
- return;
- }
-
- // app plugins
- const client = this.getClient(activeAppKey);
- if (client) {
- this.logger.track('usage', 'ping', {
- app: client.query.app,
- device: client.query.device,
- os: client.query.os,
- plugin: activePluginKey,
- });
- return;
- }
-
- // device plugins
- const device: ?BaseDevice = this.getDevice(activeAppKey);
- if (device) {
- this.logger.track('usage', 'ping', {
- os: device.os,
- plugin: activePluginKey,
- device: device.title,
- });
- }
- });
- };
-
- getDevice = (id: string): ?BaseDevice =>
- this.props.devices.find((device: BaseDevice) => device.serial === id);
-
- getClient(appKey: ?string): ?Client {
- if (appKey == null) {
- return null;
- }
-
- const info = this.server.connections.get(appKey);
- if (info != null) {
- return info.client;
- }
+ this.props.logger.trackTimeSince('init');
}
render() {
@@ -191,30 +47,21 @@ export class App extends React.Component {
{this.props.bugDialogVisible && (
this.props.toggleBugDialogVisible(false)}
/>
)}
{this.props.selectedDeviceIndex > -1 ? (
- {this.props.leftSidebarVisible && (
- client,
- )}
- />
- )}
-
+ {this.props.leftSidebarVisible && }
+
) : this.props.pluginManagerVisible ? (
) : (
)}
-
+
);
}
@@ -223,39 +70,14 @@ export class App extends React.Component {
export default connect(
({
application: {pluginManagerVisible, bugDialogVisible, leftSidebarVisible},
- connections: {devices, selectedDeviceIndex, selectedApp},
+ connections: {selectedDeviceIndex},
+ server: {error},
}) => ({
pluginManagerVisible,
bugDialogVisible,
leftSidebarVisible,
- devices,
selectedDeviceIndex,
- selectedApp,
+ error,
}),
{toggleBugDialogVisible},
)(App);
-
-function replaceGlobalConsole(logger: Logger) {
- const loggerMethods = {
- log: logger.info,
- warn: logger.warn,
- error: logger.error,
- };
- const consoleHandler = {
- get: function(obj, prop) {
- return prop in loggerMethods
- ? args => {
- obj[prop] && obj[prop](args);
- return loggerMethods[prop].bind(logger)(args);
- }
- : obj[prop];
- },
- };
- window.console = new Proxy(console, consoleHandler);
-}
-
-function setupEnvironment() {
- if (!process.env.ANDROID_HOME) {
- process.env.ANDROID_HOME = '/opt/android_sdk';
- }
-}
diff --git a/src/Client.js b/src/Client.js
index 09646a701..a6916bd1c 100644
--- a/src/Client.js
+++ b/src/Client.js
@@ -7,7 +7,8 @@
import type {SonarPlugin} from './plugin.js';
import type {App} from './App.js';
-import type BaseDevice from './devices/BaseDevice.js';
+import type Logger from './fb-stubs/Logger.js';
+
import plugins from './plugins/index.js';
import {ReactiveSocket, PartialResponder} from 'rsocket-core';
@@ -26,7 +27,12 @@ export type ClientQuery = {|
type RequestMetadata = {method: string, id: number, params: ?Object};
export default class Client extends EventEmitter {
- constructor(app: App, id: string, query: ClientQuery, conn: ReactiveSocket) {
+ constructor(
+ id: string,
+ query: ClientQuery,
+ conn: ReactiveSocket,
+ logger: Logger,
+ ) {
super();
this.connected = true;
@@ -35,7 +41,7 @@ export default class Client extends EventEmitter {
this.id = id;
this.query = query;
this.messageIdCounter = 0;
- this.app = app;
+ this.logger = logger;
this.broadcastCallbacks = new Map();
this.requestCallbacks = new Map();
@@ -82,16 +88,6 @@ export default class Client extends EventEmitter {
|},
>;
- getDevice(): ?BaseDevice {
- const {device_id} = this.query;
-
- if (device_id == null) {
- return null;
- } else {
- return this.app.getDevice(device_id);
- }
- }
-
supportsPlugin(Plugin: Class>): boolean {
return this.plugins.includes(Plugin.id);
}
@@ -193,7 +189,7 @@ export default class Client extends EventEmitter {
}
toJSON() {
- return null;
+ return ``;
}
subscribe(
@@ -257,7 +253,7 @@ export default class Client extends EventEmitter {
finishTimingRequestResponse(data: RequestMetadata) {
const mark = this.getPerformanceMark(data);
const logEventName = this.getLogEventName(data);
- this.app.logger.trackTimeSince(mark, logEventName);
+ this.logger.trackTimeSince(mark, logEventName);
}
getPerformanceMark(data: RequestMetadata): string {
diff --git a/src/PluginContainer.js b/src/PluginContainer.js
index d338e26db..7858eca78 100644
--- a/src/PluginContainer.js
+++ b/src/PluginContainer.js
@@ -36,8 +36,9 @@ type Props = {
logger: LogManager,
selectedDeviceIndex: number,
selectedPlugin: ?string,
+ selectedApp: ?string,
pluginStates: Object,
- client: ?Client,
+ clients: Array,
devices: Array,
setPluginState: (payload: {
pluginKey: string,
@@ -101,13 +102,15 @@ class PluginContainer extends Component {
if (activePlugin) {
pluginKey = `${device.serial}#${activePlugin.id}`;
} else {
+ target = props.clients.find(
+ (client: Client) => client.id === props.selectedApp,
+ );
activePlugin = plugins.find(
(p: Class>) => p.id === props.selectedPlugin,
);
- if (!activePlugin || !props.client) {
+ if (!activePlugin || !target) {
return null;
}
- target = props.client;
pluginKey = `${target.id}#${activePlugin.id}`;
}
@@ -161,13 +164,16 @@ class PluginContainer extends Component {
export default connect(
({
application: {rightSidebarVisible, rightSidebarAvailable},
- connections: {selectedPlugin, devices, selectedDeviceIndex},
+ connections: {selectedPlugin, devices, selectedDeviceIndex, selectedApp},
pluginStates,
+ server: {clients},
}) => ({
selectedPlugin,
devices,
selectedDeviceIndex,
pluginStates,
+ selectedApp,
+ clients,
}),
{
setPluginState,
diff --git a/src/chrome/MainSidebar.js b/src/chrome/MainSidebar.js
index 4a7b7f97c..599090ba3 100644
--- a/src/chrome/MainSidebar.js
+++ b/src/chrome/MainSidebar.js
@@ -221,11 +221,13 @@ class MainSidebar extends Component {
export default connect(
({
connections: {devices, selectedDeviceIndex, selectedPlugin, selectedApp},
+ server: {clients},
}) => ({
devices,
selectedDeviceIndex,
selectedPlugin,
selectedApp,
+ clients,
}),
{
selectPlugin,
diff --git a/src/device-plugins/logs/index.js b/src/device-plugins/logs/index.js
index 52def9bfd..169815300 100644
--- a/src/device-plugins/logs/index.js
+++ b/src/device-plugins/logs/index.js
@@ -554,6 +554,7 @@ export default class LogTable extends SonarDevicePlugin {
defaultFilters={DEFAULT_FILTERS}
zebra={false}
actions={}
+ stickyBottom={true}
/>
);
diff --git a/src/dispatcher/androidDevice.js b/src/dispatcher/androidDevice.js
index b11bfae01..950d847df 100644
--- a/src/dispatcher/androidDevice.js
+++ b/src/dispatcher/androidDevice.js
@@ -9,6 +9,7 @@ import AndroidDevice from '../devices/AndroidDevice';
import child_process from 'child_process';
import type {Store} from '../reducers/index.js';
import type BaseDevice from '../devices/BaseDevice';
+import type Logger from '../fb-stubs/Logger.js';
const adb = require('adbkit-fb');
function createDecive(client, device): Promise {
@@ -47,7 +48,7 @@ function getRunningEmulatorName(id: string): Promise {
});
}
-export default (store: Store) => {
+export default (store: Store, logger: Logger) => {
const client = adb.createClient();
// get emulators
diff --git a/src/dispatcher/application.js b/src/dispatcher/application.js
index 0a4190347..21ba4a56c 100644
--- a/src/dispatcher/application.js
+++ b/src/dispatcher/application.js
@@ -7,8 +7,9 @@
import {remote} from 'electron';
import type {Store} from '../reducers/index.js';
+import type Logger from '../fb-stubs/Logger.js';
-export default (store: Store) => {
+export default (store: Store, logger: Logger) => {
const currentWindow = remote.getCurrentWindow();
currentWindow.on('focus', () =>
store.dispatch({
diff --git a/src/dispatcher/iOSDevice.js b/src/dispatcher/iOSDevice.js
index 559ca7fca..a3dc5c0e2 100644
--- a/src/dispatcher/iOSDevice.js
+++ b/src/dispatcher/iOSDevice.js
@@ -7,6 +7,8 @@
import type {ChildProcess} from 'child_process';
import type {Store} from '../reducers/index.js';
+import type Logger from '../fb-stubs/Logger.js';
+
import child_process from 'child_process';
import IOSDevice from '../devices/IOSDevice';
@@ -49,7 +51,7 @@ function querySimulatorDevices(): Promise {
});
}
-export default (store: Store) => {
+export default (store: Store, logger: Logger) => {
// monitoring iOS devices only available on MacOS.
if (process.platform !== 'darwin') {
return;
diff --git a/src/dispatcher/index.js b/src/dispatcher/index.js
index dc22d6de5..66f4152b2 100644
--- a/src/dispatcher/index.js
+++ b/src/dispatcher/index.js
@@ -8,7 +8,13 @@
import androidDevice from './androidDevice';
import iOSDevice from './iOSDevice';
import application from './application';
+import tracking from './tracking';
+import server from './server';
+
+import type Logger from '../fb-stubs/Logger.js';
import type {Store} from '../reducers/index.js';
-export default (store: Store) =>
- [application, androidDevice, iOSDevice].forEach(fn => fn(store));
+export default (store: Store, logger: Logger) =>
+ [application, androidDevice, iOSDevice, tracking, server].forEach(fn =>
+ fn(store, logger),
+ );
diff --git a/src/dispatcher/server.js b/src/dispatcher/server.js
new file mode 100644
index 000000000..72568d4ca
--- /dev/null
+++ b/src/dispatcher/server.js
@@ -0,0 +1,44 @@
+/**
+ * Copyright 2018-present Facebook.
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ * @format
+ */
+
+import Server from '../server.js';
+
+import type {Store} from '../reducers/index.js';
+import type Logger from '../fb-stubs/Logger.js';
+
+export default (store: Store, logger: Logger) => {
+ const server = new Server(logger);
+ server.addListener('new-client', (client: Client) => {
+ store.dispatch({
+ type: 'NEW_CLIENT',
+ payload: client,
+ });
+ });
+
+ server.addListener('removed-client', (id: string) => {
+ store.dispatch({
+ type: 'CLIENT_REMOVED',
+ payload: id,
+ });
+ });
+
+ server.addListener('error', err => {
+ const payload: string =
+ err.code === 'EADDRINUSE'
+ ? "Couldn't start websocket server. Looks like you have multiple copies of Sonar running."
+ : err.message || 'Unknown error';
+
+ store.dispatch({
+ type: 'SERVER_ERROR',
+ payload,
+ });
+ });
+
+ window.addEventListener('beforeunload', () => {
+ server.close();
+ });
+};
diff --git a/src/dispatcher/tracking.js b/src/dispatcher/tracking.js
new file mode 100644
index 000000000..9f4c8758f
--- /dev/null
+++ b/src/dispatcher/tracking.js
@@ -0,0 +1,44 @@
+/**
+ * Copyright 2018-present Facebook.
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ * @format
+ */
+
+import {ipcRenderer} from 'electron';
+
+import type BaseDevice from '../devices/BaseDevice.js';
+import type {Store} from '../reducers/index.js';
+import type Logger from '../fb-stubs/Logger.js';
+
+export default (store: Store, logger: Logger) => {
+ ipcRenderer.on('trackUsage', () => {
+ const {
+ devices,
+ selectedDeviceIndex,
+ selectedPlugin,
+ selectedApp,
+ } = store.getState().connections;
+
+ const device: ?BaseDevice =
+ selectedDeviceIndex > -1 ? devices[selectedDeviceIndex] : null;
+ console.log(1, 2, 3);
+ if (!device || !selectedPlugin) {
+ return;
+ }
+ if (selectedApp) {
+ logger.track('usage', 'ping', {
+ app: selectedApp,
+ device,
+ os: device.os,
+ plugin: selectedPlugin,
+ });
+ } else {
+ logger.track('usage', 'ping', {
+ os: device.os,
+ plugin: selectedPlugin,
+ device: device.title,
+ });
+ }
+ });
+};
diff --git a/src/init.js b/src/init.js
index 90a61d2fe..1c2915ae7 100644
--- a/src/init.js
+++ b/src/init.js
@@ -10,7 +10,9 @@ import ReactDOM from 'react-dom';
import {ContextMenuProvider} from 'sonar';
import {precachedIcons} from './utils/icons.js';
import GK from './fb-stubs/GK.js';
+import Logger from './fb-stubs/Logger.js';
import App from './App.js';
+import BugReporter from './fb-stubs/BugReporter.js';
import {createStore} from 'redux';
import reducers from './reducers/index.js';
import dispatcher from './dispatcher/index.js';
@@ -22,15 +24,16 @@ const store = createStore(
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
);
-dispatcher(store);
-
+const logger = new Logger();
+const bugReporter = new BugReporter(logger);
+dispatcher(store, logger);
GK.init();
setupMenuBar();
const AppFrame = () => (
-
+
);
diff --git a/src/reducers/index.js b/src/reducers/index.js
index 2af1bbd96..f16a3e02a 100644
--- a/src/reducers/index.js
+++ b/src/reducers/index.js
@@ -8,6 +8,7 @@
import {combineReducers} from 'redux';
import application from './application.js';
import connections from './connections.js';
+import server from './server.js';
import pluginStates from './pluginStates.js';
import type {
State as ApplicationState,
@@ -21,6 +22,7 @@ import type {
State as PluginsState,
Action as PluginsAction,
} from './pluginStates.js';
+import type {State as ServerState, Action as ServerAction} from './server.js';
import type {Store as ReduxStore} from 'redux';
export type Store = ReduxStore<
@@ -28,8 +30,14 @@ export type Store = ReduxStore<
application: ApplicationState,
connections: DevicesState,
pluginStates: PluginsState,
+ server: ServerState,
},
- ApplicationAction | DevicesAction | PluginsAction,
+ ApplicationAction | DevicesAction | PluginsAction | ServerAction,
>;
-export default combineReducers({application, connections, pluginStates});
+export default combineReducers({
+ application,
+ connections,
+ pluginStates,
+ server,
+});
diff --git a/src/reducers/server.js b/src/reducers/server.js
new file mode 100644
index 000000000..84e342855
--- /dev/null
+++ b/src/reducers/server.js
@@ -0,0 +1,54 @@
+/**
+ * Copyright 2018-present Facebook.
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ * @format
+ */
+
+export type State = {
+ error: ?string,
+ clients: Array,
+};
+
+export type Action =
+ | {
+ type: 'SERVER_ERROR',
+ payload: ?string,
+ }
+ | {
+ type: 'NEW_CLIENT',
+ payload: Client,
+ }
+ | {
+ type: 'CLIENT_REMOVED',
+ payload: string,
+ };
+
+const INITIAL_STATE: State = {
+ error: null,
+ clients: [],
+};
+
+export default function reducer(
+ state: State = INITIAL_STATE,
+ action: Action,
+): State {
+ if (action.type === 'NEW_CLIENT') {
+ const {payload} = action;
+ return {
+ ...state,
+ clients: state.clients.concat(payload),
+ };
+ } else if (action.type === 'CLIENT_REMOVED') {
+ const {payload} = action;
+ return {
+ ...state,
+ clients: state.clients.filter((client: Client) => client.id !== payload),
+ };
+ } else if (action.type === 'SERVER_ERROR') {
+ const {payload} = action;
+ return {...state, error: payload};
+ } else {
+ return state;
+ }
+}
diff --git a/src/server.js b/src/server.js
index 343b28557..8873fc74b 100644
--- a/src/server.js
+++ b/src/server.js
@@ -5,7 +5,6 @@
* @format
*/
-import type {App} from './App.js';
import type {SecureServerConfig} from './utils/CertificateProvider';
import type Logger from './fb-stubs/Logger';
import type {ClientQuery} from './Client.js';
@@ -40,14 +39,14 @@ export default class Server extends EventEmitter {
insecureServer: RSocketServer;
certificateProvider: CertificateProvider;
connectionTracker: ConnectionTracker;
- app: App;
+ logger: Logger;
- constructor(app: App) {
+ constructor(logger: Logger) {
super();
- this.app = app;
+ this.logger = logger;
this.connections = new Map();
- this.certificateProvider = new CertificateProvider(this, app.logger);
- this.connectionTracker = new ConnectionTracker(app.logger);
+ this.certificateProvider = new CertificateProvider(this, logger);
+ this.connectionTracker = new ConnectionTracker(logger);
this.init();
}
@@ -186,7 +185,7 @@ export default class Server extends EventEmitter {
const id = `${query.app}-${query.os}-${query.device}`;
console.warn(`Device connected: ${id}`, 'connection');
- const client = new Client(this.app, id, query, conn);
+ const client = new Client(id, query, conn, this.logger);
const info = {
client,
@@ -235,6 +234,7 @@ export default class Server extends EventEmitter {
info.client.emit('close');
this.connections.delete(id);
this.emit('clients-change');
+ this.emit('removed-client', id);
}
}
}
diff --git a/static/index.js b/static/index.js
index ad1286379..faff72c7a 100644
--- a/static/index.js
+++ b/static/index.js
@@ -11,6 +11,10 @@ const fs = require('fs');
const compilePlugins = require('./compilePlugins.js');
const os = require('os');
+if (!process.env.ANDROID_HOME) {
+ process.env.ANDROID_HOME = '/opt/android_sdk';
+}
+
// ensure .sonar folder and config exist
const sonarDir = path.join(os.homedir(), '.sonar');
if (!fs.existsSync(sonarDir)) {