Skip to content

Commit 0a3dad5

Browse files
feat: Add stop recording button to in-browser controls (#688)
1 parent fd16d2b commit 0a3dad5

File tree

8 files changed

+55
-2
lines changed

8 files changed

+55
-2
lines changed

extension/src/background/routing.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ studio.forward('highlight-elements', [frontend])
2424
frontend.forward('record-events', [background])
2525
frontend.forward('navigate', [background])
2626
frontend.forward('load-events', [background])
27+
frontend.forward('stop-recording', [studio])
2728

2829
export { background as client }

extension/src/frontend/routing.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const background = new BrowserExtensionClient(
1111
frontend.forward('record-events', [background])
1212
frontend.forward('navigate', [background])
1313
frontend.forward('load-events', [background])
14+
frontend.forward('stop-recording', [background])
1415

1516
background.forward('events-recorded', [frontend])
1617
background.forward('events-loaded', [frontend])

extension/src/frontend/view/InBrowserControls.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { useState } from 'react'
22

3+
import { client } from '../routing'
4+
35
import { ElementInspector } from './ElementInspector'
46
import { EventDrawer } from './EventDrawer'
57
import { RemoteHighlights } from './RemoteHighlights'
@@ -17,6 +19,12 @@ export function InBrowserControls() {
1719
selectTool(null)
1820
}
1921

22+
const handleStopRecording = () => {
23+
client.send({
24+
type: 'stop-recording',
25+
})
26+
}
27+
2028
return (
2129
<>
2230
<RemoteHighlights />
@@ -28,6 +36,7 @@ export function InBrowserControls() {
2836
isDrawerOpen={isDrawerOpen}
2937
tool={tool}
3038
onSelectTool={selectTool}
39+
onStopRecording={handleStopRecording}
3140
onToggleDrawer={setIsDrawerOpen}
3241
/>
3342
<EventDrawer

extension/src/frontend/view/ToolBox.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
CursorArrowIcon,
44
CursorTextIcon,
55
ReaderIcon,
6+
StopIcon,
67
} from '@radix-ui/react-icons'
78

89
import { Toolbar } from '@/components/primitives/Toolbar'
@@ -14,13 +15,15 @@ interface ToolBoxProps {
1415
tool: Tool | null
1516
isDrawerOpen: boolean
1617
onSelectTool: (value: Tool | null) => void
18+
onStopRecording: () => void
1719
onToggleDrawer: (open: boolean) => void
1820
}
1921

2022
export function ToolBox({
2123
isDrawerOpen,
2224
tool,
2325
onSelectTool,
26+
onStopRecording,
2427
onToggleDrawer,
2528
}: ToolBoxProps) {
2629
const handleToolChange = (value: string) => {
@@ -54,6 +57,12 @@ export function ToolBox({
5457
border: 1px solid var(--gray-6);
5558
`}
5659
>
60+
<Tooltip delayDuration={0} asChild content="Stop recording">
61+
<Toolbar.Button onClick={onStopRecording}>
62+
<StopIcon />
63+
</Toolbar.Button>
64+
</Tooltip>
65+
<Toolbar.Separator />
5766
<Toolbar.ToggleGroup
5867
type="single"
5968
value={tool ?? ''}

extension/src/messaging/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,20 +40,27 @@ export const NavigateSchema = z.object({
4040
url: z.string(),
4141
})
4242

43+
export const StopRecordingSchema = z.object({
44+
type: z.literal('stop-recording'),
45+
})
46+
4347
export const BrowserExtensionMessageSchema = z.discriminatedUnion('type', [
4448
LoadEventsSchema,
49+
4550
EventsLoadedSchema,
4651
RecordEventsSchema,
4752
EventsRecordedSchema,
4853
HighlightElementsSchema,
4954
NavigateSchema,
55+
StopRecordingSchema,
5056
])
5157

5258
export type RecordEvents = z.infer<typeof RecordEventsSchema>
5359
export type EventsRecorded = z.infer<typeof EventsRecordedSchema>
5460
export type HighlightSelector = z.infer<typeof HighlightSelectorSchema>
5561
export type HighlightElements = z.infer<typeof HighlightElementsSchema>
5662
export type Navigate = z.infer<typeof NavigateSchema>
63+
export type StopRecording = z.infer<typeof StopRecordingSchema>
5764

5865
export type BrowserExtensionMessage = z.infer<
5966
typeof BrowserExtensionMessageSchema

src/components/primitives/Toolbar.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
import styled from '@emotion/styled'
22
import * as RadixToolbar from '@radix-ui/react-toolbar'
33

4-
const Button = styled(RadixToolbar.Button)``
4+
const Button = styled(RadixToolbar.Button)`
5+
display: flex;
6+
justify-content: center;
7+
align-items: center;
8+
cursor: pointer;
9+
color: var(--studio-foreground);
10+
background-color: var(--studio-toggle-bg-off);
11+
border: none;
12+
padding: var(--studio-spacing-2);
13+
`
514

615
const Link = styled(RadixToolbar.Link)``
716

src/handlers/browser/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,8 @@ export function initialize(browserServer: BrowserServer) {
4747
console.info(`${BrowserHandler.OpenExternalLink} event received`)
4848
return shell.openExternal(url)
4949
})
50+
51+
browserServer.on('stop-recording', () => {
52+
ipcMain.emit(BrowserHandler.Stop)
53+
})
5054
}

src/services/browser/server.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
import { BrowserWindow } from 'electron'
22

33
import { BrowserExtensionClient } from 'extension/src/messaging'
4+
import { Sender } from 'extension/src/messaging/transports/transport'
45
import { WebSocketServerTransport } from 'extension/src/messaging/transports/webSocketServer'
56
import { BrowserExtensionMessage } from 'extension/src/messaging/types'
7+
import { EventEmitter } from 'extension/src/utils/events'
68

7-
export class BrowserServer {
9+
type BrowserExtensionServerEvents = {
10+
'stop-recording': {
11+
sender?: Sender
12+
data: Extract<BrowserExtensionMessage, { type: 'stop-recording' }>
13+
}
14+
}
15+
16+
export class BrowserServer extends EventEmitter<BrowserExtensionServerEvents> {
817
#client: BrowserExtensionClient | null = null
918

1019
start(browserWindow: BrowserWindow) {
@@ -16,6 +25,10 @@ export class BrowserServer {
1625
this.#client.on('events-recorded', (event) => {
1726
browserWindow.webContents.send('browser:event', event.data.events)
1827
})
28+
29+
this.#client.on('stop-recording', (event) => {
30+
this.emit('stop-recording', event)
31+
})
1932
}
2033

2134
send(message: BrowserExtensionMessage) {

0 commit comments

Comments
 (0)