@@ -12,6 +12,7 @@ import {
1212 ModalContent ,
1313 ModalFooter ,
1414 ModalHeader ,
15+ Slider ,
1516 Switch ,
1617} from '@/components/emcn'
1718import { Input , Skeleton } from '@/components/ui'
@@ -76,12 +77,18 @@ export function General({ onOpenChange }: GeneralProps) {
7677
7778 const [ uploadError , setUploadError ] = useState < string | null > ( null )
7879
80+ const [ snapToGridValue , setSnapToGridValue ] = useState ( settings ?. snapToGridSize ?? 0 )
81+
7982 useEffect ( ( ) => {
8083 if ( profile ?. name ) {
8184 setName ( profile . name )
8285 }
8386 } , [ profile ?. name ] )
8487
88+ useEffect ( ( ) => {
89+ setSnapToGridValue ( settings ?. snapToGridSize ?? 0 )
90+ } , [ settings ?. snapToGridSize ] )
91+
8592 useEffect ( ( ) => {
8693 const fetchSuperUserStatus = async ( ) => {
8794 try {
@@ -234,6 +241,17 @@ export function General({ onOpenChange }: GeneralProps) {
234241 }
235242 }
236243
244+ const handleSnapToGridChange = ( value : number [ ] ) => {
245+ setSnapToGridValue ( value [ 0 ] )
246+ }
247+
248+ const handleSnapToGridCommit = async ( value : number [ ] ) => {
249+ const newValue = value [ 0 ]
250+ if ( newValue !== settings ?. snapToGridSize && ! updateSetting . isPending ) {
251+ await updateSetting . mutateAsync ( { key : 'snapToGridSize' , value : newValue } )
252+ }
253+ }
254+
237255 const handleTrainingControlsChange = async ( checked : boolean ) => {
238256 if ( checked !== settings ?. showTrainingControls && ! updateSetting . isPending ) {
239257 await updateSetting . mutateAsync ( { key : 'showTrainingControls' , value : checked } )
@@ -410,17 +428,34 @@ export function General({ onOpenChange }: GeneralProps) {
410428 id = 'auto-connect'
411429 checked = { settings ?. autoConnect ?? true }
412430 onCheckedChange = { handleAutoConnectChange }
413- disabled = { updateSetting . isPending }
414431 />
415432 </ div >
416433
434+ < div className = 'flex items-center justify-between' >
435+ < Label htmlFor = 'snap-to-grid' > Snap to grid</ Label >
436+ < div className = 'flex items-center gap-[12px]' >
437+ < span className = 'w-[32px] text-right text-[12px] text-[var(--text-tertiary)]' >
438+ { snapToGridValue === 0 ? 'Off' : `${ snapToGridValue } px` }
439+ </ span >
440+ < Slider
441+ id = 'snap-to-grid'
442+ value = { [ snapToGridValue ] }
443+ onValueChange = { handleSnapToGridChange }
444+ onValueCommit = { handleSnapToGridCommit }
445+ min = { 0 }
446+ max = { 50 }
447+ step = { 1 }
448+ className = 'w-[100px]'
449+ />
450+ </ div >
451+ </ div >
452+
417453 < div className = 'flex items-center justify-between' >
418454 < Label htmlFor = 'error-notifications' > Run error notifications</ Label >
419455 < Switch
420456 id = 'error-notifications'
421457 checked = { settings ?. errorNotificationsEnabled ?? true }
422458 onCheckedChange = { handleErrorNotificationsChange }
423- disabled = { updateSetting . isPending }
424459 />
425460 </ div >
426461
@@ -430,7 +465,6 @@ export function General({ onOpenChange }: GeneralProps) {
430465 id = 'telemetry'
431466 checked = { settings ?. telemetryEnabled ?? true }
432467 onCheckedChange = { handleTelemetryToggle }
433- disabled = { updateSetting . isPending }
434468 />
435469 </ div >
436470
@@ -446,7 +480,6 @@ export function General({ onOpenChange }: GeneralProps) {
446480 id = 'training-controls'
447481 checked = { settings ?. showTrainingControls ?? false }
448482 onCheckedChange = { handleTrainingControlsChange }
449- disabled = { updateSetting . isPending }
450483 />
451484 </ div >
452485 ) }
@@ -458,7 +491,6 @@ export function General({ onOpenChange }: GeneralProps) {
458491 id = 'super-user-mode'
459492 checked = { settings ?. superUserModeEnabled ?? true }
460493 onCheckedChange = { handleSuperUserModeToggle }
461- disabled = { updateSetting . isPending }
462494 />
463495 </ div >
464496 ) }
@@ -534,6 +566,15 @@ function GeneralSkeleton() {
534566 < Skeleton className = 'h-[17px] w-[30px] rounded-full' />
535567 </ div >
536568
569+ { /* Snap to grid row */ }
570+ < div className = 'flex items-center justify-between' >
571+ < Skeleton className = 'h-4 w-24' />
572+ < div className = 'flex items-center gap-[12px]' >
573+ < Skeleton className = 'h-3 w-[32px]' />
574+ < Skeleton className = 'h-[6px] w-[100px] rounded-[20px]' />
575+ </ div >
576+ </ div >
577+
537578 { /* Error notifications row */ }
538579 < div className = 'flex items-center justify-between' >
539580 < Skeleton className = 'h-4 w-40' />
0 commit comments