From 2ce82a7edcbc93c372948137b06d6b315fadd103 Mon Sep 17 00:00:00 2001 From: sanio Date: Fri, 11 Jul 2025 17:58:31 +0900 Subject: [PATCH] retrieve mouth dragging on button of main header --- src/app/ApiKeyHeader.js | 4 +++ src/app/MainHeader.js | 64 ++++++++++++++++++++++++++++++++++- src/app/PermissionHeader.js | 3 ++ src/electron/windowManager.js | 55 ++++++++++++++++++++++++++++-- 4 files changed, 122 insertions(+), 4 deletions(-) diff --git a/src/app/ApiKeyHeader.js b/src/app/ApiKeyHeader.js index 1f0b938..276fa85 100644 --- a/src/app/ApiKeyHeader.js +++ b/src/app/ApiKeyHeader.js @@ -78,6 +78,7 @@ export class ApiKeyHeader extends LitElement { } .close-button { + -webkit-app-region: no-drag; position: absolute; top: 10px; right: 10px; @@ -157,6 +158,7 @@ export class ApiKeyHeader extends LitElement { } .api-input { + -webkit-app-region: no-drag; width: 100%; height: 34px; background: rgba(255, 255, 255, 0.1); @@ -184,6 +186,7 @@ export class ApiKeyHeader extends LitElement { .provider-column { flex: 1; display: flex; flex-direction: column; align-items: center; } .provider-label { color: rgba(255, 255, 255, 0.7); font-size: 11px; font-weight: 500; margin-bottom: 6px; } .api-input, .provider-select { + -webkit-app-region: no-drag; width: 100%; height: 34px; text-align: center; @@ -210,6 +213,7 @@ export class ApiKeyHeader extends LitElement { .action-button { + -webkit-app-region: no-drag; width: 100%; height: 34px; background: rgba(255, 255, 255, 0.2); diff --git a/src/app/MainHeader.js b/src/app/MainHeader.js index 4fe49f6..3f78f67 100644 --- a/src/app/MainHeader.js +++ b/src/app/MainHeader.js @@ -82,6 +82,7 @@ export class MainHeader extends LitElement { } .listen-button { + -webkit-app-region: no-drag; height: 26px; padding: 0 13px; background: transparent; @@ -189,6 +190,7 @@ export class MainHeader extends LitElement { } .header-actions { + -webkit-app-region: no-drag; height: 26px; box-sizing: border-box; justify-content: flex-start; @@ -260,6 +262,7 @@ export class MainHeader extends LitElement { } .settings-button { + -webkit-app-region: no-drag; padding: 5px; border-radius: 50%; background: transparent; @@ -350,6 +353,61 @@ export class MainHeader extends LitElement { this.actionText = 'Listen'; this.animationEndTimer = null; this.handleAnimationEnd = this.handleAnimationEnd.bind(this); + this.handleMouseMove = this.handleMouseMove.bind(this); + this.handleMouseUp = this.handleMouseUp.bind(this); + this.dragState = null; + this.wasJustDragged = false; + } + + async handleMouseDown(e) { + e.preventDefault(); + + const { ipcRenderer } = window.require('electron'); + const initialPosition = await ipcRenderer.invoke('get-header-position'); + + this.dragState = { + initialMouseX: e.screenX, + initialMouseY: e.screenY, + initialWindowX: initialPosition.x, + initialWindowY: initialPosition.y, + moved: false, + }; + + window.addEventListener('mousemove', this.handleMouseMove, { capture: true }); + window.addEventListener('mouseup', this.handleMouseUp, { once: true, capture: true }); + } + + handleMouseMove(e) { + if (!this.dragState) return; + + const deltaX = Math.abs(e.screenX - this.dragState.initialMouseX); + const deltaY = Math.abs(e.screenY - this.dragState.initialMouseY); + + if (deltaX > 3 || deltaY > 3) { + this.dragState.moved = true; + } + + const newWindowX = this.dragState.initialWindowX + (e.screenX - this.dragState.initialMouseX); + const newWindowY = this.dragState.initialWindowY + (e.screenY - this.dragState.initialMouseY); + + const { ipcRenderer } = window.require('electron'); + ipcRenderer.invoke('move-header-to', newWindowX, newWindowY); + } + + handleMouseUp(e) { + if (!this.dragState) return; + + const wasDragged = this.dragState.moved; + + window.removeEventListener('mousemove', this.handleMouseMove, { capture: true }); + this.dragState = null; + + if (wasDragged) { + this.wasJustDragged = true; + setTimeout(() => { + this.wasJustDragged = false; + }, 0); + } } toggleVisibility() { @@ -455,6 +513,7 @@ export class MainHeader extends LitElement { } invoke(channel, ...args) { + if (this.wasJustDragged) return; if (window.require) { window.require('electron').ipcRenderer.invoke(channel, ...args); } @@ -462,6 +521,7 @@ export class MainHeader extends LitElement { } showSettingsWindow(element) { + if (this.wasJustDragged) return; if (window.require) { const { ipcRenderer } = window.require('electron'); console.log(`[MainHeader] showSettingsWindow called at ${Date.now()}`); @@ -481,6 +541,7 @@ export class MainHeader extends LitElement { } hideSettingsWindow() { + if (this.wasJustDragged) return; if (window.require) { console.log(`[MainHeader] hideSettingsWindow called at ${Date.now()}`); window.require('electron').ipcRenderer.send('hide-settings-window'); @@ -488,6 +549,7 @@ export class MainHeader extends LitElement { } async _handleListenClick() { + if (this.wasJustDragged) return; if (this.isTogglingSession) { return; } @@ -536,7 +598,7 @@ export class MainHeader extends LitElement { const showStopIcon = this.actionText === 'Stop' || this.actionText === 'Done'; return html` -
+