Skip to content

Commit d63bb4f

Browse files
committed
Add a lot of analytics events for the app.
1 parent 6e38615 commit d63bb4f

File tree

9 files changed

+203
-20
lines changed

9 files changed

+203
-20
lines changed

apps/reactotron-app/src/renderer/RootModals.tsx

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import {
55
ReactotronContext,
66
StateContext,
77
} from "reactotron-core-ui"
8+
import { useAnalytics } from "./util/analyticsHelpers"
89

910
function RootModals() {
11+
const { sendAnalyticsEvent } = useAnalytics()
1012
const {
1113
sendCommand,
1214

@@ -20,30 +22,44 @@ function RootModals() {
2022
} = useContext(ReactotronContext)
2123
const { addSubscription } = useContext(StateContext)
2224

23-
const dispatchAction = (action: any) => {
24-
sendCommand("state.action.dispatch", { action })
25-
}
26-
2725
return (
2826
<>
2927
<DispatchActionModal
3028
isOpen={isDispatchModalOpen}
3129
initialValue={dispatchModalInitialAction}
3230
onClose={() => {
3331
closeDispatchModal()
32+
sendAnalyticsEvent({
33+
category: "dispatch",
34+
action: "dispatchAbort",
35+
})
36+
}}
37+
onDispatchAction={(action: any) => {
38+
sendCommand("state.action.dispatch", { action })
39+
sendAnalyticsEvent({
40+
category: "dispatch",
41+
action: "dispatchConfirm",
42+
})
3443
}}
35-
onDispatchAction={dispatchAction}
3644
isDarwin={window.process.platform === "darwin"}
3745
/>
3846
<SubscriptionAddModal
3947
isOpen={isSubscriptionModalOpen}
4048
onClose={() => {
4149
closeSubscriptionModal()
50+
sendAnalyticsEvent({
51+
category: "subscription",
52+
action: "addAbort",
53+
})
4254
}}
4355
onAddSubscription={(path: string) => {
4456
// TODO: Get this out of here.
4557
closeSubscriptionModal()
4658
addSubscription(path)
59+
sendAnalyticsEvent({
60+
category: "subscription",
61+
action: "addConfirm",
62+
})
4763
}}
4864
/>
4965
</>

apps/reactotron-app/src/renderer/pages/help/components/AndroidDeviceHelp.tsx

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ import { IoReloadOutline as ReloadAppIcon } from "react-icons/io5"
88
import { EmptyState, Tooltip } from "reactotron-core-ui"
99
import { FaAndroid } from "react-icons/fa"
1010
import { ItemContainer, ItemIconContainer } from "../SharedStyles"
11+
import { useAnalytics } from "../../../util/analyticsHelpers"
12+
13+
interface IAndroidDevice {
14+
id: string
15+
state: string
16+
}
1117

1218
const Container = styled.div`
1319
margin: 50px 0px;
@@ -101,18 +107,19 @@ const PortSettingsIconContainer = styled.div`
101107
`
102108

103109
function AndroidDeviceHelp() {
104-
const [androidDevices, setAndroidDevices] = React.useState([])
110+
const [androidDevices, setAndroidDevices] = React.useState<IAndroidDevice[]>([])
105111
const [portsVisible, setPortsVisible] = React.useState(false)
106112
const [reactotronPort, setReactotronPort] = React.useState("9090")
107113
const [metroPort, setMetroPort] = React.useState("8081")
114+
const { sendAnalyticsEvent } = useAnalytics()
108115

109116
// When the page loads, get the list of devices from ADB to help users debug android issues.
110117
React.useEffect(() => {
111118
ipcRenderer.on("device-list", (_event, arg) => {
112119
arg = arg.replace(/(\r\n|\n|\r)/gm, "\n").trim() // Fix newlines
113120
const rawDevices = arg.split("\n")
114121
rawDevices.shift() // Remove the first line
115-
const devices = rawDevices.map((device) => {
122+
const devices: IAndroidDevice[] = rawDevices.map((device) => {
116123
const [id, state] = device.split("\t")
117124
return { id, state }
118125
})
@@ -142,7 +149,14 @@ function AndroidDeviceHelp() {
142149
<PortSettingsIconContainer
143150
data-tip="Advanced Port Settings"
144151
data-for="port-settings"
145-
onClick={() => setPortsVisible(!portsVisible)}
152+
onClick={() => {
153+
setPortsVisible(!portsVisible)
154+
sendAnalyticsEvent({
155+
category: "android",
156+
action: "settings",
157+
label: portsVisible ? "close" : "open",
158+
})
159+
}}
146160
>
147161
<SettingsIcon size={20} />
148162
<Tooltip id="port-settings" />
@@ -210,16 +224,21 @@ const AndroidDeviceList = ({
210224
reactotronPort: string
211225
metroPort: string
212226
}) => {
227+
const { sendAnalyticsEvent } = useAnalytics()
213228
return (
214229
<>
215230
{devices.map((device) => (
216231
<div key={device.id}>
217232
<DeviceID>{device.id}</DeviceID>
218233
<AndroidDeviceButtonsContainer>
219234
<ItemContainer
220-
onClick={() =>
235+
onClick={() => {
221236
ipcRenderer.send("reverse-tunnel-device", device.id, reactotronPort, metroPort)
222-
}
237+
sendAnalyticsEvent({
238+
category: "android",
239+
action: "reverse-tunnel",
240+
})
241+
}}
223242
data-tip={`This will allow reactotron to connect to your device via USB<br />by running adb reverse tcp:${reactotronPort} tcp:${reactotronPort}<br /><br />Reload your React Native app after pressing this.`}
224243
data-for="reverse-tunnel"
225244
>
@@ -230,7 +249,13 @@ const AndroidDeviceList = ({
230249
<Tooltip id="reverse-tunnel" multiline />
231250
</ItemContainer>
232251
<ItemContainer
233-
onClick={() => ipcRenderer.send("reload-app", device.id)}
252+
onClick={() => {
253+
ipcRenderer.send("reload-app", device.id)
254+
sendAnalyticsEvent({
255+
category: "android",
256+
action: "reload-app",
257+
})
258+
}}
234259
data-tip="This will reload the React Native app currently running on this device.<br />If you get the React Native red screen, relaunch the app from the build process."
235260
data-for="reload-app"
236261
>
@@ -241,7 +266,13 @@ const AndroidDeviceList = ({
241266
<Tooltip id="reload-app" multiline />
242267
</ItemContainer>
243268
<ItemContainer
244-
onClick={() => ipcRenderer.send("shake-device", device.id)}
269+
onClick={() => {
270+
ipcRenderer.send("shake-device", device.id)
271+
sendAnalyticsEvent({
272+
category: "android",
273+
action: "shake-device",
274+
})
275+
}}
245276
data-tip="This will shake the device to bring up<br /> the React Native developer menu."
246277
data-for="shake-device"
247278
>

apps/reactotron-app/src/renderer/pages/help/index.tsx

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ import { getApplicationKeyMap } from "react-hotkeys"
1212
import { ItemContainer, ItemIconContainer } from "./SharedStyles"
1313
import KeybindGroup from "./components/KeybindGroup"
1414
import { reactotronLogo } from "../../images"
15-
16-
const projectJson = require("../../../../package.json")
15+
import { useAnalytics } from "../../util/analyticsHelpers"
16+
import projectJson from "../../../../package.json"
1717

1818
const Container = styled.div`
1919
display: flex;
@@ -85,6 +85,8 @@ function Keybinds() {
8585
}
8686

8787
function Help() {
88+
const { sendExternalLinkAnalyticsEvent } = useAnalytics()
89+
8890
return (
8991
<Container>
9092
<Header title={`Using Reactotron ${projectJson.version}`} isDraggable />
@@ -94,25 +96,45 @@ function Help() {
9496
</LogoContainer>
9597
<Title>Let&apos;s Connect!</Title>
9698
<ConnectContainer>
97-
<ItemContainer onClick={openRepo}>
99+
<ItemContainer
100+
onClick={() => {
101+
openRepo()
102+
sendExternalLinkAnalyticsEvent("repo")
103+
}}
104+
>
98105
<ItemIconContainer>
99106
<RepoIcon size={40} />
100107
</ItemIconContainer>
101108
GitHub Docs
102109
</ItemContainer>
103-
<ItemContainer onClick={openFeedback}>
110+
<ItemContainer
111+
onClick={() => {
112+
openFeedback()
113+
sendExternalLinkAnalyticsEvent("feedback")
114+
}}
115+
>
104116
<ItemIconContainer>
105117
<FeedbackIcon size={40} />
106118
</ItemIconContainer>
107119
Feedback
108120
</ItemContainer>
109-
<ItemContainer onClick={openUpdates}>
121+
<ItemContainer
122+
onClick={() => {
123+
openUpdates()
124+
sendExternalLinkAnalyticsEvent("updates")
125+
}}
126+
>
110127
<ItemIconContainer>
111128
<ReleaseIcon size={40} />
112129
</ItemIconContainer>
113130
Updates
114131
</ItemContainer>
115-
<ItemContainer onClick={openTwitter}>
132+
<ItemContainer
133+
onClick={() => {
134+
openTwitter()
135+
sendExternalLinkAnalyticsEvent("twitter")
136+
}}
137+
>
116138
<ItemIconContainer>
117139
<TwitterIcon size={40} />
118140
</ItemIconContainer>

apps/reactotron-app/src/renderer/pages/reactNative/Overlay.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { OverlayMargins } from "./components/OverlayMargins"
1717
import type { DragEvent } from "react"
1818
import type { JustifyContent, AlignItems } from "./components/OverlayAlignment"
1919
import type { ResizeMode } from "./components/OverlayResizeMode"
20+
import { useAnalytics } from "../../util/analyticsHelpers"
2021

2122
const isDevelopment = process.env.NODE_ENV !== "production"
2223

@@ -54,6 +55,7 @@ const ReapplyContainer = styled.div`
5455
`
5556

5657
function Overlay() {
58+
const { sendAnalyticsEvent } = useAnalytics()
5759
const { overlayParams, updateOverlayParams } = useContext(ReactNativeContext)
5860
const {
5961
uri,
@@ -123,8 +125,18 @@ function Overlay() {
123125
event.preventDefault()
124126
event.stopPropagation()
125127
if (event.dataTransfer.files.length !== 1) {
128+
sendAnalyticsEvent({
129+
category: "error",
130+
action: "OverlayDropImage",
131+
label: "Too many files",
132+
})
126133
return
127134
}
135+
sendAnalyticsEvent({
136+
category: "overlay",
137+
action: "OverlayDropImage",
138+
label: "Success",
139+
})
128140
const file = event.dataTransfer.files[0]
129141
importFile(file.path)
130142
}
@@ -144,6 +156,11 @@ function Overlay() {
144156
alignItems: "center",
145157
justifyContent: "center",
146158
})
159+
sendAnalyticsEvent({
160+
category: "overlay",
161+
action: "OverlayRemoveImage",
162+
label: "Success",
163+
})
147164
}
148165

149166
function handlePreventDefault(event: DragEvent<HTMLDivElement>) {
@@ -200,6 +217,11 @@ function Overlay() {
200217
event.stopPropagation()
201218
event.preventDefault()
202219
updateOverlayParams({ showDebug: newShowDebug })
220+
sendAnalyticsEvent({
221+
category: "overlay",
222+
action: "OverlayShowDebug",
223+
label: newShowDebug ? "On" : "Off",
224+
})
203225
}
204226

205227
function renderDropZone() {

apps/reactotron-app/src/renderer/pages/reactNative/Storybook.tsx

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
MdWarning,
1010
} from "react-icons/md"
1111
import { storybookActiveImg, storybookInactiveImg } from "../../images"
12+
import { useAnalytics } from "../../util/analyticsHelpers"
1213

1314
const Container = styled.div`
1415
display: flex;
@@ -60,6 +61,7 @@ const WarningDescription = styled.div`
6061
`
6162

6263
function Storybook() {
64+
const { sendAnalyticsEvent } = useAnalytics()
6365
const { isStorybookOn, turnOffStorybook, turnOnStorybook } = useContext(ReactNativeContext)
6466

6567
return (
@@ -121,15 +123,33 @@ function Storybook() {
121123
<StorybookLogo src={isStorybookOn ? storybookActiveImg : storybookInactiveImg} />
122124

123125
<ToggleContainer>
124-
<RadioButton onClick={() => turnOnStorybook()}>
126+
<RadioButton
127+
onClick={() => {
128+
turnOnStorybook()
129+
sendAnalyticsEvent({
130+
category: "storybook",
131+
action: "ToggleStorybook",
132+
label: "On",
133+
})
134+
}}
135+
>
125136
{isStorybookOn ? (
126137
<MdRadioButtonChecked size={32} />
127138
) : (
128139
<MdRadioButtonUnchecked size={32} />
129140
)}
130141
<div>On</div>
131142
</RadioButton>
132-
<RadioButton onClick={() => turnOffStorybook()}>
143+
<RadioButton
144+
onClick={() => {
145+
turnOffStorybook()
146+
sendAnalyticsEvent({
147+
category: "storybook",
148+
action: "ToggleStorybook",
149+
label: "Off",
150+
})
151+
}}
152+
>
133153
{isStorybookOn ? (
134154
<MdRadioButtonUnchecked size={32} />
135155
) : (

0 commit comments

Comments
 (0)