mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-16 13:03:31 +08:00
Merge zoom slider drag stability fix into local main
The Settings zoom slider follow-up stops app-wide zoom from being applied continuously while the pointer is dragging, then commits the chosen value on release. This keeps the local main checkout aligned with the verified worktree fix. Constraint: The slider was resizing the UI under the pointer when live zoom applied on every drag event Confidence: high Scope-risk: narrow Directive: Keep pointer-drag zoom as local preview plus release commit; keyboard zoom remains live through the shared app zoom state Tested: bun run check:desktop Tested: agent-browser Settings smoke confirms drag preview keeps cssZoom at 1 until release, then commits 1.23
This commit is contained in:
commit
571f16135f
@ -268,7 +268,7 @@ describe('Settings > General tab', () => {
|
||||
expect((uiZoomHeading.compareDocumentPosition(webFetchHeading) & Node.DOCUMENT_POSITION_FOLLOWING) !== 0).toBe(true)
|
||||
})
|
||||
|
||||
it('applies UI zoom while dragging so the slider and app zoom stay synchronized', async () => {
|
||||
it('previews UI zoom while dragging and applies it once on release', async () => {
|
||||
render(<Settings />)
|
||||
|
||||
fireEvent.click(screen.getByText('General'))
|
||||
@ -278,6 +278,7 @@ describe('Settings > General tab', () => {
|
||||
expect(screen.getByText('0 resets zoom to 100%.')).toBeInTheDocument()
|
||||
|
||||
const slider = screen.getByLabelText('UI Zoom')
|
||||
expect(slider).toHaveAttribute('step', '0.01')
|
||||
|
||||
fireEvent.pointerDown(slider, { pointerId: 1 })
|
||||
await act(async () => {
|
||||
@ -287,8 +288,8 @@ describe('Settings > General tab', () => {
|
||||
})
|
||||
|
||||
expect(screen.getAllByText('125%')).toHaveLength(2)
|
||||
expect(useSettingsStore.getState().setUiZoom).toHaveBeenCalledWith(1.25)
|
||||
expect(useSettingsStore.getState().uiZoom).toBe(1.25)
|
||||
expect(useSettingsStore.getState().setUiZoom).not.toHaveBeenCalledWith(1.25)
|
||||
expect(useSettingsStore.getState().uiZoom).toBe(1)
|
||||
expect(slider).toHaveValue('1.25')
|
||||
expect(slider).toHaveClass('settings-zoom-range')
|
||||
expect(slider.closest('.settings-zoom-control')).toHaveClass('is-dragging')
|
||||
|
||||
@ -4,7 +4,7 @@ export const DEFAULT_APP_ZOOM = 1
|
||||
export const MIN_APP_ZOOM = 0.5
|
||||
export const MAX_APP_ZOOM = 2
|
||||
export const APP_ZOOM_STEP = 0.1
|
||||
export const APP_ZOOM_CONTROL_STEP = 0.05
|
||||
export const APP_ZOOM_CONTROL_STEP = 0.01
|
||||
|
||||
export type AppZoomAction = 'in' | 'out' | 'reset'
|
||||
|
||||
|
||||
@ -1394,6 +1394,7 @@ function GeneralSettings() {
|
||||
const [notificationActionRunning, setNotificationActionRunning] = useState(false)
|
||||
const [uiZoomDraft, setUiZoomDraft] = useState(uiZoom)
|
||||
const [isUiZoomDragging, setIsUiZoomDragging] = useState(false)
|
||||
const isUiZoomDraggingRef = useRef(false)
|
||||
const webSearchDirty = JSON.stringify(webSearchDraft) !== JSON.stringify(webSearch)
|
||||
const uiZoomPercent = Math.round(uiZoomDraft * 100)
|
||||
const uiZoomRangeProgress = `${Math.round(((uiZoomDraft - UI_ZOOM_MIN) / (UI_ZOOM_MAX - UI_ZOOM_MIN)) * 1000) / 10}%`
|
||||
@ -1523,11 +1524,14 @@ function GeneralSettings() {
|
||||
}
|
||||
}
|
||||
|
||||
const commitUiZoom = (value: number, options: { keepDragging?: boolean } = {}) => {
|
||||
const setUiZoomDraggingState = (dragging: boolean) => {
|
||||
isUiZoomDraggingRef.current = dragging
|
||||
setIsUiZoomDragging(dragging)
|
||||
}
|
||||
|
||||
const commitUiZoom = (value: number) => {
|
||||
const nextZoom = Number.isFinite(value) ? value : UI_ZOOM_DEFAULT
|
||||
if (!options.keepDragging) {
|
||||
setIsUiZoomDragging(false)
|
||||
}
|
||||
setUiZoomDraggingState(false)
|
||||
setUiZoomDraft(nextZoom)
|
||||
setUiZoom(nextZoom)
|
||||
}
|
||||
@ -1602,16 +1606,27 @@ function GeneralSettings() {
|
||||
step={UI_ZOOM_STEP}
|
||||
value={uiZoomDraft}
|
||||
onPointerDown={() => {
|
||||
setIsUiZoomDragging(true)
|
||||
setUiZoomDraggingState(true)
|
||||
}}
|
||||
onPointerUp={(e) => commitUiZoom(e.currentTarget.valueAsNumber)}
|
||||
onPointerCancel={() => {
|
||||
setUiZoomDraggingState(false)
|
||||
setUiZoomDraft(uiZoom)
|
||||
}}
|
||||
onChange={(e) => {
|
||||
const nextZoom = Number.isFinite(e.currentTarget.valueAsNumber)
|
||||
? e.currentTarget.valueAsNumber
|
||||
: UI_ZOOM_DEFAULT
|
||||
setUiZoomDraft(nextZoom)
|
||||
if (!isUiZoomDraggingRef.current) {
|
||||
setUiZoom(nextZoom)
|
||||
}
|
||||
}}
|
||||
onPointerUp={() => setIsUiZoomDragging(false)}
|
||||
onPointerCancel={() => setIsUiZoomDragging(false)}
|
||||
onChange={(e) => commitUiZoom(e.currentTarget.valueAsNumber, { keepDragging: isUiZoomDragging })}
|
||||
onBlur={(e) => {
|
||||
if (uiZoomDraft !== uiZoom) {
|
||||
commitUiZoom(e.currentTarget.valueAsNumber)
|
||||
} else {
|
||||
setIsUiZoomDragging(false)
|
||||
setUiZoomDraggingState(false)
|
||||
}
|
||||
}}
|
||||
className="settings-zoom-range w-full"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user