Skip to content

Commit 4c2e081

Browse files
authored
feat(app): livestream image capture button (#20292)
# Overview Add non functional livestream image capture button hidden behind the camera settings feature flag ## Test Plan and Hands on Testing Smoke tested on ODD w/o feature flag on <img width="491" height="430" alt="Screenshot 2025-12-04 at 2 56 59 PM" src="https://github.com/user-attachments/assets/750a5315-4eee-4dbc-8a8d-698d8784683a" /> ## Review requests ## Risk assessment low Closes EXEC-2101
1 parent 7d902db commit 4c2e081

File tree

3 files changed

+39
-1
lines changed

3 files changed

+39
-1
lines changed

app/src/assets/localization/en/run_details.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"cancel_run_module_info": "Additionally, any hardware modules used within the protocol will remain active and maintain their current states until deactivated.",
2222
"canceling_run": "Canceling Run",
2323
"canceling_run_dot": "canceling run...",
24+
"capture_image": "Capture image",
2425
"clear_protocol": "Clear protocol",
2526
"clear_protocol_to_make_available": "Clear protocol from robot to make it available.",
2627
"close_door": "Close robot door",

app/src/pages/Desktop/LivestreamViewer/index.tsx

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
import { useState } from 'react'
22
import { useTranslation } from 'react-i18next'
33

4-
import { Chip } from '@opentrons/components'
4+
import {
5+
Btn,
6+
Chip,
7+
COLORS,
8+
Flex,
9+
Icon,
10+
StyledText,
11+
} from '@opentrons/components'
512

613
import { useHlsVideo } from '/app/pages/Desktop/LivestreamViewer/hooks/useHlsVideo'
714
import { useReportWindowDurationEvent } from '/app/pages/Desktop/LivestreamViewer/hooks/useReportWindowDurationEvent'
815
import {
916
LivestreamInfoScreen,
1017
useLivestreamInfoScreen,
1118
} from '/app/pages/Desktop/LivestreamViewer/LivestreamInfoScreen'
19+
import { useFeatureFlag } from '/app/redux/config'
1220
import { useCurrentRunId, useNotifyRunQuery } from '/app/resources/runs'
1321

1422
import styles from './livestream.module.css'
@@ -19,6 +27,8 @@ export function LivestreamViewer(): JSX.Element {
1927
// We make UI affordances when a run has ended, even if it is un-currented.
2028
// The livestream viewer makes the assumption that it will not *initially* render
2129
// for a run that is already historical.
30+
const { t } = useTranslation('run_details')
31+
2232
const [retainedRunId, setRetainedRunId] = useState<string | null>(null)
2333
const currentRunId = useCurrentRunId({
2434
refetchInterval: RUN_POLLING_INTERVAL_MS,
@@ -44,6 +54,7 @@ export function LivestreamViewer(): JSX.Element {
4454
isCurrentRunLoading,
4555
videoError
4656
)
57+
const liveStreamImageCaptureEnabled = useFeatureFlag('camera')
4758

4859
useReportWindowDurationEvent(
4960
retainedRunId,
@@ -72,6 +83,19 @@ export function LivestreamViewer(): JSX.Element {
7283
</div>
7384
)}
7485
</div>
86+
{infoScreenType == null && liveStreamImageCaptureEnabled && (
87+
<Btn
88+
className={styles.capture_image_button}
89+
backgroundColor={COLORS.blue50}
90+
>
91+
<Flex className={styles.capture_image_button_text}>
92+
<Icon name="camera" size="1rem" color={COLORS.white} />
93+
<StyledText color={COLORS.white} desktopStyle="bodyDefaultSemiBold">
94+
{t('capture_image')}
95+
</StyledText>
96+
</Flex>
97+
</Btn>
98+
)}
7599
</div>
76100
)
77101
}

app/src/pages/Desktop/LivestreamViewer/livestream.module.css

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,16 @@
3636
.video_inactive {
3737
display: none;
3838
}
39+
40+
.capture_image_button {
41+
width: 100%;
42+
height: 36px;
43+
border-radius: var(--border-radius-8);
44+
}
45+
46+
.capture_image_button_text {
47+
flex-direction: row;
48+
align-items: center;
49+
justify-content: center;
50+
gap: var(--spacing-8);
51+
}

0 commit comments

Comments
 (0)