-
@@ -54,46 +45,6 @@
}
}
- .message {
- display: flex;
- flex-direction: column;
-
- span {
- display: block;
- text-align: center;
- text-transform: uppercase;
- line-height: 30px;
- }
-
- input {
- border: none;
- padding: 6px 8px;
- line-height: 20px;
- border-radius: 5px;
- margin: 5px 0;
- background: $background-tertiary;
- color: $text-normal;
-
- &::selection {
- background: $text-link;
- }
- }
-
- button {
- cursor: pointer;
- border-radius: 5px;
- padding: 4px;
- background: $style-primary;
- color: $text-normal;
- text-align: center;
- text-transform: uppercase;
- font-weight: bold;
- line-height: 30px;
- margin: 5px 0;
- border: none;
- }
- }
-
.loader {
width: 90px;
height: 90px;
diff --git a/images/chromium-headful/client/src/components/disconnected.vue b/images/chromium-headful/client/src/components/disconnected.vue
new file mode 100644
index 00000000..db45cc78
--- /dev/null
+++ b/images/chromium-headful/client/src/components/disconnected.vue
@@ -0,0 +1,38 @@
+
+
+
+ {{ $t('disconnected.message') }}
+
+
+
+
+
+
+
diff --git a/images/chromium-headful/client/src/locale/en-us.ts b/images/chromium-headful/client/src/locale/en-us.ts
index edc7f2bb..3c976c73 100644
--- a/images/chromium-headful/client/src/locale/en-us.ts
+++ b/images/chromium-headful/client/src/locale/en-us.ts
@@ -125,3 +125,7 @@ export const files = {
uploads: 'Uploads',
upload_here: 'Click or drag files here to upload',
}
+
+export const disconnected = {
+ message: 'Browser has been shut down and is no longer available',
+}
diff --git a/images/chromium-headful/client/src/neko/base.ts b/images/chromium-headful/client/src/neko/base.ts
index 12828595..501a8fd8 100644
--- a/images/chromium-headful/client/src/neko/base.ts
+++ b/images/chromium-headful/client/src/neko/base.ts
@@ -69,8 +69,11 @@ export abstract class BaseClient extends EventEmitter
{
)
this.emit('debug', `connecting to ${this._ws.url}`)
this._ws.onmessage = this.onMessage.bind(this)
- this._ws.onerror = () => this.onError.bind(this)
- this._ws.onclose = () => this.onDisconnected.bind(this, new Error('websocket closed'))
+ this._ws.onerror = this.onError.bind(this)
+ this._ws.onclose = (event) => {
+ this.emit('debug', `websocket closed: code=${event.code}, reason=${event.reason}`)
+ this.onDisconnected(new Error('websocket closed'))
+ }
this._timeout = window.setTimeout(this.onTimeout.bind(this), 15000)
} catch (err: any) {
this.onDisconnected(err)
diff --git a/images/chromium-headful/client/src/neko/index.ts b/images/chromium-headful/client/src/neko/index.ts
index b0fb9397..92df801d 100644
--- a/images/chromium-headful/client/src/neko/index.ts
+++ b/images/chromium-headful/client/src/neko/index.ts
@@ -75,13 +75,14 @@ export class NekoClient extends BaseClient implements EventEmitter {
// Internal Events
/////////////////////////////
protected [EVENT.RECONNECTING]() {
- this.$vue.$notify({
- group: 'neko',
- type: 'warning',
- title: this.$vue.$t('connection.reconnecting') as string,
- duration: 5000,
- speed: 1000,
- })
+ // KERNEL: Differentiate between temporary network issues and permanent disconnection
+ // If WebSocket is still open, this is likely a temporary ICE disconnection (network glitch)
+ // Allow WebRTC to attempt recovery automatically
+ // If WebSocket is closed, the browser process is likely gone - show disconnected overlay
+ if (!this.socketOpen) {
+ this.cleanup()
+ }
+ // else: WebSocket still open, let WebRTC recover naturally
}
protected [EVENT.CONNECTING]() {