summaryrefslogtreecommitdiff
path: root/app_expo/services/reactotron
diff options
context:
space:
mode:
Diffstat (limited to 'app_expo/services/reactotron')
-rw-r--r--app_expo/services/reactotron/index.ts1
-rw-r--r--app_expo/services/reactotron/reactotron-config.ts30
-rw-r--r--app_expo/services/reactotron/reactotron.ts185
-rw-r--r--app_expo/services/reactotron/tron.ts2
-rw-r--r--app_expo/services/reactotron/tron.web.ts2
5 files changed, 220 insertions, 0 deletions
diff --git a/app_expo/services/reactotron/index.ts b/app_expo/services/reactotron/index.ts
new file mode 100644
index 0000000..0c02f1f
--- /dev/null
+++ b/app_expo/services/reactotron/index.ts
@@ -0,0 +1 @@
+export * from './reactotron'
diff --git a/app_expo/services/reactotron/reactotron-config.ts b/app_expo/services/reactotron/reactotron-config.ts
new file mode 100644
index 0000000..40e9c93
--- /dev/null
+++ b/app_expo/services/reactotron/reactotron-config.ts
@@ -0,0 +1,30 @@
+export interface ReactotronConfig {
+ /** The name of the app. */
+ name?: string
+ /** The host to connect to: default 'localhost'. */
+ host?: string
+ /** Should we use async storage */
+ useAsyncStorage?: boolean
+ /** Should we clear Reactotron when load? */
+ clearOnLoad?: boolean
+ /** Root state logging. */
+ state?: {
+ /** log the initial data that we put into the state on startup? */
+ initial?: boolean
+ /** log snapshot changes. */
+ snapshots?: boolean
+ }
+}
+
+/**
+ * The default Reactotron configuration.
+ */
+export const DEFAULT_REACTOTRON_CONFIG: ReactotronConfig = {
+ clearOnLoad: true,
+ host: 'localhost',
+ useAsyncStorage: true,
+ state: {
+ initial: true,
+ snapshots: false,
+ },
+}
diff --git a/app_expo/services/reactotron/reactotron.ts b/app_expo/services/reactotron/reactotron.ts
new file mode 100644
index 0000000..6a20a75
--- /dev/null
+++ b/app_expo/services/reactotron/reactotron.ts
@@ -0,0 +1,185 @@
+import { Tron } from './tron'
+import AsyncStorage from '@react-native-async-storage/async-storage'
+import { RootStore } from '../../models/root-store/root-store'
+import { onSnapshot } from 'mobx-state-tree'
+import { ReactotronConfig, DEFAULT_REACTOTRON_CONFIG } from './reactotron-config'
+import { mst } from 'reactotron-mst'
+import { clear } from '../../utils/storage'
+import { RootNavigation } from '../../navigators'
+import { Platform } from 'react-native'
+
+// Teach TypeScript about the bad things we want to do.
+declare global {
+ interface Console {
+ /**
+ * Hey, it's Reactotron if we're in dev, and no-ops if we're in prod.
+ */
+ tron: typeof Tron
+ }
+}
+
+/** Do Nothing. */
+const noop = () => undefined
+
+// in dev, we attach Reactotron, in prod we attach a interface-compatible mock.
+if (__DEV__) {
+ console.tron = Tron // attach reactotron to `console.tron`
+} else {
+ // attach a mock so if things sneaky by our __DEV__ guards, we won't crash.
+ console.tron = {
+ benchmark: noop,
+ clear: noop,
+ close: noop,
+ configure: noop,
+ connect: noop,
+ display: noop,
+ error: noop,
+ image: noop,
+ log: noop,
+ logImportant: noop,
+ onCustomCommand: noop,
+ overlay: noop,
+ reportError: noop,
+ send: noop,
+ startTimer: noop,
+ storybookSwitcher: noop,
+ use: noop,
+ useReactNative: noop,
+ warn: noop,
+ }
+}
+
+/**
+ * You'll probably never use the service like this since we hang the Reactotron
+ * instance off of `console.tron`. This is only to be consistent with the other
+ * services.
+ */
+export class Reactotron {
+ config: ReactotronConfig
+
+ rootStore: any
+
+ /**
+ * Create the Reactotron service.
+ *
+ * @param config the configuration
+ */
+ constructor(config: ReactotronConfig = DEFAULT_REACTOTRON_CONFIG) {
+ // merge the passed in config with some defaults
+ this.config = {
+ host: 'localhost',
+ useAsyncStorage: true,
+ ...config,
+ state: {
+ initial: false,
+ snapshots: false,
+ ...(config && config.state),
+ },
+ }
+ }
+
+ /**
+ * Hook into the root store for doing awesome state-related things.
+ *
+ * @param rootStore The root store
+ */
+ setRootStore(rootStore: any, initialData: any) {
+ if (__DEV__) {
+ rootStore = rootStore as RootStore // typescript hack
+ this.rootStore = rootStore
+
+ const { initial, snapshots } = this.config.state
+ const name = 'ROOT STORE'
+
+ // logging features
+ if (initial) {
+ console.tron.display({
+ name,
+ value: initialData,
+ preview: 'Initial State',
+ })
+ }
+ // log state changes?
+ if (snapshots) {
+ onSnapshot(rootStore, (snapshot) => {
+ console.tron.display({ name, value: snapshot, preview: 'New State' })
+ })
+ }
+
+ console.tron.trackMstNode(rootStore)
+ }
+ }
+
+ /**
+ * Configure reactotron based on the the config settings passed in, then connect if we need to.
+ */
+ async setup() {
+ // only run this in dev... metro bundler will ignore this block: 🎉
+ if (__DEV__) {
+ // configure reactotron
+ Tron.configure({
+ name: this.config.name || require('../../../package.json').name,
+ host: this.config.host,
+ })
+
+ // hookup middleware
+ if (Platform.OS !== 'web') {
+ if (this.config.useAsyncStorage) {
+ Tron.setAsyncStorageHandler(AsyncStorage)
+ }
+ Tron.useReactNative({
+ asyncStorage: this.config.useAsyncStorage ? undefined : false,
+ })
+ }
+
+ // ignore some chatty `mobx-state-tree` actions
+ const RX = /postProcessSnapshot|@APPLY_SNAPSHOT/
+
+ // hookup mobx-state-tree middleware
+ Tron.use(
+ mst({
+ filter: (event) => RX.test(event.name) === false,
+ }),
+ )
+
+ // connect to the app
+ Tron.connect()
+
+ // Register Custom Commands
+ Tron.onCustomCommand({
+ title: 'Reset Root Store',
+ description: 'Resets the MST store',
+ command: 'resetStore',
+ handler: () => {
+ console.tron.log('resetting store')
+ clear()
+ },
+ })
+
+ Tron.onCustomCommand({
+ title: 'Reset Navigation State',
+ description: 'Resets the navigation state',
+ command: 'resetNavigation',
+ handler: () => {
+ console.tron.log('resetting navigation state')
+ RootNavigation.resetRoot({ routes: [] })
+ },
+ })
+
+ Tron.onCustomCommand({
+ title: 'Go Back',
+ description: 'Goes back',
+ command: 'goBack',
+ handler: () => {
+ console.tron.log('Going back')
+ RootNavigation.goBack()
+ },
+ })
+
+ // clear if we should
+ if (this.config.clearOnLoad) {
+ Tron.clear()
+ }
+ }
+ }
+}
diff --git a/app_expo/services/reactotron/tron.ts b/app_expo/services/reactotron/tron.ts
new file mode 100644
index 0000000..6086e48
--- /dev/null
+++ b/app_expo/services/reactotron/tron.ts
@@ -0,0 +1,2 @@
+import Reactotron from 'reactotron-react-native'
+export const Tron = Reactotron
diff --git a/app_expo/services/reactotron/tron.web.ts b/app_expo/services/reactotron/tron.web.ts
new file mode 100644
index 0000000..a525c06
--- /dev/null
+++ b/app_expo/services/reactotron/tron.web.ts
@@ -0,0 +1,2 @@
+import Reactotron from 'reactotron-react-js'
+export const Tron = Reactotron