Skip to content

Socket cleanup#181

Merged
imxade merged 9 commits into
AOSSIE-Org:mainfrom
imxade:socket_cleanup
Feb 26, 2026
Merged

Socket cleanup#181
imxade merged 9 commits into
AOSSIE-Org:mainfrom
imxade:socket_cleanup

Conversation

@imxade
Copy link
Copy Markdown
Contributor

@imxade imxade commented Feb 26, 2026

Declaration: Changes are made by claude as per my instructions

Functional Verification

  • Please check off the behaviors verified with this change.

Basic Gestures

  • One-finger tap: Verified as Left Click.

  • Two-finger tap: Verified as Right Click.

  • Click and drag: Verified selection behavior.

  • Pinch to zoom: Verified zoom functionality (if applicable).

Modes & Settings

  • Cursor mode: Cursor moves smoothly and accurately.

  • Scroll mode: Page scrolls as expected.

  • Sensitivity: Verified changes in cursor speed/sensitivity settings.

  • Invert Scrolling: Verified scroll direction toggles correctly.

Advanced Input

  • Key combinations: Verified "hold" behavior for modifiers (e.g., Ctrl+C) and held keys are shown in buffer.

  • Keyboard input: Verified Space, Backspace, and Enter keys work correctly.

  • Glide typing: Verified path drawing and text output.

  • Voice input: Verified speech-to-text functionality.

  • Backspace doesn't send the previous input.

Any other gesture or input behavior introduced:

  • New Gestures: Verified any other gesture or input behavior introduced in this PR.

Additional Notes:

Checklist

  • My PR addresses a single issue, fixes a single bug or makes a single improvement.

  • My code follows the project's code style and conventions

  • I have performed a self-review of my own code

  • I have commented my code, particularly in hard-to-understand areas

  • If applicable, I have made corresponding changes or additions to the documentation

  • If applicable, I have made corresponding changes or additions to tests

  • My changes generate no new warnings or errors

  • I have joined the and I will share a link to this PR with the project maintainers there

  • I have read the

  • Once I submit my PR, CodeRabbit AI will automatically review it and I will address CodeRabbit's comments.

  • Incase of UI change I've added a demo video.

⚠️ AI Notice - Important!
We encourage contributors to use AI tools responsibly when creating Pull Requests. While AI can be a valuable aid, it is essential to ensure that your contributions meet the task requirements, build successfully, include relevant tests, and pass all linters. Submissions that do not meet these standards may be closed without warning to maintain the quality and integrity of the project. Please take the time to understand the changes you are proposing and their impact.

Summary by CodeRabbit

  • New Features

    • Input throttling is now configurable via server settings (1–1000 ms, default 8 ms).
    • Token interactions are rate-limited to reduce excessive updates.
  • Bug Fixes

    • Invalid throttle values are rejected to prevent erroneous behavior.
  • Chores

    • Internal configuration simplified and validation added for the throttle setting.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 26, 2026

Walkthrough

Removed the exported CONFIG and direct FRONTEND_PORT wiring; added configurable inputThrottleMs in server-config.json and propagated it through websocket initialization into InputHandler to replace hardcoded 8ms throttling, with validation for updates.

Changes

Cohort / File(s) Summary
Config export removed & server config
src/config.tsx, src/server-config.json
Removed CONFIG export from src/config.tsx; added inputThrottleMs (default 8) to src/server-config.json.
Settings UI
src/routes/settings.tsx
Replaced usage of CONFIG.FRONTEND_PORT with serverConfig.frontendPort for frontend port initialization and placeholders.
Input handling & websocket
src/server/InputHandler.ts, src/server/websocket.ts
Added throttleMs constructor parameter to InputHandler and replaced hardcoded 8ms with configurable value; websocket reads inputThrottleMs (default 8), validates remote config updates (range [1,1000]), passes throttle into InputHandler, and uses throttle for duplicate-window/token-touch timing and throttles touchToken calls.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant WebSocketServer as WebSocket
  participant InputHandler
  participant TokenStore
  Note over WebSocket,InputHandler: Server reads `server-config.json` (inputThrottleMs) at startup

  Client->>WebSocket: send input message (move/scroll)
  WebSocket->>InputHandler: forward parsed input
  InputHandler-->>InputHandler: apply throttle (inputThrottleMs)
  alt allowed by throttle
    InputHandler->>TokenStore: touchToken (may be rate-limited)
    TokenStore-->>InputHandler: ack
    InputHandler-->>WebSocket: send response/ack
    WebSocket-->>Client: optional response
  else throttled
    InputHandler-->>WebSocket: drop or defer input
    WebSocket-->>Client: optional throttle-notice
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

Typescript Lang

Poem

🐰
I hopped through code at break of dawn,
From hardcoded eight to config drawn.
Throttle sprouted from a tiny seed,
Now inputs hop with nimble speed.
A joyful nibble — smooth, precise, and fond!

🚥 Pre-merge checks | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description is missing critical sections required by the template, including 'Addressed Issues', 'Description', and 'Screenshots/Recordings'. The description only contains unchecked checklists without explaining the actual changes. Add the missing 'Addressed Issues' section with the issue number being fixed, provide a clear 'Description' explaining what the PR does and why, include 'Screenshots/Recordings' if applicable, and verify relevant functional checks are completed or clearly marked as N/A if not applicable to these changes.
Title check ❓ Inconclusive The title 'Socket cleanup' is vague and does not clearly convey the main changes, which involve making input throttling configurable and refactoring configuration handling. Use a more descriptive title that captures the primary change, such as 'Make input throttling configurable' or 'Refactor to load frontend port directly from server-config.json'.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/server/InputHandler.ts (1)

63-75: ⚠️ Potential issue | 🟠 Major

Throttle timers should wait the remaining window, not the full window.

Current logic can delay pending events by an extra throttleMs (especially noticeable when inputThrottleMs is increased).

Proposed fix
 		if (msg.type === "move") {
 			const now = Date.now()
-			if (now - this.lastMoveTime < this.throttleMs) {
+			const elapsed = now - this.lastMoveTime
+			if (elapsed < this.throttleMs) {
 				this.pendingMove = msg
 				if (!this.moveTimer) {
+					const waitMs = this.throttleMs - elapsed
 					this.moveTimer = setTimeout(() => {
 						this.moveTimer = null
 						if (this.pendingMove) {
 							const pending = this.pendingMove
 							this.pendingMove = null
 							this.handleMessage(pending).catch((err) => {
 								console.error("Error processing pending move event:", err)
 							})
 						}
-					}, this.throttleMs)
+					}, waitMs)
 				}
 				return
 			}
 			this.lastMoveTime = now
 		} else if (msg.type === "scroll") {
 			const now = Date.now()
-			if (now - this.lastScrollTime < this.throttleMs) {
+			const elapsed = now - this.lastScrollTime
+			if (elapsed < this.throttleMs) {
 				this.pendingScroll = msg
 				if (!this.scrollTimer) {
+					const waitMs = this.throttleMs - elapsed
 					this.scrollTimer = setTimeout(() => {
 						this.scrollTimer = null
 						if (this.pendingScroll) {
 							const pending = this.pendingScroll
 							this.pendingScroll = null
 							this.handleMessage(pending).catch((err) => {
 								console.error("Error processing pending move event:", err)
 							})
 						}
-					}, this.throttleMs)
+					}, waitMs)
 				}
 				return
 			}

Also applies to: 82-94

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/server/InputHandler.ts` around lines 63 - 75, The throttle timer
currently always waits the full this.throttleMs which can add extra delay;
change the setTimeout delay in the InputHandler logic that uses
lastMoveTime/pendingMove/moveTimer to compute the remaining window as const
delay = Math.max(0, this.throttleMs - (Date.now() - this.lastMoveTime)) and use
that delay when scheduling the pending handler (and apply the same fix to the
other analogous block at 82-94). Ensure you preserve clearing moveTimer,
resetting pendingMove, and calling this.handleMessage(pending).catch(...)
exactly as before but use the computed remaining delay instead of
this.throttleMs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/routes/settings.tsx`:
- Line 5: The route is importing serverConfig from "../server-config.json" which
bundles all server-side keys into client code; remove that import from
src/routes/settings.tsx and replace usage with a frontend-safe surface (e.g.,
create a new module like frontend-config.ts that only exports allowed fields
such as frontendPort or expose the value via a server loader API). Ensure
server-config.json remains read only on the server (e.g., in loader or server
utilities) and reference the new frontend-config export in SettingsRoute (or
whichever component/function in settings.tsx uses serverConfig) so no sensitive
keys are shipped to the browser.

In `@src/server/websocket.ts`:
- Line 50: The startup-only use of inputThrottleMs (used when constructing new
InputHandler) means runtime config updates aren’t applied; change the
config-update handling to propagate new values to the live components instead of
only persisting them. Locate where InputHandler is instantiated (new
InputHandler(inputThrottleMs)) and in your update-config path call a method on
that instance to update the throttle (e.g., add or use an existing
setThrottle/updateThrottle on InputHandler) or replace the instance atomically
with a new one, and likewise update the duplicate-window variables on the
running subsystem(s) (the same places referenced around lines 122-123 and
232-250) so the new duplicate-window and inputThrottleMs values take effect
immediately at runtime.
- Around line 36-42: The JSON parsing of server-config.json is unguarded and
will throw on malformed files; update the code around configPath/serverConfig
(where fs.existsSync, fs.readFileSync and JSON.parse are used) to wrap the
read+parse in a try/catch, log or processLogger.error the parse error, and on
error fall back to an empty object (or safe defaults) so WebSocket
initialization continues; ensure serverConfig remains a Record<string, unknown>
after the fallback.

---

Outside diff comments:
In `@src/server/InputHandler.ts`:
- Around line 63-75: The throttle timer currently always waits the full
this.throttleMs which can add extra delay; change the setTimeout delay in the
InputHandler logic that uses lastMoveTime/pendingMove/moveTimer to compute the
remaining window as const delay = Math.max(0, this.throttleMs - (Date.now() -
this.lastMoveTime)) and use that delay when scheduling the pending handler (and
apply the same fix to the other analogous block at 82-94). Ensure you preserve
clearing moveTimer, resetting pendingMove, and calling
this.handleMessage(pending).catch(...) exactly as before but use the computed
remaining delay instead of this.throttleMs.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e95ab33 and eb0426d.

📒 Files selected for processing (5)
  • src/config.tsx
  • src/routes/settings.tsx
  • src/server-config.json
  • src/server/InputHandler.ts
  • src/server/websocket.ts
💤 Files with no reviewable changes (1)
  • src/config.tsx

Comment thread src/routes/settings.tsx
Comment thread src/server/websocket.ts Outdated
Comment thread src/server/websocket.ts
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/server/websocket.ts (1)

208-255: ⚠️ Potential issue | 🟠 Major

inputThrottleMs updates are persisted but not applied live.

update-config saves and validates the new value, but active behavior still uses startup-initialized instances/values (inputHandler and duplicate-window logic), so the change is not effective until restart.

Suggested fix
-	const inputHandler = new InputHandler(inputThrottleMs)
+	let inputHandler = new InputHandler(inputThrottleMs)
@@
-			const DUPLICATE_WINDOW_MS = inputThrottleMs
@@
-					if (raw === lastRaw && now - lastTime < DUPLICATE_WINDOW_MS) {
+					if (raw === lastRaw && now - lastTime < inputThrottleMs) {
 						return
 					}
@@
 								} else if (key === "inputThrottleMs") {
 									const ms = Number(msg.config[key])
@@
 									filtered[key] = ms
+									inputThrottleMs = ms
+									inputHandler = new InputHandler(inputThrottleMs)
 								} else if (
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/server/websocket.ts` around lines 208 - 255, The update-config branch
correctly validates and persists inputThrottleMs but doesn't propagate it to
running components; after you persist the new config in the handler that
processes the "update-config" message in websocket.ts, apply the value to the
live runtime: call the runtime API on the input handler (e.g.,
inputHandler.setThrottle or inputHandler.updateOptions) or, if the
implementation uses a recreated instance, recreate/replace inputHandler with the
same constructor/factory using the new ms; also update any duplicate-window
logic/timers that rely on the startup value so they read the new inputThrottleMs
(e.g., updateDuplicateWindowThreshold or reset related timers) to ensure the
change takes effect immediately without restart.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/server/websocket.ts`:
- Around line 48-52: The startup assignment for inputThrottleMs accepts any
positive number but should match the update-time validation (integer between 1
and 1000); change the initialization of inputThrottleMs (using
serverConfig.inputThrottleMs) to validate
Number.isInteger(serverConfig.inputThrottleMs) && serverConfig.inputThrottleMs
>= 1 && serverConfig.inputThrottleMs <= 1000, and fall back to the existing
default (8) if validation fails so runtime behavior matches the update-config
constraints.

---

Duplicate comments:
In `@src/server/websocket.ts`:
- Around line 208-255: The update-config branch correctly validates and persists
inputThrottleMs but doesn't propagate it to running components; after you
persist the new config in the handler that processes the "update-config" message
in websocket.ts, apply the value to the live runtime: call the runtime API on
the input handler (e.g., inputHandler.setThrottle or inputHandler.updateOptions)
or, if the implementation uses a recreated instance, recreate/replace
inputHandler with the same constructor/factory using the new ms; also update any
duplicate-window logic/timers that rely on the startup value so they read the
new inputThrottleMs (e.g., updateDuplicateWindowThreshold or reset related
timers) to ensure the change takes effect immediately without restart.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between eb0426d and 8343f24.

📒 Files selected for processing (1)
  • src/server/websocket.ts

Comment thread src/server/websocket.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant