diff --git a/desktop/src/__tests__/generalSettings.test.tsx b/desktop/src/__tests__/generalSettings.test.tsx index dc6e0018..3e36eafb 100644 --- a/desktop/src/__tests__/generalSettings.test.tsx +++ b/desktop/src/__tests__/generalSettings.test.tsx @@ -268,7 +268,7 @@ describe('Settings > General tab', () => { expect((uiZoomHeading.compareDocumentPosition(webFetchHeading) & Node.DOCUMENT_POSITION_FOLLOWING) !== 0).toBe(true) }) - it('previews UI zoom while dragging and applies it only when the user releases the slider', async () => { + it('applies UI zoom while dragging so the slider and app zoom stay synchronized', async () => { render() fireEvent.click(screen.getByText('General')) @@ -287,7 +287,9 @@ describe('Settings > General tab', () => { }) expect(screen.getAllByText('125%')).toHaveLength(2) - expect(useSettingsStore.getState().setUiZoom).not.toHaveBeenCalledWith(1.25) + expect(useSettingsStore.getState().setUiZoom).toHaveBeenCalledWith(1.25) + expect(useSettingsStore.getState().uiZoom).toBe(1.25) + expect(slider).toHaveValue('1.25') expect(slider).toHaveClass('settings-zoom-range') expect(slider.closest('.settings-zoom-control')).toHaveClass('is-dragging') expect(slider.closest('.settings-zoom-control')).toHaveStyle({ '--settings-zoom-range-progress': '50%' }) @@ -297,6 +299,7 @@ describe('Settings > General tab', () => { }) expect(useSettingsStore.getState().setUiZoom).toHaveBeenCalledWith(1.25) + expect(slider.closest('.settings-zoom-control')).not.toHaveClass('is-dragging') await act(async () => { fireEvent.click(screen.getByRole('button', { name: 'Reset UI zoom to 100%' })) @@ -305,6 +308,22 @@ describe('Settings > General tab', () => { expect(useSettingsStore.getState().setUiZoom).toHaveBeenLastCalledWith(1) }) + it('updates the UI zoom slider when shortcut zoom changes the shared setting while Settings is open', async () => { + render() + + fireEvent.click(screen.getByText('General')) + + const slider = screen.getByLabelText('UI Zoom') + + await act(async () => { + useSettingsStore.setState({ uiZoom: 1.1 }) + }) + + expect(slider).toHaveValue('1.1') + expect(screen.getAllByText('110%')).toHaveLength(2) + expect(slider.closest('.settings-zoom-control')).toHaveStyle({ '--settings-zoom-range-progress': '40%' }) + }) + it('opens the Token usage tab from Settings navigation above Diagnostics', () => { render() diff --git a/desktop/src/pages/Settings.tsx b/desktop/src/pages/Settings.tsx index fc34c1ae..01d07690 100644 --- a/desktop/src/pages/Settings.tsx +++ b/desktop/src/pages/Settings.tsx @@ -1396,7 +1396,7 @@ function GeneralSettings() { const [isUiZoomDragging, setIsUiZoomDragging] = useState(false) const webSearchDirty = JSON.stringify(webSearchDraft) !== JSON.stringify(webSearch) const uiZoomPercent = Math.round(uiZoomDraft * 100) - const uiZoomRangeProgress = `${((uiZoomDraft - UI_ZOOM_MIN) / (UI_ZOOM_MAX - UI_ZOOM_MIN)) * 100}%` + const uiZoomRangeProgress = `${Math.round(((uiZoomDraft - UI_ZOOM_MIN) / (UI_ZOOM_MAX - UI_ZOOM_MIN)) * 1000) / 10}%` useEffect(() => { setWebSearchDraft(webSearch) @@ -1523,9 +1523,11 @@ function GeneralSettings() { } } - const commitUiZoom = (value: number) => { + const commitUiZoom = (value: number, options: { keepDragging?: boolean } = {}) => { const nextZoom = Number.isFinite(value) ? value : UI_ZOOM_DEFAULT - setIsUiZoomDragging(false) + if (!options.keepDragging) { + setIsUiZoomDragging(false) + } setUiZoomDraft(nextZoom) setUiZoom(nextZoom) } @@ -1599,21 +1601,17 @@ function GeneralSettings() { max={UI_ZOOM_MAX} step={UI_ZOOM_STEP} value={uiZoomDraft} - onPointerDown={(e) => { + onPointerDown={() => { setIsUiZoomDragging(true) - e.currentTarget.setPointerCapture?.(e.pointerId) - }} - onPointerUp={(e) => commitUiZoom(e.currentTarget.valueAsNumber)} - onPointerCancel={(e) => commitUiZoom(e.currentTarget.valueAsNumber)} - onChange={(e) => setUiZoomDraft(e.currentTarget.valueAsNumber)} - onKeyUp={(e) => { - if (['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End', 'PageUp', 'PageDown'].includes(e.key)) { - commitUiZoom(e.currentTarget.valueAsNumber) - } }} + 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) } }} className="settings-zoom-range w-full" diff --git a/desktop/src/theme/globals.css b/desktop/src/theme/globals.css index 5e394bbe..88e7a40d 100644 --- a/desktop/src/theme/globals.css +++ b/desktop/src/theme/globals.css @@ -199,6 +199,7 @@ cursor: pointer; background: transparent; accent-color: var(--color-brand); + touch-action: none; } .settings-zoom-range:focus {