diff --git a/android/plugins/sandbox/SandboxSonarPlugin.java b/android/plugins/sandbox/SandboxSonarPlugin.java new file mode 100644 index 000000000..e64cb11ab --- /dev/null +++ b/android/plugins/sandbox/SandboxSonarPlugin.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2004-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. + * + */ +package com.facebook.sonar.plugins.sandbox; + +import com.facebook.sonar.core.SonarArray; +import com.facebook.sonar.core.SonarConnection; +import com.facebook.sonar.core.SonarObject; +import com.facebook.sonar.core.SonarPlugin; +import com.facebook.sonar.core.SonarReceiver; +import com.facebook.sonar.core.SonarResponder; +import java.util.Map; + +public class SandboxSonarPlugin implements SonarPlugin { + public static final String ID = "Sandbox"; + + private static final String SET_METHOD_NAME = "setSandbox"; + private static final String GET_METHOD_NAME = "getSandbox"; + + private final SandboxSonarPluginStrategy mStrategy; + + public SandboxSonarPlugin(SandboxSonarPluginStrategy strategy) { + mStrategy = strategy; + } + + @Override + public String getId() { + return ID; + } + + @Override + public void onConnect(SonarConnection connection) { + connection.receive( + GET_METHOD_NAME, + new SonarReceiver() { + @Override + public void onReceive(SonarObject params, final SonarResponder responder) { + final SonarArray.Builder sandboxes = new SonarArray.Builder(); + Map knownSandboxes = mStrategy.getKnownSandboxes(); + if (knownSandboxes == null) { + responder.success(sandboxes.build()); + return; + } + for (String sandboxName : knownSandboxes.keySet()) { + sandboxes.put( + new SonarObject.Builder() + .put("name", sandboxName) + .put("value", knownSandboxes.get(sandboxName))); + } + responder.success(sandboxes.build()); + } + }); + connection.receive( + SET_METHOD_NAME, + new SonarReceiver() { + @Override + public void onReceive(SonarObject params, SonarResponder responder) throws Exception { + String sandbox = params.getString("sandbox"); + mStrategy.setSandbox(sandbox); + responder.success(new SonarObject.Builder().put("result", true).build()); + } + }); + } + + @Override + public void onDisconnect() {} +} diff --git a/android/plugins/sandbox/SandboxSonarPluginStrategy.java b/android/plugins/sandbox/SandboxSonarPluginStrategy.java new file mode 100644 index 000000000..a0d96dffc --- /dev/null +++ b/android/plugins/sandbox/SandboxSonarPluginStrategy.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2004-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. + * + */ +package com.facebook.sonar.plugins.sandbox; + +import java.util.Map; +import javax.annotation.Nullable; + +public interface SandboxSonarPluginStrategy { + + @Nullable + Map getKnownSandboxes(); + + void setSandbox(@Nullable String sandbox); +} diff --git a/docs/sandbox-plugin.md b/docs/sandbox-plugin.md new file mode 100644 index 000000000..1c2023c95 --- /dev/null +++ b/docs/sandbox-plugin.md @@ -0,0 +1,25 @@ +--- +id: sandbox-plugin +title: Sandbox +--- + +The Sandbox plugin is useful for developers that had to test changes of their apps by pointing them to some Sandbox environment. Through this plugin and a few lines of code in the client, +the app can get a callback and get the value that the user has input through Sonar. At this point, the developer can plugin its logic to save this setting in its app. + +## Setup + +To use the sandbox plugin, you need to add the plugin to your Sonar client instance. + +### Android + +```java +import com.facebook.sonar.plugins.SandboxSonarPlugin; +import com.facebook.sonar.plugins.SandboxSonarPluginStrategy; + +final SandboxSonarPluginStrategy strategy = getStrategy(); // Your strategy goes here +client.addPlugin(new SandboxSonarPlugin(strategy)); +``` + +### iOS + +Coming soon diff --git a/src/plugins/sandbox/index.js b/src/plugins/sandbox/index.js new file mode 100644 index 000000000..54c6d7374 --- /dev/null +++ b/src/plugins/sandbox/index.js @@ -0,0 +1,144 @@ +/** + * 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 {SonarPlugin} from 'sonar'; +import {FlexColumn} from 'sonar'; +import {ButtonGroup, Button, styled, colors} from 'sonar'; + +export type Sandbox = { + name: string, + value: string, +}; + +type SandboxState = {| + sandboxes: Array, + customSandbox: string, + showFeedback: boolean, +|}; + +const BigButton = Button.extends({ + flexGrow: 1, + fontSize: 24, + padding: 20, +}); + +const ButtonContainer = FlexColumn.extends({ + alignItems: 'center', + padding: 20, +}); + +export default class SandboxView extends SonarPlugin { + state = { + sandboxes: [], + customSandbox: '', + showFeedback: false, + }; + + static title = 'Sandbox'; + static id = 'Sandbox'; + static icon = 'translate'; + + static TextInput = styled.textInput({ + border: `1px solid ${colors.light10}`, + fontSize: '1em', + padding: '0 5px', + borderRight: 0, + borderTopLeftRadius: 4, + borderBottomLeftRadius: 4, + flexGrow: 1, + }); + + static FeedbackMessage = styled.text({ + fontSize: '1.2em', + paddingTop: '10px', + color: 'green', + }); + + static TextInputLayout = FlexColumn.extends({ + float: 'left', + justifyContent: 'center', + flexGrow: 1, + borderRadius: 4, + marginRight: 15, + marginTop: 15, + marginLeft: 15, + }); + + reducers = { + UpdateSandboxes(state: SandboxState, results: Object) { + return { + sandboxes: results.results, + }; + }, + }; + + init() { + this.client.call('getSandbox', {}).then((results: Array) => { + this.dispatchAction({results, type: 'UpdateSandboxes'}); + }); + } + + onSendSandboxEnvironment = (sandbox: string) => { + this.client + .call('setSandbox', { + sandbox: sandbox, + }) + .then((result: Object) => { + setTimeout(() => { + this.setState({showFeedback: false}); + }, 3000); + this.setState({showFeedback: result.result}); + }); + }; + + onChangeSandbox = (e: SyntheticInputEvent<>) => { + this.setState({customSandbox: e.target.value}); + }; + + render() { + return ( + + + + { + if (event.key === 'Enter') { + this.onSendSandboxEnvironment(this.state.customSandbox); + } + }} + /> +