Skip to content

Commit 1dd0947

Browse files
fix: It's possible to start a recording with no supported browser installed (#523)
1 parent 1d55758 commit 1dd0947

File tree

14 files changed

+225
-87
lines changed

14 files changed

+225
-87
lines changed

src/App.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ import { Global } from '@emotion/react'
33
import { QueryClientProvider } from '@tanstack/react-query'
44
import { enableMapSet } from 'immer'
55

6-
import { useTheme } from './hooks/useTheme'
6+
import { DevToolsDialog } from '@/components/DevToolsDialog'
7+
import { SettingsDialog } from '@/components/Settings/SettingsDialog'
8+
import { Toasts } from '@/components/Toast/Toasts'
9+
import { useCloseSplashScreen } from '@/hooks/useCloseSplashScreen'
10+
import { useTheme } from '@/hooks/useTheme'
11+
import { queryClient } from '@/utils/query'
712
import { globalStyles } from './globalStyles'
813
import { AppRoutes } from './AppRoutes'
9-
import { Toasts } from './components/Toast/Toasts'
10-
import { queryClient } from './utils/query'
11-
import { useCloseSplashScreen } from './hooks/useCloseSplashScreen'
12-
import { DevToolsDialog } from './components/DevToolsDialog'
1314

1415
enableMapSet()
1516

@@ -24,6 +25,7 @@ export function App() {
2425
<Toasts />
2526
<AppRoutes />
2627
<DevToolsDialog />
28+
<SettingsDialog />
2729
</Theme>
2830
</QueryClientProvider>
2931
)

src/browser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const createUserDataDir = async () => {
1515
return mkdtemp(path.join(os.tmpdir(), 'k6-studio-'))
1616
}
1717

18-
function getBrowserPath() {
18+
export function getBrowserPath() {
1919
const { recorder } = appSettings
2020

2121
if (recorder.detectBrowserPath) {

src/components/Form/FileUploadInput.tsx

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Flex, TextField, Button } from '@radix-ui/themes'
22
import { FieldGroup } from './FieldGroup'
33
import { Controller, FieldErrors } from 'react-hook-form'
4+
import { css } from '@emotion/react'
45

56
type FileUploadInputProps = {
67
name: string
@@ -34,29 +35,26 @@ export const FileUploadInput = ({
3435
hint={hint}
3536
hintType="text"
3637
>
37-
<TextField.Root
38-
type="text"
39-
disabled={disabled}
40-
onChange={field.onChange}
41-
name={field.name}
42-
// TODO: https://github.com/grafana/k6-studio/issues/277
43-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
44-
value={field.value}
45-
/>
38+
<Flex gap="2" width="100%">
39+
<TextField.Root
40+
css={css`
41+
flex: 1;
42+
`}
43+
type="text"
44+
disabled={disabled}
45+
onChange={field.onChange}
46+
name={field.name}
47+
// TODO: https://github.com/grafana/k6-studio/issues/277
48+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
49+
value={field.value}
50+
/>
51+
<Button disabled={disabled} onClick={onSelectFile} type="button">
52+
{buttonText}
53+
</Button>
54+
</Flex>
4655
</FieldGroup>
4756
)}
4857
/>
49-
50-
<Button
51-
ml="2"
52-
disabled={disabled}
53-
onClick={onSelectFile}
54-
style={{
55-
marginTop: 48,
56-
}}
57-
>
58-
{buttonText}
59-
</Button>
6058
</Flex>
6159
)
6260
}

src/components/Layout/ActivityBar/ProxyStatusIndicator.tsx

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import { css } from '@emotion/react'
22
import { Link1Icon, LinkBreak1Icon, LinkNone1Icon } from '@radix-ui/react-icons'
33
import { Box, Flex, Tooltip } from '@radix-ui/themes'
4-
import { useEffect } from 'react'
54

6-
import { useStudioUIStore } from '@/store/ui'
75
import type { ProxyStatus } from '@/types'
86
import { exhaustive } from '@/utils/typescript'
7+
import { useProxyStatus } from '@/hooks/useProxyStatus'
98

109
const COLOR_MAP: Record<ProxyStatus, string> = {
1110
['online']: 'var(--green-9)',
@@ -14,19 +13,7 @@ const COLOR_MAP: Record<ProxyStatus, string> = {
1413
}
1514

1615
export function ProxyStatusIndicator() {
17-
const status = useStudioUIStore((state) => state.proxyStatus)
18-
const setProxyStatus = useStudioUIStore((state) => state.setProxyStatus)
19-
20-
useEffect(() => {
21-
;(async function fetchProxyStatus() {
22-
const status = await window.studio.proxy.getProxyStatus()
23-
setProxyStatus(status)
24-
})()
25-
26-
return window.studio.proxy.onProxyStatusChange((status) =>
27-
setProxyStatus(status)
28-
)
29-
}, [setProxyStatus])
16+
const status = useProxyStatus()
3017

3118
return (
3219
<Tooltip content={`Proxy status: ${status}`} side="right">
Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,20 @@
1-
import { SettingsDialog } from '@/components/Settings/SettingsDialog'
1+
import { useStudioUIStore } from '@/store/ui'
22
import { GearIcon } from '@radix-ui/react-icons'
33
import { Tooltip, IconButton } from '@radix-ui/themes'
4-
import { useState } from 'react'
54

65
export function SettingsButton() {
7-
const [open, setOpen] = useState(false)
6+
const setIsOpen = useStudioUIStore((state) => state.setIsSettingsDialogOpen)
87

98
return (
10-
<>
11-
<Tooltip content="Settings" side="right">
12-
<IconButton
13-
area-label="Settings"
14-
color="gray"
15-
variant="ghost"
16-
onClick={() => setOpen(true)}
17-
>
18-
<GearIcon />
19-
</IconButton>
20-
</Tooltip>
21-
22-
<SettingsDialog open={open} onOpenChange={setOpen} />
23-
</>
9+
<Tooltip content="Settings" side="right">
10+
<IconButton
11+
area-label="Settings"
12+
color="gray"
13+
variant="ghost"
14+
onClick={() => setIsOpen(true)}
15+
>
16+
<GearIcon />
17+
</IconButton>
18+
</Tooltip>
2419
)
2520
}

src/components/Settings/RecorderSettings.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export const RecorderSettings = () => {
5757
name="recorder.browserPath"
5858
onSelectFile={handleSelectFile}
5959
buttonText="Select executable"
60-
hint="The location of the browser executable (Grafana k6 Studio currently supports Chrome)"
60+
hint="Google Chrome needs to be installed on your machine for the recording functionality to work"
6161
disabled={recorder.detectBrowserPath}
6262
/>
6363
</SettingsSection>

src/components/Settings/SettingsDialog.tsx

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,8 @@ import { TelemetrySettings } from './TelemetrySettings'
1414
import { ButtonWithTooltip } from '../ButtonWithTooltip'
1515
import { AppearanceSettings } from './AppearanceSettings'
1616
import { LogsSettings } from './LogsSettings'
17-
import { useSaveSettings, useSettings } from './Settings.hooks'
18-
19-
type SettingsDialogProps = {
20-
open: boolean
21-
onOpenChange: (open: boolean) => void
22-
}
17+
import { useStudioUIStore } from '@/store/ui'
18+
import { useSaveSettings, useSettings } from '@/hooks/useSettings'
2319

2420
const tabs = [
2521
{ label: 'Proxy', value: 'proxy', component: ProxySettings },
@@ -41,10 +37,12 @@ const tabs = [
4137
},
4238
]
4339

44-
export const SettingsDialog = ({ open, onOpenChange }: SettingsDialogProps) => {
40+
export const SettingsDialog = () => {
4541
const { data: settings } = useSettings()
42+
const isOpen = useStudioUIStore((state) => state.isSettingsDialogOpen)
43+
const setIsOpen = useStudioUIStore((state) => state.setIsSettingsDialogOpen)
4644
const { mutateAsync: saveSettings, isPending } = useSaveSettings(() => {
47-
onOpenChange(false)
45+
setIsOpen(false)
4846
})
4947
const [selectedTab, setSelectedTab] = useState('proxy')
5048

@@ -71,11 +69,11 @@ export const SettingsDialog = ({ open, onOpenChange }: SettingsDialogProps) => {
7169
const handleOpenChange = () => {
7270
reset(settings)
7371
setSelectedTab('proxy')
74-
onOpenChange(!open)
72+
setIsOpen(!isOpen)
7573
}
7674

7775
return (
78-
<Dialog.Root open={open} onOpenChange={handleOpenChange}>
76+
<Dialog.Root open={isOpen} onOpenChange={handleOpenChange}>
7977
<Dialog.Content
8078
maxWidth="800px"
8179
maxHeight="640px"

src/components/TextButton.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export function TextButton({
88
}) {
99
return (
1010
<button
11+
type="button"
1112
onClick={onClick}
1213
data-accent-color=""
1314
className="rt-Text rt-reset rt-Link rt-underline-auto"

src/hooks/useProxyStatus.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { useStudioUIStore } from '@/store/ui'
2+
import { useEffect } from 'react'
3+
4+
export function useProxyStatus() {
5+
const status = useStudioUIStore((state) => state.proxyStatus)
6+
const setProxyStatus = useStudioUIStore((state) => state.setProxyStatus)
7+
8+
useEffect(() => {
9+
;(async function fetchProxyStatus() {
10+
const status = await window.studio.proxy.getProxyStatus()
11+
setProxyStatus(status)
12+
})()
13+
14+
return window.studio.proxy.onProxyStatusChange((status) =>
15+
setProxyStatus(status)
16+
)
17+
}, [setProxyStatus])
18+
19+
return status
20+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,10 @@ export function useSaveSettings(onSuccess?: () => void) {
2424
},
2525
})
2626
}
27+
28+
export function useBrowserCheck() {
29+
return useQuery({
30+
queryKey: ['settings', 'browserCheck'],
31+
queryFn: window.studio.ui.detectBrowser,
32+
})
33+
}

0 commit comments

Comments
 (0)