feat(desktop): add pinch zoom setting (#28632)
This commit is contained in:
parent
2697cb8001
commit
2caac055ef
11 changed files with 244 additions and 35 deletions
|
|
@ -21,7 +21,7 @@ import { createEffect, createResource, onCleanup, onMount, Show } from "solid-js
|
|||
import { render } from "solid-js/web"
|
||||
import pkg from "../../package.json"
|
||||
import { initI18n, t } from "./i18n"
|
||||
import { resetZoom, webviewZoom, zoomIn, zoomOut } from "./webview-zoom"
|
||||
import { resetZoom, setPinchZoomEnabled, webviewZoom, zoomIn, zoomOut } from "./webview-zoom"
|
||||
import "./styles.css"
|
||||
import { useTheme } from "@opencode-ai/ui/theme"
|
||||
|
||||
|
|
@ -274,6 +274,10 @@ const createPlatform = (): Platform => {
|
|||
|
||||
webviewZoom,
|
||||
|
||||
getPinchZoomEnabled: () => window.api.getPinchZoomEnabled(),
|
||||
|
||||
setPinchZoomEnabled,
|
||||
|
||||
runDesktopMenuAction,
|
||||
|
||||
checkAppExists: async (appName: string) => {
|
||||
|
|
|
|||
|
|
@ -13,9 +13,21 @@ const OS_NAME = (() => {
|
|||
|
||||
const [webviewZoom, setWebviewZoom] = createSignal(1)
|
||||
let requestedZoom = 1
|
||||
let pinchZoomEnabled = false
|
||||
let wheelPinch = undefined as
|
||||
| {
|
||||
active: boolean
|
||||
startZoom: number
|
||||
totalDelta: number
|
||||
timeout: ReturnType<typeof setTimeout> | undefined
|
||||
}
|
||||
| undefined
|
||||
|
||||
const MAX_ZOOM_LEVEL = 10
|
||||
const MIN_ZOOM_LEVEL = 0.2
|
||||
const WHEEL_PINCH_THRESHOLD = 20
|
||||
const WHEEL_PINCH_STEP = 0.2
|
||||
const WHEEL_PINCH_END_DELAY = 160
|
||||
|
||||
const clamp = (value: number) => Math.min(Math.max(value, MIN_ZOOM_LEVEL), MAX_ZOOM_LEVEL)
|
||||
|
||||
|
|
@ -33,10 +45,77 @@ const applyZoom = (next: number) => {
|
|||
})
|
||||
}
|
||||
|
||||
window.api.onZoomFactorChanged((factor) => {
|
||||
requestedZoom = clamp(factor)
|
||||
setWebviewZoom(requestedZoom)
|
||||
})
|
||||
|
||||
void window.api.getPinchZoomEnabled().then((enabled) => {
|
||||
pinchZoomEnabled = enabled
|
||||
})
|
||||
|
||||
window.api.onPinchZoomEnabledChanged((enabled) => {
|
||||
pinchZoomEnabled = enabled
|
||||
resetWheelPinch()
|
||||
})
|
||||
|
||||
const setPinchZoomEnabled = (enabled: boolean) => {
|
||||
pinchZoomEnabled = enabled
|
||||
resetWheelPinch()
|
||||
return window.api.setPinchZoomEnabled(enabled)
|
||||
}
|
||||
|
||||
const resetZoom = () => applyZoom(1)
|
||||
const zoomIn = () => applyZoom(clamp(requestedZoom + 0.2))
|
||||
const zoomOut = () => applyZoom(clamp(requestedZoom - 0.2))
|
||||
|
||||
const resetWheelPinch = () => {
|
||||
clearTimeout(wheelPinch?.timeout)
|
||||
wheelPinch = undefined
|
||||
}
|
||||
|
||||
const normalizeWheelDelta = (event: WheelEvent) => {
|
||||
if (event.deltaMode === WheelEvent.DOM_DELTA_LINE) return event.deltaY * 16
|
||||
if (event.deltaMode === WheelEvent.DOM_DELTA_PAGE) return event.deltaY * window.innerHeight
|
||||
return event.deltaY
|
||||
}
|
||||
|
||||
const updateWheelPinch = (event: WheelEvent) => {
|
||||
wheelPinch ??= {
|
||||
active: false,
|
||||
startZoom: requestedZoom,
|
||||
totalDelta: 0,
|
||||
timeout: undefined,
|
||||
}
|
||||
|
||||
clearTimeout(wheelPinch.timeout)
|
||||
wheelPinch.timeout = setTimeout(resetWheelPinch, WHEEL_PINCH_END_DELAY)
|
||||
wheelPinch.totalDelta += normalizeWheelDelta(event)
|
||||
|
||||
if (!wheelPinch.active && Math.abs(wheelPinch.totalDelta) < WHEEL_PINCH_THRESHOLD) return
|
||||
if (!wheelPinch.active) {
|
||||
wheelPinch.active = true
|
||||
wheelPinch.startZoom = requestedZoom
|
||||
wheelPinch.totalDelta = 0
|
||||
return
|
||||
}
|
||||
|
||||
wheelPinch.active = true
|
||||
applyZoom(clamp(wheelPinch.startZoom - (wheelPinch.totalDelta / WHEEL_PINCH_THRESHOLD) * WHEEL_PINCH_STEP))
|
||||
}
|
||||
|
||||
window.addEventListener(
|
||||
"wheel",
|
||||
(event) => {
|
||||
if (!pinchZoomEnabled) return
|
||||
if (!event.ctrlKey) return
|
||||
|
||||
event.preventDefault()
|
||||
updateWheelPinch(event)
|
||||
},
|
||||
{ passive: false },
|
||||
)
|
||||
|
||||
window.addEventListener("keydown", (event) => {
|
||||
if (!(OS_NAME === "macos" ? event.metaKey : event.ctrlKey)) return
|
||||
|
||||
|
|
@ -56,4 +135,4 @@ window.addEventListener("keydown", (event) => {
|
|||
}
|
||||
})
|
||||
|
||||
export { webviewZoom, resetZoom, zoomIn, zoomOut }
|
||||
export { webviewZoom, resetZoom, setPinchZoomEnabled, zoomIn, zoomOut }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue