Skip to content

Conversation

@archandatta
Copy link
Contributor

@archandatta archandatta commented Jan 15, 2026

Note

Introduces a post-disconnect overlay and refines connection lifecycle handling.

  • New neko-disconnected overlay with i18n (disconnected.message) to inform users when the browser session is no longer available
  • Connection flow update in app.vue: show neko-connect only before first successful connection (!connected && !wasConnected); show neko-disconnected after a dropped session (!connected && wasConnected); track via new wasConnected with watchers
  • Reconnection logic tweak in client (neko/index.ts): treat ICE hiccups vs. permanent shutdown differently—only cleanup when WebSocket is closed; remove reconnecting toast
  • WebSocket handling fixes (neko/base.ts): correct onerror binding and add detailed close logging before invoking disconnection
  • UI cleanup in connect.vue: remove manual login form; keep loader/auto-login behavior

Written by Cursor Bugbot for commit 9227a23. This will update automatically on new commits. Configure here.

Copy link
Contributor

@tembo tembo bot left a comment

Choose a reason for hiding this comment

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

A few small things to consider from the diff:

  1. images/chromium-headful/client/src/app.vue
  • There are now two @Watch('connected', { immediate: true }) handlers (onConnected and onConnectedChange). Might be simpler/less error-prone to fold the wasConnected behavior into the existing onConnected watcher so there’s only one place reacting to connection transitions.
@Watch('connected', { immediate: true })
onConnected(connected: boolean) {
  if (connected) {
    this.wasConnected = true
    this.applyQueryResolution()
  }
}
  1. images/chromium-headful/client/src/components/connect.vue
  • Removing the non-connecting form means the overlay can render empty if we’re not connecting but also not connected (e.g. transient failures, bad creds, server down). Even a minimal fallback text + retry/reload affordance would help avoid a “blank screen” state.
  1. images/chromium-headful/client/src/components/disconnected.vue
  • Since this is user-facing UI, consider using existing theme vars + i18n rather than hard-coded strings/colors so it stays consistent with the rest of the client.
  1. images/chromium-headful/client/src/neko/base.ts
  • Nice fix on the handler binding. Since you already log code/reason on close, it could be useful to include that detail in the Error you pass into onDisconnected so the UI/toasts can surface it.
this.onDisconnected(
  new Error(
    `websocket closed: code=${event.code}${event.reason ? `, reason=${event.reason}` : ''}`,
  ),
)
  1. images/chromium-headful/client/src/neko/index.ts
  • EVENT.RECONNECTING now calls cleanup() and the comment says “Don’t … attempt reconnection”. If the intent is to fully stop reconnect attempts, it might be worth ensuring any underlying reconnect timers/sockets are also stopped, or updating the comment to match what actually happens.

@archandatta archandatta marked this pull request as ready for review January 15, 2026 18:40
@archandatta archandatta requested a review from rgarcia January 15, 2026 18:40
Copy link
Contributor

@tembo tembo bot left a comment

Choose a reason for hiding this comment

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

Overall direction makes sense: distinguish first-connect vs post-connect disconnect, and fixing the websocket handler bindings is definitely the right move.

A few small follow-ups:

  • Consider including the websocket close code/reason in the Error passed into the disconnected path (right now it’s only in debug logs).
  • The new disconnected overlay likely wants an explicit z-index so it always sits above the video/menus.
  • connect.vue can render a blank overlay when connecting is false; making the loader unconditional avoids that.
  • Minor copy tweak: “shut down” reads more natural than “shutdown”.
  • wasConnected never resets; if there’s ever an explicit logout/new-session flow, it can trap users on the disconnected overlay.

Comment on lines +73 to +76
this._ws.onclose = (event) => {
this.emit('debug', `websocket closed: code=${event.code}, reason=${event.reason}`)
this.onDisconnected(new Error('websocket closed'))
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice fix on the event handler binding.

Right now we log event.code/event.reason but the user-facing Error('websocket closed') drops that context (it ends up in the disconnected notification text). Might be worth carrying the details into the Error message.

Suggested change
this._ws.onclose = (event) => {
this.emit('debug', `websocket closed: code=${event.code}, reason=${event.reason}`)
this.onDisconnected(new Error('websocket closed'))
}
this._ws.onclose = (event) => {
const message = `websocket closed: code=${event.code}, reason=${event.reason || 'unknown'}`
this.emit('debug', message)
this.onDisconnected(new Error(message))
}


<style lang="scss" scoped>
.disconnected-overlay {
position: fixed;
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor UI nit: since this is a full-screen overlay, adding an explicit z-index helps ensure it always renders above the video/menus.

Suggested change
position: fixed;
position: fixed;
z-index: 9999;

{{ $t('connect.connect') }}
</button>
</form>
<div class="loader" v-if="connecting">
Copy link
Contributor

Choose a reason for hiding this comment

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

Since the login form is gone, v-if="connecting" can leave an empty overlay if connecting briefly flips false/undefined during init. Making the loader unconditional avoids a blank screen.

Suggested change
<div class="loader" v-if="connecting">
<div class="loader">

}

export const disconnected = {
message: 'Browser has been shutdown and is no longer available',
Copy link
Contributor

Choose a reason for hiding this comment

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

Tiny copy tweak: "shut down" reads a bit more natural here.

Suggested change
message: 'Browser has been shutdown and is no longer available',
message: 'Browser has been shut down and is no longer available',

Copy link
Contributor

Choose a reason for hiding this comment

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

agree with tembo!

<neko-side v-if="!videoOnly && side" />
<neko-connect v-if="!connected" />
<neko-connect v-if="!connected && !wasConnected" />
<neko-disconnected v-if="!connected && wasConnected" />
Copy link
Contributor

Choose a reason for hiding this comment

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

One edge case with wasConnected: if there’s an explicit logout flow (or any future “start a new session” flow), this flag never resets so you can get stuck on the disconnected overlay forever. Might be worth either (a) renaming it to something like hasEverConnected to make the semantics explicit, and/or (b) resetting it when initiating a new login attempt (or when the store indicates a new session).

background: #000;
display: flex;
justify-content: center;
align-items: center;
Copy link

Choose a reason for hiding this comment

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

Disconnected overlay missing position fixed for proper layering

High Severity

The .disconnected-overlay CSS uses width: 100vw; height: 100vh but lacks position: fixed (or position: absolute with positioning offsets). Since the parent #neko container uses display: flex; flex-direction: row, this overlay becomes a flex item laid out alongside main.neko-main rather than overlaying the content. Other overlay components like neko-connect and neko-about correctly use position: fixed/absolute with top/left/right/bottom: 0 to achieve proper overlay behavior.

Fix in Cursor Fix in Web

Copy link
Contributor

@rgarcia rgarcia left a comment

Choose a reason for hiding this comment

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

agree with the one comment about copy but otherwise lgtm

}

export const disconnected = {
message: 'Browser has been shutdown and is no longer available',
Copy link
Contributor

Choose a reason for hiding this comment

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

agree with tembo!

@archandatta archandatta force-pushed the archand/kernel-797/add-disconnected-screen branch from 0b98dc4 to 9227a23 Compare January 16, 2026 17:23
@archandatta archandatta requested a review from rgarcia January 16, 2026 17:23
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.


export const disconnected = {
message: 'Browser has been shut down and is no longer available',
}
Copy link

Choose a reason for hiding this comment

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

Missing translation for disconnected message in non-English locales

Medium Severity

The new disconnected translation object was only added to en-us.ts, but the application supports 12 other locales (de-de, es-sp, sk-sk, sv-se, nb-no, fr-fr, ko-kr, fi-fi, ru-ru, zh-cn, zh-tw, ja-jp). When users with non-English locales view the disconnected screen, $t('disconnected.message') will fail to find the translation, causing either the raw key string to display or unexpected fallback behavior instead of a proper localized message.

Fix in Cursor Fix in Web

@archandatta archandatta merged commit 766e761 into main Jan 16, 2026
7 of 8 checks passed
@archandatta archandatta deleted the archand/kernel-797/add-disconnected-screen branch January 16, 2026 17:46
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.

3 participants