11import { createFileRoute } from "@tanstack/react-router"
22import QRCode from "qrcode"
3- import { useEffect , useState } from "react"
3+ import { useEffect , useState , useRef , useMemo } from "react"
44import { APP_CONFIG , THEMES } from "../config"
55import serverConfig from "../server-config.json"
6-
6+ import { useRemoteConnection } from "../hooks/useRemoteConnection"
77export const Route = createFileRoute ( "/settings" ) ( {
88 component : SettingsPage ,
99} )
@@ -14,26 +14,26 @@ function SettingsPage() {
1414 String ( serverConfig . frontendPort ) ,
1515 )
1616 const [ originalPort ] = useState ( String ( serverConfig . frontendPort ) )
17-
1817 const serverConfigChanged = frontendPort !== originalPort
19-
18+ const sendConfigUpdate = useRemoteConnection ( ) . sendConfigUpdate
2019 // Client Side Settings (LocalStorage)
21- const [ invertScroll , setInvertScroll ] = useState ( ( ) => {
22- if ( typeof window === "undefined" ) return false
20+ const [ initialSensitivity , initialInvert ] = ( ( ) => {
2321 try {
24- const saved = localStorage . getItem ( "rein_invert" )
25- return saved === "true"
22+ const savedSensitivity = localStorage . getItem ( "rein_sensitivity" )
23+ const parsed = savedSensitivity
24+ ? Number . parseFloat ( savedSensitivity )
25+ : Number . NaN
26+ return [
27+ Number . isFinite ( parsed ) ? parsed : 1.0 ,
28+ localStorage . getItem ( "rein_invert" ) === "true" ,
29+ ] as const
2630 } catch {
27- return false
31+ return [ 1.0 , false ] as const
2832 }
29- } )
33+ } ) ( )
3034
31- const [ sensitivity , setSensitivity ] = useState ( ( ) => {
32- if ( typeof window === "undefined" ) return 1.0
33- const saved = localStorage . getItem ( "rein_sensitivity" )
34- const parsed = saved ? Number . parseFloat ( saved ) : Number . NaN
35- return Number . isFinite ( parsed ) ? parsed : 1.0
36- } )
35+ const sensitivity = useRef ( initialSensitivity )
36+ const invertScroll = useRef ( initialInvert )
3737
3838 const [ theme , setTheme ] = useState ( ( ) => {
3939 if ( typeof window === "undefined" ) return THEMES . DEFAULT
@@ -48,6 +48,16 @@ function SettingsPage() {
4848 } )
4949
5050 const [ qrData , setQrData ] = useState ( "" )
51+ const setConfig = ( sensitivity_val : number , invertedScroll_val : boolean ) => {
52+ sensitivity . current = sensitivity_val
53+ invertScroll . current = invertedScroll_val
54+ localStorage . setItem ( "rein_sensitivity" , String ( sensitivity_val ) )
55+ localStorage . setItem ( "rein_invert" , JSON . stringify ( invertedScroll_val ) )
56+ const timer = setTimeout ( ( ) => {
57+ sendConfigUpdate ( sensitivity . current , invertScroll . current )
58+ } , 300 )
59+ return ( ) => clearTimeout ( timer )
60+ }
5161
5262 // Load initial state (IP is not stored in localStorage; only sensitivity, invert, theme are client settings)
5363 const [ authToken , setAuthToken ] = useState ( ( ) => {
@@ -112,15 +122,6 @@ function SettingsPage() {
112122 }
113123 } , [ ] )
114124
115- // Effect: Update LocalStorage when settings change
116- useEffect ( ( ) => {
117- localStorage . setItem ( "rein_sensitivity" , String ( sensitivity ) )
118- } , [ sensitivity ] )
119-
120- useEffect ( ( ) => {
121- localStorage . setItem ( "rein_invert" , JSON . stringify ( invertScroll ) )
122- } , [ invertScroll ] )
123-
124125 // Effect: Theme
125126 useEffect ( ( ) => {
126127 if ( typeof window === "undefined" ) return
@@ -137,20 +138,6 @@ function SettingsPage() {
137138 . catch ( ( e ) => console . error ( "QR Error:" , e ) )
138139 } , [ ip , shareUrl ] )
139140
140- const [ acceleration , setAcceleration ] = useState ( ( ) => {
141- if ( typeof window === "undefined" ) return true
142- try {
143- const saved = localStorage . getItem ( "rein_acceleration" )
144- return saved === "true"
145- } catch {
146- return true
147- }
148- } )
149-
150- useEffect ( ( ) => {
151- localStorage . setItem ( "rein_acceleration" , JSON . stringify ( acceleration ) )
152- } , [ acceleration ] )
153-
154141 // Effect: Auto-detect LAN IP from Server (only if on localhost)
155142 useEffect ( ( ) => {
156143 if ( typeof window === "undefined" ) return
@@ -195,19 +182,22 @@ function SettingsPage() {
195182 < label className = "label mb-3" htmlFor = "sensitivity-slider" >
196183 < span className = "label-text" > Mouse Sensitivity</ span >
197184 < span className = "label-text-alt font-mono" >
198- { sensitivity . toFixed ( 1 ) } x
185+ { sensitivity . current . toFixed ( 1 ) } x
199186 </ span >
200187 </ label >
201188
202189 < input
203190 type = "range"
204191 id = "sensitivity-slider"
205192 min = "0.1"
206- max = "3 .0"
193+ max = "6 .0"
207194 step = "0.1"
208- value = { sensitivity }
195+ defaultValue = { sensitivity . current }
209196 onChange = { ( e ) =>
210- setSensitivity ( Number . parseFloat ( e . target . value ) )
197+ setConfig (
198+ parseFloat ( e . target . value ) || 1.0 ,
199+ invertScroll . current ,
200+ )
211201 }
212202 className = "range range-primary range-sm w-full"
213203 />
@@ -229,8 +219,10 @@ function SettingsPage() {
229219 id = "invert-scroll-toggle"
230220 type = "checkbox"
231221 className = "toggle toggle-primary"
232- checked = { invertScroll }
233- onChange = { ( e ) => setInvertScroll ( e . target . checked ) }
222+ defaultChecked = { invertScroll . current }
223+ onChange = { ( e ) =>
224+ setConfig ( sensitivity . current , e . target . checked )
225+ }
234226 />
235227 </ label >
236228
0 commit comments