♻️(frontend) extract recording row layout in reusable component
Now that screen recording and transcription share the same UI presentation, extract the row logic into a reusable component to avoid code duplication and improve code maintainability.
This commit is contained in:
committed by
aleb_the_flash
parent
398ef1ae8a
commit
57a7523cc4
@@ -0,0 +1,60 @@
|
||||
import { css } from '@/styled-system/css'
|
||||
import { ReactNode } from 'react'
|
||||
|
||||
type RowPosition = 'first' | 'middle' | 'last' | 'single'
|
||||
|
||||
const BORDER_RADIUS_MAP: Record<RowPosition, string> = {
|
||||
first: '4px 4px 0 0',
|
||||
middle: '0',
|
||||
last: '0 0 4px 4px',
|
||||
single: '4px',
|
||||
} as const
|
||||
|
||||
interface RowWrapperProps {
|
||||
iconName: string
|
||||
children: ReactNode
|
||||
position?: RowPosition
|
||||
}
|
||||
|
||||
export const RowWrapper = ({
|
||||
iconName,
|
||||
children,
|
||||
position = 'middle',
|
||||
}: RowWrapperProps) => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
borderRadius: BORDER_RADIUS_MAP[position],
|
||||
}}
|
||||
className={css({
|
||||
width: '100%',
|
||||
background: 'gray.100',
|
||||
padding: '8px',
|
||||
display: 'flex',
|
||||
marginTop: '4px',
|
||||
})}
|
||||
>
|
||||
<div
|
||||
className={css({
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
})}
|
||||
>
|
||||
{/* fixme - doesn't handle properly material-symbols */}
|
||||
<span className="material-icons">{iconName}</span>
|
||||
</div>
|
||||
<div
|
||||
className={css({
|
||||
flex: 5,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '0.25rem',
|
||||
})}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import { useConfig } from '@/api/useConfig'
|
||||
import { FeatureFlags } from '@/features/analytics/enums'
|
||||
import { NoAccessView } from './NoAccessView'
|
||||
import { HStack, VStack } from '@/styled-system/jsx'
|
||||
import { RowWrapper } from './RowWrapper'
|
||||
import { Checkbox } from '@/primitives/Checkbox'
|
||||
import { useTranscriptionLanguage } from '@/features/settings'
|
||||
|
||||
@@ -188,63 +189,12 @@ export const ScreenRecordingSidePanel = () => {
|
||||
</Text>
|
||||
</VStack>
|
||||
<VStack gap={0} marginBottom={40}>
|
||||
<div
|
||||
className={css({
|
||||
width: '100%',
|
||||
background: 'gray.100',
|
||||
borderRadius: '4px 4px 0 0',
|
||||
paddingLeft: '4px',
|
||||
padding: '8px',
|
||||
display: 'flex',
|
||||
})}
|
||||
>
|
||||
<div
|
||||
className={css({
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
})}
|
||||
>
|
||||
<span className="material-icons">cloud_download</span>
|
||||
</div>
|
||||
<div
|
||||
className={css({
|
||||
flex: 5,
|
||||
})}
|
||||
>
|
||||
<Text variant="sm">{t('details.destination')}</Text>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={css({
|
||||
width: '100%',
|
||||
background: 'gray.100',
|
||||
borderRadius: '0 0 4px 4px',
|
||||
paddingLeft: '4px',
|
||||
padding: '8px',
|
||||
display: 'flex',
|
||||
marginTop: '4px',
|
||||
})}
|
||||
>
|
||||
<div
|
||||
className={css({
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
})}
|
||||
>
|
||||
<span className="material-icons">mail</span>
|
||||
</div>
|
||||
<div
|
||||
className={css({
|
||||
flex: 5,
|
||||
})}
|
||||
>
|
||||
<Text variant="sm">{t('details.receiver')}</Text>
|
||||
</div>
|
||||
</div>
|
||||
<RowWrapper iconName="cloud_download" position="first">
|
||||
<Text variant="sm">{t('details.destination')}</Text>
|
||||
</RowWrapper>
|
||||
<RowWrapper iconName="mail" position="last">
|
||||
<Text variant="sm">{t('details.receiver')}</Text>
|
||||
</RowWrapper>
|
||||
|
||||
<div className={css({ height: '15px' })} />
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import posthog from 'posthog-js'
|
||||
import { useSnapshot } from 'valtio/index'
|
||||
import { Spinner } from '@/primitives/Spinner'
|
||||
import { useConfig } from '@/api/useConfig'
|
||||
import { HStack, VStack } from '@/styled-system/jsx'
|
||||
import { VStack } from '@/styled-system/jsx'
|
||||
import { Checkbox } from '@/primitives/Checkbox.tsx'
|
||||
|
||||
import {
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
useTranscriptionLanguage,
|
||||
} from '@/features/settings'
|
||||
import { NoAccessView } from './NoAccessView'
|
||||
import { RowWrapper } from './RowWrapper'
|
||||
|
||||
export const TranscriptSidePanel = () => {
|
||||
const { data } = useConfig()
|
||||
@@ -214,123 +215,41 @@ export const TranscriptSidePanel = () => {
|
||||
</Text>
|
||||
</VStack>
|
||||
<VStack gap={0} marginBottom={40}>
|
||||
<div
|
||||
className={css({
|
||||
width: '100%',
|
||||
// border: '1px solid black',
|
||||
background: 'gray.100',
|
||||
borderRadius: '4px 4px 0 0',
|
||||
paddingLeft: '4px',
|
||||
padding: '8px',
|
||||
display: 'flex',
|
||||
})}
|
||||
>
|
||||
<div
|
||||
className={css({
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
})}
|
||||
>
|
||||
<span className="material-icons">article</span>
|
||||
</div>
|
||||
<div
|
||||
className={css({
|
||||
flex: 5,
|
||||
})}
|
||||
>
|
||||
<Text variant="sm">
|
||||
{data?.transcription_destination ? (
|
||||
<>
|
||||
{t('details.destination')}{' '}
|
||||
<A
|
||||
href={data.transcription_destination}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{data.transcription_destination.replace('https://', '')}
|
||||
</A>
|
||||
</>
|
||||
) : (
|
||||
t('details.destinationUnknown')
|
||||
)}
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={css({
|
||||
width: '100%',
|
||||
// border: '1px solid black',
|
||||
background: 'gray.100',
|
||||
paddingLeft: '4px',
|
||||
padding: '8px',
|
||||
display: 'flex',
|
||||
marginTop: '4px',
|
||||
})}
|
||||
>
|
||||
<div
|
||||
className={css({
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
})}
|
||||
>
|
||||
<span className="material-icons">mail</span>
|
||||
</div>
|
||||
<div
|
||||
className={css({
|
||||
flex: 5,
|
||||
})}
|
||||
>
|
||||
<Text variant="sm">{t('details.receiver')}</Text>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={css({
|
||||
width: '100%',
|
||||
background: 'gray.100',
|
||||
borderRadius: '0 0 4px 4px',
|
||||
paddingLeft: '4px',
|
||||
padding: '8px',
|
||||
display: 'flex',
|
||||
marginTop: '4px',
|
||||
})}
|
||||
>
|
||||
<div
|
||||
className={css({
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
})}
|
||||
>
|
||||
<span className="material-icons">language</span>
|
||||
</div>
|
||||
<div
|
||||
className={css({
|
||||
flex: 5,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '0.25rem',
|
||||
})}
|
||||
>
|
||||
<Text variant="sm">{t('details.language')}</Text>
|
||||
<Text variant="sm">
|
||||
<Button
|
||||
variant="text"
|
||||
size="xs"
|
||||
onPress={() =>
|
||||
openSettingsDialog(SettingsDialogExtendedKey.TRANSCRIPTION)
|
||||
}
|
||||
>
|
||||
{selectedLanguageLabel}
|
||||
</Button>
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<RowWrapper iconName="article" position="first">
|
||||
<Text variant="sm">
|
||||
{data?.transcription_destination ? (
|
||||
<>
|
||||
{t('details.destination')}{' '}
|
||||
<A
|
||||
href={data.transcription_destination}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{data.transcription_destination.replace('https://', '')}
|
||||
</A>
|
||||
</>
|
||||
) : (
|
||||
t('details.destinationUnknown')
|
||||
)}
|
||||
</Text>
|
||||
</RowWrapper>
|
||||
<RowWrapper iconName="mail">
|
||||
<Text variant="sm">{t('details.receiver')}</Text>
|
||||
</RowWrapper>
|
||||
<RowWrapper iconName="language" position="last">
|
||||
<Text variant="sm">{t('details.language')}</Text>
|
||||
<Text variant="sm">
|
||||
<Button
|
||||
variant="text"
|
||||
size="xs"
|
||||
onPress={() =>
|
||||
openSettingsDialog(SettingsDialogExtendedKey.TRANSCRIPTION)
|
||||
}
|
||||
>
|
||||
{selectedLanguageLabel}
|
||||
</Button>
|
||||
</Text>
|
||||
</RowWrapper>
|
||||
<div className={css({ height: '15px' })} />
|
||||
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user