Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions images/chromium-headful/client/src/components/video.vue
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,10 @@
return this.$accessor.connecting
}

get controlling() {
return this.$accessor.remote.controlling
}

get hosting() {
return this.$accessor.remote.hosting
}
Expand Down Expand Up @@ -807,6 +811,10 @@
onMouseDown(e: MouseEvent) {
this.unmuteOnInteraction()

if (!this.controlling && this.implicitHosting && !this.locked) {
this.$accessor.remote.request()
}

if (!this.hosting) {
this.$emit('control-attempt', e)
}
Expand Down
20 changes: 9 additions & 11 deletions images/chromium-headful/client/src/neko/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,17 +240,15 @@ export class NekoClient extends BaseClient implements EventEmitter<NekoEvents> {
return
}

if (this.id === id) {
this.$vue.$notify({
group: 'neko',
type: 'info',
title: this.$vue.$t('notifications.controls_taken', {
name: member.id == this.id && this.$vue.$te('you') ? this.$vue.$t('you') : member.displayname,
}) as string,
duration: 5000,
speed: 1000,
})
}
// KERNEL: drop the self-only "you took the controls" toast (was gated on
// this.id === id). With implicit hosting, control is now registered
// automatically on the first interaction (see remote.request() in
// video.vue), so it would fire on essentially every session's first click
// — pure noise for a single-viewer embedded live view. The chat event
// below (and other members' take/steal toasts elsewhere) is unaffected.
// Note: this is a shared component, so explicit control-takes in the full
// neko UI also lose this confirmation; acceptable since Kernel only ships
// the embedded live view.

this.$accessor.chat.newMessage({
id: member.id,
Expand Down
19 changes: 17 additions & 2 deletions images/chromium-headful/client/src/store/remote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,16 @@ export const state = () => ({
implicitHosting: true,
fileTransfer: true,
keyboardModifierState: -1,
// true once a control/request has been sent and we're waiting for the
// server's control/locked response. Prevents rapid clicks from emitting
// multiple requests before `controlling` flips.
requesting: false,
})

export const getters = getterTree(state, {
controlling: (state, getters, root) => {
return root.user.id !== '' && root.user.id === state.id
},
hosting: (state, getters, root) => {
return root.user.id === state.id || state.implicitHosting
},
Expand All @@ -36,6 +43,8 @@ export const mutations = mutationTree(state, {
} else {
state.id = host.id
}
// host resolved (for us or someone else) — clear any pending request
state.requesting = false
},

setClipboard(state, clipboard: string) {
Expand All @@ -58,10 +67,15 @@ export const mutations = mutationTree(state, {
state.fileTransfer = val
},

setRequesting(state, val: boolean) {
state.requesting = val
},

reset(state) {
state.id = ''
state.clipboard = ''
state.locked = false
state.requesting = false
},
})

Expand All @@ -88,11 +102,12 @@ export const actions = actionTree(
}
},

request({ getters }) {
if (!accessor.connected || getters.hosting) {
request({ state, getters }) {
if (!accessor.connected || getters.controlling || state.requesting) {
return
}

accessor.remote.setRequesting(true)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stuck requesting blocks host registration

Medium Severity

The request action sets requesting to true before confirming the message can be sent. If $client.connected is false (e.g., during network reconnects), sendMessage no-ops, leaving requesting latched true. This incorrectly blocks subsequent control requests, breaking host registration and clipboard sync until a full reset.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c15d5d5. Configure here.

$client.sendMessage(EVENT.CONTROL.REQUEST)
},

Expand Down
Loading