Finder-launched terminals now inherit a login PATH so tools like ollama resolve, destructive SFTP/editor actions require confirmation, and terminal search plus window dragging work again. SSH forwards and RDP sessions keep listeners and survive reconnect without FastPath crashes. Co-authored-by: Cursor <cursoragent@cursor.com>
112 lines
3.5 KiB
TypeScript
112 lines
3.5 KiB
TypeScript
import { useState } from 'react'
|
|
import { useTranslation } from 'react-i18next'
|
|
import {
|
|
DESKTOP_RESOLUTION_PRESETS,
|
|
clampDesktopResolution,
|
|
formatResolution,
|
|
matchPresetId,
|
|
type DesktopResolution,
|
|
} from '../../utils/desktopResolution'
|
|
|
|
interface DesktopResolutionPickerProps {
|
|
width: number
|
|
height: number
|
|
onChange: (next: DesktopResolution) => void
|
|
ns?: 'desktop' | 'sessions'
|
|
resolutionLabelKey?: string
|
|
widthLabelKey?: string
|
|
heightLabelKey?: string
|
|
customKey?: string
|
|
}
|
|
|
|
export default function DesktopResolutionPicker({
|
|
width,
|
|
height,
|
|
onChange,
|
|
ns = 'desktop',
|
|
resolutionLabelKey = ns === 'desktop' ? 'connect.resolution' : 'dialog.resolution',
|
|
widthLabelKey = ns === 'desktop' ? 'connect.width' : 'dialog.width',
|
|
heightLabelKey = ns === 'desktop' ? 'connect.height' : 'dialog.height',
|
|
customKey = ns === 'desktop' ? 'connect.resolutionCustom' : 'dialog.resolutionCustom',
|
|
}: DesktopResolutionPickerProps) {
|
|
const { t } = useTranslation(ns)
|
|
const current = clampDesktopResolution(width, height)
|
|
const matched = matchPresetId(current)
|
|
const [forceCustom, setForceCustom] = useState(false)
|
|
const selected = forceCustom || matched === 'custom' ? 'custom' : matched
|
|
const showCustom = selected === 'custom'
|
|
|
|
return (
|
|
<div className="space-y-2 sm:col-span-3">
|
|
<div>
|
|
<label htmlFor={`${ns}-desktop-resolution`} className="ui-label">
|
|
{t(resolutionLabelKey)}
|
|
</label>
|
|
<select
|
|
id={`${ns}-desktop-resolution`}
|
|
className="ui-input font-mono"
|
|
value={selected}
|
|
onChange={(event) => {
|
|
const value = event.target.value
|
|
if (value === 'custom') {
|
|
setForceCustom(true)
|
|
onChange(current)
|
|
return
|
|
}
|
|
const preset = DESKTOP_RESOLUTION_PRESETS.find((item) => item.id === value)
|
|
if (!preset) return
|
|
setForceCustom(false)
|
|
onChange({ width: preset.width, height: preset.height })
|
|
}}
|
|
>
|
|
{DESKTOP_RESOLUTION_PRESETS.map((preset) => (
|
|
<option key={preset.id} value={preset.id}>
|
|
{formatResolution(preset)}
|
|
</option>
|
|
))}
|
|
<option value="custom">{t(customKey)}</option>
|
|
</select>
|
|
</div>
|
|
{showCustom && (
|
|
<div className="grid grid-cols-2 gap-3">
|
|
<div>
|
|
<label htmlFor={`${ns}-desktop-width`} className="ui-label">
|
|
{t(widthLabelKey)}
|
|
</label>
|
|
<input
|
|
id={`${ns}-desktop-width`}
|
|
type="number"
|
|
min={200}
|
|
max={8192}
|
|
step={2}
|
|
value={width}
|
|
onChange={(event) => {
|
|
setForceCustom(true)
|
|
onChange(clampDesktopResolution(Number(event.target.value) || current.width, height))
|
|
}}
|
|
className="ui-input font-mono"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label htmlFor={`${ns}-desktop-height`} className="ui-label">
|
|
{t(heightLabelKey)}
|
|
</label>
|
|
<input
|
|
id={`${ns}-desktop-height`}
|
|
type="number"
|
|
min={200}
|
|
max={8192}
|
|
value={height}
|
|
onChange={(event) => {
|
|
setForceCustom(true)
|
|
onChange(clampDesktopResolution(width, Number(event.target.value) || current.height))
|
|
}}
|
|
className="ui-input font-mono"
|
|
/>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|