Merge branch 'main' of https://github.com/pickle-com/glass
This commit is contained in:
		
						commit
						2a1edb6ed8
					
				
							
								
								
									
										35
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										35
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -4172,6 +4172,28 @@
 | 
				
			|||||||
                "node": ">= 8"
 | 
					                "node": ">= 8"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        "node_modules/fs-temp": {
 | 
				
			||||||
 | 
					            "version": "1.2.1",
 | 
				
			||||||
 | 
					            "dev": true,
 | 
				
			||||||
 | 
					            "license": "MIT",
 | 
				
			||||||
 | 
					            "optional": true,
 | 
				
			||||||
 | 
					            "dependencies": {
 | 
				
			||||||
 | 
					                "random-path": "^0.1.0"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "node_modules/fs-xattr": {
 | 
				
			||||||
 | 
					            "version": "0.3.1",
 | 
				
			||||||
 | 
					            "dev": true,
 | 
				
			||||||
 | 
					            "hasInstallScript": true,
 | 
				
			||||||
 | 
					            "license": "MIT",
 | 
				
			||||||
 | 
					            "optional": true,
 | 
				
			||||||
 | 
					            "os": [
 | 
				
			||||||
 | 
					                "!win32"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "engines": {
 | 
				
			||||||
 | 
					                "node": ">=8.6.0"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        "node_modules/fs.realpath": {
 | 
					        "node_modules/fs.realpath": {
 | 
				
			||||||
            "version": "1.0.0",
 | 
					            "version": "1.0.0",
 | 
				
			||||||
            "dev": true,
 | 
					            "dev": true,
 | 
				
			||||||
@ -5136,6 +5158,19 @@
 | 
				
			|||||||
                "lru-cache": "6.0.0"
 | 
					                "lru-cache": "6.0.0"
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        "node_modules/macos-alias": {
 | 
				
			||||||
 | 
					            "version": "0.2.12",
 | 
				
			||||||
 | 
					            "dev": true,
 | 
				
			||||||
 | 
					            "hasInstallScript": true,
 | 
				
			||||||
 | 
					            "license": "MIT",
 | 
				
			||||||
 | 
					            "optional": true,
 | 
				
			||||||
 | 
					            "os": [
 | 
				
			||||||
 | 
					                "darwin"
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            "dependencies": {
 | 
				
			||||||
 | 
					                "nan": "^2.4.0"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        "node_modules/make-fetch-happen": {
 | 
					        "node_modules/make-fetch-happen": {
 | 
				
			||||||
            "version": "10.2.1",
 | 
					            "version": "10.2.1",
 | 
				
			||||||
            "dev": true,
 | 
					            "dev": true,
 | 
				
			||||||
 | 
				
			|||||||
@ -25,15 +25,14 @@ export class ApiKeyHeader extends LitElement {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  static styles = css`
 | 
					  static styles = css`
 | 
				
			||||||
        :host {
 | 
					        :host {
 | 
				
			||||||
            display: block;
 | 
					          display: block;
 | 
				
			||||||
            transform: translate3d(0, 0, 0);
 | 
					          transition: opacity 0.3s ease-in, transform 0.3s ease-in;
 | 
				
			||||||
            backface-visibility: hidden;
 | 
					          will-change: opacity, transform;
 | 
				
			||||||
            transition: opacity 0.25s ease-out;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        :host(.sliding-out) {
 | 
					        :host(.sliding-out) {
 | 
				
			||||||
            animation: slideOutUp 0.3s ease-in forwards;
 | 
					            opacity: 0;
 | 
				
			||||||
            will-change: opacity, transform;
 | 
					            transform: translateY(-20px);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        :host(.hidden) {
 | 
					        :host(.hidden) {
 | 
				
			||||||
@ -41,17 +40,6 @@ export class ApiKeyHeader extends LitElement {
 | 
				
			|||||||
            pointer-events: none;
 | 
					            pointer-events: none;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @keyframes slideOutUp {
 | 
					 | 
				
			||||||
            from {
 | 
					 | 
				
			||||||
                opacity: 1;
 | 
					 | 
				
			||||||
                transform: translateY(0);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            to {
 | 
					 | 
				
			||||||
                opacity: 0;
 | 
					 | 
				
			||||||
                transform: translateY(-20px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        * {
 | 
					        * {
 | 
				
			||||||
            font-family: 'Helvetica Neue', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
 | 
					            font-family: 'Helvetica Neue', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
 | 
				
			||||||
            cursor: default;
 | 
					            cursor: default;
 | 
				
			||||||
@ -60,6 +48,7 @@ export class ApiKeyHeader extends LitElement {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        .container {
 | 
					        .container {
 | 
				
			||||||
 | 
					            -webkit-app-region: drag;
 | 
				
			||||||
            width: 350px;
 | 
					            width: 350px;
 | 
				
			||||||
            min-height: 260px;
 | 
					            min-height: 260px;
 | 
				
			||||||
            padding: 18px 20px;
 | 
					            padding: 18px 20px;
 | 
				
			||||||
@ -89,6 +78,7 @@ export class ApiKeyHeader extends LitElement {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        .close-button {
 | 
					        .close-button {
 | 
				
			||||||
 | 
					            -webkit-app-region: no-drag;
 | 
				
			||||||
            position: absolute;
 | 
					            position: absolute;
 | 
				
			||||||
            top: 10px;
 | 
					            top: 10px;
 | 
				
			||||||
            right: 10px;
 | 
					            right: 10px;
 | 
				
			||||||
@ -168,6 +158,7 @@ export class ApiKeyHeader extends LitElement {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        .api-input {
 | 
					        .api-input {
 | 
				
			||||||
 | 
					            -webkit-app-region: no-drag;
 | 
				
			||||||
            width: 100%;
 | 
					            width: 100%;
 | 
				
			||||||
            height: 34px;
 | 
					            height: 34px;
 | 
				
			||||||
            background: rgba(255, 255, 255, 0.1);
 | 
					            background: rgba(255, 255, 255, 0.1);
 | 
				
			||||||
@ -195,6 +186,7 @@ export class ApiKeyHeader extends LitElement {
 | 
				
			|||||||
        .provider-column { flex: 1; display: flex; flex-direction: column; align-items: center; }
 | 
					        .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; }
 | 
					        .provider-label { color: rgba(255, 255, 255, 0.7); font-size: 11px; font-weight: 500; margin-bottom: 6px; }
 | 
				
			||||||
        .api-input, .provider-select {
 | 
					        .api-input, .provider-select {
 | 
				
			||||||
 | 
					            -webkit-app-region: no-drag;
 | 
				
			||||||
            width: 100%;
 | 
					            width: 100%;
 | 
				
			||||||
            height: 34px;
 | 
					            height: 34px;
 | 
				
			||||||
            text-align: center;
 | 
					            text-align: center;
 | 
				
			||||||
@ -221,6 +213,7 @@ export class ApiKeyHeader extends LitElement {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        .action-button {
 | 
					        .action-button {
 | 
				
			||||||
 | 
					            -webkit-app-region: no-drag;
 | 
				
			||||||
            width: 100%;
 | 
					            width: 100%;
 | 
				
			||||||
            height: 34px;
 | 
					            height: 34px;
 | 
				
			||||||
            background: rgba(255, 255, 255, 0.2);
 | 
					            background: rgba(255, 255, 255, 0.2);
 | 
				
			||||||
@ -266,37 +259,10 @@ export class ApiKeyHeader extends LitElement {
 | 
				
			|||||||
            font-weight: 500; /* Medium */
 | 
					            font-weight: 500; /* Medium */
 | 
				
			||||||
            margin: 10px 0;
 | 
					            margin: 10px 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /* ────────────────[ GLASS BYPASS ]─────────────── */
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .container,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .api-input,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .provider-select,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .action-button,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .close-button {
 | 
					 | 
				
			||||||
            background: transparent !important;
 | 
					 | 
				
			||||||
            border: none !important;
 | 
					 | 
				
			||||||
            box-shadow: none !important;
 | 
					 | 
				
			||||||
            filter: none !important;
 | 
					 | 
				
			||||||
            backdrop-filter: none !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .container::after,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .action-button::after {
 | 
					 | 
				
			||||||
            display: none !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .action-button:hover,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .provider-select:hover,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .close-button:hover {
 | 
					 | 
				
			||||||
            background: transparent !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    `
 | 
					    `
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor() {
 | 
					  constructor() {
 | 
				
			||||||
    super()
 | 
					    super()
 | 
				
			||||||
    this.dragState = null
 | 
					 | 
				
			||||||
    this.wasJustDragged = false
 | 
					 | 
				
			||||||
    this.isLoading = false
 | 
					    this.isLoading = false
 | 
				
			||||||
    this.errorMessage = ""
 | 
					    this.errorMessage = ""
 | 
				
			||||||
    this.successMessage = ""
 | 
					    this.successMessage = ""
 | 
				
			||||||
@ -358,8 +324,6 @@ export class ApiKeyHeader extends LitElement {
 | 
				
			|||||||
    this.loadProviderConfig();
 | 
					    this.loadProviderConfig();
 | 
				
			||||||
    //////// after_modelStateService ////////
 | 
					    //////// after_modelStateService ////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.handleMouseMove = this.handleMouseMove.bind(this)
 | 
					 | 
				
			||||||
    this.handleMouseUp = this.handleMouseUp.bind(this)
 | 
					 | 
				
			||||||
    this.handleKeyPress = this.handleKeyPress.bind(this)
 | 
					    this.handleKeyPress = this.handleKeyPress.bind(this)
 | 
				
			||||||
    this.handleSubmit = this.handleSubmit.bind(this)
 | 
					    this.handleSubmit = this.handleSubmit.bind(this)
 | 
				
			||||||
    this.handleInput = this.handleInput.bind(this)
 | 
					    this.handleInput = this.handleInput.bind(this)
 | 
				
			||||||
@ -1533,7 +1497,6 @@ export class ApiKeyHeader extends LitElement {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  handleUsePicklesKey(e) {
 | 
					  handleUsePicklesKey(e) {
 | 
				
			||||||
    e.preventDefault()
 | 
					    e.preventDefault()
 | 
				
			||||||
    if (this.wasJustDragged) return
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    console.log("Requesting Firebase authentication from main process...")
 | 
					    console.log("Requesting Firebase authentication from main process...")
 | 
				
			||||||
    if (window.require) {
 | 
					    if (window.require) {
 | 
				
			||||||
 | 
				
			|||||||
@ -9,10 +9,7 @@ export class MainHeader extends LitElement {
 | 
				
			|||||||
    static styles = css`
 | 
					    static styles = css`
 | 
				
			||||||
        :host {
 | 
					        :host {
 | 
				
			||||||
            display: flex;
 | 
					            display: flex;
 | 
				
			||||||
            transform: translate3d(0, 0, 0);
 | 
					 | 
				
			||||||
            backface-visibility: hidden;
 | 
					 | 
				
			||||||
            transition: transform 0.2s cubic-bezier(0.23, 1, 0.32, 1), opacity 0.2s ease-out;
 | 
					            transition: transform 0.2s cubic-bezier(0.23, 1, 0.32, 1), opacity 0.2s ease-out;
 | 
				
			||||||
            will-change: transform, opacity;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        :host(.hiding) {
 | 
					        :host(.hiding) {
 | 
				
			||||||
@ -33,65 +30,6 @@ export class MainHeader extends LitElement {
 | 
				
			|||||||
            pointer-events: none;
 | 
					            pointer-events: none;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @keyframes slideUp {
 | 
					 | 
				
			||||||
            0% {
 | 
					 | 
				
			||||||
                opacity: 1;
 | 
					 | 
				
			||||||
                transform: translateY(0) scale(1);
 | 
					 | 
				
			||||||
                filter: blur(0px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            30% {
 | 
					 | 
				
			||||||
                opacity: 0.7;
 | 
					 | 
				
			||||||
                transform: translateY(-20%) scale(0.98);
 | 
					 | 
				
			||||||
                filter: blur(0.5px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            70% {
 | 
					 | 
				
			||||||
                opacity: 0.3;
 | 
					 | 
				
			||||||
                transform: translateY(-80%) scale(0.92);
 | 
					 | 
				
			||||||
                filter: blur(1.5px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            100% {
 | 
					 | 
				
			||||||
                opacity: 0;
 | 
					 | 
				
			||||||
                transform: translateY(-150%) scale(0.85);
 | 
					 | 
				
			||||||
                filter: blur(2px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        @keyframes slideDown {
 | 
					 | 
				
			||||||
            0% {
 | 
					 | 
				
			||||||
                opacity: 0;
 | 
					 | 
				
			||||||
                transform: translateY(-150%) scale(0.85);
 | 
					 | 
				
			||||||
                filter: blur(2px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            30% {
 | 
					 | 
				
			||||||
                opacity: 0.5;
 | 
					 | 
				
			||||||
                transform: translateY(-50%) scale(0.92);
 | 
					 | 
				
			||||||
                filter: blur(1px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            65% {
 | 
					 | 
				
			||||||
                opacity: 0.9;
 | 
					 | 
				
			||||||
                transform: translateY(-5%) scale(0.99);
 | 
					 | 
				
			||||||
                filter: blur(0.2px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            85% {
 | 
					 | 
				
			||||||
                opacity: 0.98;
 | 
					 | 
				
			||||||
                transform: translateY(2%) scale(1.005);
 | 
					 | 
				
			||||||
                filter: blur(0px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            100% {
 | 
					 | 
				
			||||||
                opacity: 1;
 | 
					 | 
				
			||||||
                transform: translateY(0) scale(1);
 | 
					 | 
				
			||||||
                filter: blur(0px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        @keyframes fadeIn {
 | 
					 | 
				
			||||||
            0% {
 | 
					 | 
				
			||||||
                opacity: 0;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            100% {
 | 
					 | 
				
			||||||
                opacity: 1;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        * {
 | 
					        * {
 | 
				
			||||||
            font-family: 'Helvetica Neue', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
 | 
					            font-family: 'Helvetica Neue', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
 | 
				
			||||||
@ -100,6 +38,7 @@ export class MainHeader extends LitElement {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        .header {
 | 
					        .header {
 | 
				
			||||||
 | 
					            -webkit-app-region: drag;
 | 
				
			||||||
            width: max-content;
 | 
					            width: max-content;
 | 
				
			||||||
            height: 47px;
 | 
					            height: 47px;
 | 
				
			||||||
            padding: 2px 10px 2px 13px;
 | 
					            padding: 2px 10px 2px 13px;
 | 
				
			||||||
@ -141,6 +80,7 @@ export class MainHeader extends LitElement {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        .listen-button {
 | 
					        .listen-button {
 | 
				
			||||||
 | 
					            -webkit-app-region: no-drag;
 | 
				
			||||||
            height: 26px;
 | 
					            height: 26px;
 | 
				
			||||||
            padding: 0 13px;
 | 
					            padding: 0 13px;
 | 
				
			||||||
            background: transparent;
 | 
					            background: transparent;
 | 
				
			||||||
@ -193,6 +133,7 @@ export class MainHeader extends LitElement {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        .header-actions {
 | 
					        .header-actions {
 | 
				
			||||||
 | 
					            -webkit-app-region: no-drag;
 | 
				
			||||||
            height: 26px;
 | 
					            height: 26px;
 | 
				
			||||||
            box-sizing: border-box;
 | 
					            box-sizing: border-box;
 | 
				
			||||||
            justify-content: flex-start;
 | 
					            justify-content: flex-start;
 | 
				
			||||||
@ -264,6 +205,7 @@ export class MainHeader extends LitElement {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        .settings-button {
 | 
					        .settings-button {
 | 
				
			||||||
 | 
					            -webkit-app-region: no-drag;
 | 
				
			||||||
            padding: 5px;
 | 
					            padding: 5px;
 | 
				
			||||||
            border-radius: 50%;
 | 
					            border-radius: 50%;
 | 
				
			||||||
            background: transparent;
 | 
					            background: transparent;
 | 
				
			||||||
@ -291,125 +233,20 @@ export class MainHeader extends LitElement {
 | 
				
			|||||||
            width: 16px;
 | 
					            width: 16px;
 | 
				
			||||||
            height: 16px;
 | 
					            height: 16px;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* ────────────────[ GLASS BYPASS ]─────────────── */
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .header,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .listen-button,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .header-actions,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .settings-button {
 | 
					 | 
				
			||||||
            background: transparent !important;
 | 
					 | 
				
			||||||
            filter: none !important;
 | 
					 | 
				
			||||||
            box-shadow: none !important;
 | 
					 | 
				
			||||||
            backdrop-filter: none !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .icon-box {
 | 
					 | 
				
			||||||
            background: transparent !important;
 | 
					 | 
				
			||||||
            border: none !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .header::before,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .header::after,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .listen-button::before,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .listen-button::after {
 | 
					 | 
				
			||||||
            display: none !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .header-actions:hover,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .settings-button:hover,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .listen-button:hover::before {
 | 
					 | 
				
			||||||
            background: transparent !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) * {
 | 
					 | 
				
			||||||
            animation: none !important;
 | 
					 | 
				
			||||||
            transition: none !important;
 | 
					 | 
				
			||||||
            transform: none !important;
 | 
					 | 
				
			||||||
            filter: none !important;
 | 
					 | 
				
			||||||
            backdrop-filter: none !important;
 | 
					 | 
				
			||||||
            box-shadow: none !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .header,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .listen-button,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .header-actions,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .settings-button,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .icon-box {
 | 
					 | 
				
			||||||
            border-radius: 0 !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) {
 | 
					 | 
				
			||||||
            animation: none !important;
 | 
					 | 
				
			||||||
            transition: none !important;
 | 
					 | 
				
			||||||
            transform: none !important;
 | 
					 | 
				
			||||||
            will-change: auto !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        `;
 | 
					        `;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor() {
 | 
					    constructor() {
 | 
				
			||||||
        super();
 | 
					        super();
 | 
				
			||||||
        this.shortcuts = {};
 | 
					        this.shortcuts = {};
 | 
				
			||||||
        this.dragState = null;
 | 
					 | 
				
			||||||
        this.wasJustDragged = false;
 | 
					 | 
				
			||||||
        this.isVisible = true;
 | 
					        this.isVisible = true;
 | 
				
			||||||
        this.isAnimating = false;
 | 
					        this.isAnimating = false;
 | 
				
			||||||
        this.hasSlidIn = false;
 | 
					        this.hasSlidIn = false;
 | 
				
			||||||
        this.settingsHideTimer = null;
 | 
					        this.settingsHideTimer = null;
 | 
				
			||||||
        this.isSessionActive = false;
 | 
					        this.isSessionActive = false;
 | 
				
			||||||
        this.animationEndTimer = null;
 | 
					        this.animationEndTimer = null;
 | 
				
			||||||
        this.handleMouseMove = this.handleMouseMove.bind(this);
 | 
					 | 
				
			||||||
        this.handleMouseUp = this.handleMouseUp.bind(this);
 | 
					 | 
				
			||||||
        this.handleAnimationEnd = this.handleAnimationEnd.bind(this);
 | 
					        this.handleAnimationEnd = this.handleAnimationEnd.bind(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    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() {
 | 
					    toggleVisibility() {
 | 
				
			||||||
        if (this.isAnimating) {
 | 
					        if (this.isAnimating) {
 | 
				
			||||||
            console.log('[MainHeader] Animation already in progress, ignoring toggle');
 | 
					            console.log('[MainHeader] Animation already in progress, ignoring toggle');
 | 
				
			||||||
@ -431,58 +268,29 @@ export class MainHeader extends LitElement {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    hide() {
 | 
					    hide() {
 | 
				
			||||||
        this.classList.remove('showing', 'hidden');
 | 
					        this.classList.remove('showing');
 | 
				
			||||||
        this.classList.add('hiding');
 | 
					        this.classList.add('hiding');
 | 
				
			||||||
        this.isVisible = false;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        this.animationEndTimer = setTimeout(() => {
 | 
					 | 
				
			||||||
            if (this.classList.contains('hiding')) {
 | 
					 | 
				
			||||||
                this.handleAnimationEnd({ target: this });
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }, 350);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    show() {
 | 
					    show() {
 | 
				
			||||||
        this.classList.remove('hiding', 'hidden');
 | 
					        this.classList.remove('hiding', 'hidden');
 | 
				
			||||||
        this.classList.add('showing');
 | 
					        this.classList.add('showing');
 | 
				
			||||||
        this.isVisible = true;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        this.animationEndTimer = setTimeout(() => {
 | 
					 | 
				
			||||||
            if (this.classList.contains('showing')) {
 | 
					 | 
				
			||||||
                this.handleAnimationEnd({ target: this });
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }, 400);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    handleAnimationEnd(e) {
 | 
					    handleAnimationEnd(e) {
 | 
				
			||||||
        if (e.target !== this) return;
 | 
					        if (e.target !== this) return;
 | 
				
			||||||
        
 | 
					    
 | 
				
			||||||
        if (this.animationEndTimer) {
 | 
					 | 
				
			||||||
            clearTimeout(this.animationEndTimer);
 | 
					 | 
				
			||||||
            this.animationEndTimer = null;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        this.isAnimating = false;
 | 
					        this.isAnimating = false;
 | 
				
			||||||
        
 | 
					    
 | 
				
			||||||
        if (this.classList.contains('hiding')) {
 | 
					        if (this.classList.contains('hiding')) {
 | 
				
			||||||
            this.classList.remove('hiding');
 | 
					 | 
				
			||||||
            this.classList.add('hidden');
 | 
					            this.classList.add('hidden');
 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            if (window.require) {
 | 
					            if (window.require) {
 | 
				
			||||||
                const { ipcRenderer } = window.require('electron');
 | 
					                window.require('electron').ipcRenderer.send('header-animation-finished', 'hidden');
 | 
				
			||||||
                ipcRenderer.send('header-animation-complete', 'hidden');
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else if (this.classList.contains('showing')) {
 | 
					        } else if (this.classList.contains('showing')) {
 | 
				
			||||||
            this.classList.remove('showing');
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            if (window.require) {
 | 
					            if (window.require) {
 | 
				
			||||||
                const { ipcRenderer } = window.require('electron');
 | 
					                window.require('electron').ipcRenderer.send('header-animation-finished', 'visible');
 | 
				
			||||||
                ipcRenderer.send('header-animation-complete', 'visible');
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else if (this.classList.contains('sliding-in')) {
 | 
					 | 
				
			||||||
            this.classList.remove('sliding-in');
 | 
					 | 
				
			||||||
            this.hasSlidIn = true;
 | 
					 | 
				
			||||||
            console.log('[MainHeader] Slide-in animation completed');
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -530,50 +338,37 @@ export class MainHeader extends LitElement {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    invoke(channel, ...args) {
 | 
					    invoke(channel, ...args) {
 | 
				
			||||||
        if (this.wasJustDragged) {
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (window.require) {
 | 
					        if (window.require) {
 | 
				
			||||||
            window.require('electron').ipcRenderer.invoke(channel, ...args);
 | 
					            window.require('electron').ipcRenderer.invoke(channel, ...args);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    showWindow(name, element) {
 | 
					    showSettingsWindow(element) {
 | 
				
			||||||
        if (this.wasJustDragged) return;
 | 
					 | 
				
			||||||
        if (window.require) {
 | 
					        if (window.require) {
 | 
				
			||||||
            const { ipcRenderer } = window.require('electron');
 | 
					            const { ipcRenderer } = window.require('electron');
 | 
				
			||||||
            console.log(`[MainHeader] showWindow('${name}') called at ${Date.now()}`);
 | 
					            console.log(`[MainHeader] showSettingsWindow called at ${Date.now()}`);
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            ipcRenderer.send('cancel-hide-window', name);
 | 
					            ipcRenderer.send('cancel-hide-settings-window');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (name === 'settings' && element) {
 | 
					            if (element) {
 | 
				
			||||||
                const rect = element.getBoundingClientRect();
 | 
					                const { left, top, width, height } = element.getBoundingClientRect();
 | 
				
			||||||
                ipcRenderer.send('show-window', {
 | 
					                ipcRenderer.send('show-settings-window', {
 | 
				
			||||||
                    name: 'settings',
 | 
					                    x: left,
 | 
				
			||||||
                    bounds: {
 | 
					                    y: top,
 | 
				
			||||||
                        x: rect.left,
 | 
					                    width,
 | 
				
			||||||
                        y: rect.top,
 | 
					                    height,
 | 
				
			||||||
                        width: rect.width,
 | 
					 | 
				
			||||||
                        height: rect.height
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                ipcRenderer.send('show-window', name);
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    hideWindow(name) {
 | 
					    hideSettingsWindow() {
 | 
				
			||||||
        if (this.wasJustDragged) return;
 | 
					 | 
				
			||||||
        if (window.require) {
 | 
					        if (window.require) {
 | 
				
			||||||
            console.log(`[MainHeader] hideWindow('${name}') called at ${Date.now()}`);
 | 
					            console.log(`[MainHeader] hideSettingsWindow called at ${Date.now()}`);
 | 
				
			||||||
            window.require('electron').ipcRenderer.send('hide-window', name);
 | 
					            window.require('electron').ipcRenderer.send('hide-settings-window');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cancelHideWindow(name) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    renderShortcut(accelerator) {
 | 
					    renderShortcut(accelerator) {
 | 
				
			||||||
        if (!accelerator) return html``;
 | 
					        if (!accelerator) return html``;
 | 
				
			||||||
@ -600,7 +395,7 @@ export class MainHeader extends LitElement {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    render() {
 | 
					    render() {
 | 
				
			||||||
        return html`
 | 
					        return html`
 | 
				
			||||||
            <div class="header" @mousedown=${this.handleMouseDown}>
 | 
					            <div class="header">
 | 
				
			||||||
                <button 
 | 
					                <button 
 | 
				
			||||||
                    class="listen-button ${this.isSessionActive ? 'active' : ''}"
 | 
					                    class="listen-button ${this.isSessionActive ? 'active' : ''}"
 | 
				
			||||||
                    @click=${() => this.invoke(this.isSessionActive ? 'close-session' : 'toggle-feature', 'listen')}
 | 
					                    @click=${() => this.invoke(this.isSessionActive ? 'close-session' : 'toggle-feature', 'listen')}
 | 
				
			||||||
@ -646,8 +441,8 @@ export class MainHeader extends LitElement {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                <button 
 | 
					                <button 
 | 
				
			||||||
                    class="settings-button"
 | 
					                    class="settings-button"
 | 
				
			||||||
                    @mouseenter=${(e) => this.showWindow('settings', e.currentTarget)}
 | 
					                    @mouseenter=${(e) => this.showSettingsWindow(e.currentTarget)}
 | 
				
			||||||
                    @mouseleave=${() => this.hideWindow('settings')}
 | 
					                    @mouseleave=${() => this.hideSettingsWindow()}
 | 
				
			||||||
                >
 | 
					                >
 | 
				
			||||||
                    <div class="settings-icon">
 | 
					                    <div class="settings-icon">
 | 
				
			||||||
                        <svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
 | 
					                        <svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
 | 
				
			||||||
 | 
				
			|||||||
@ -4,14 +4,13 @@ export class PermissionHeader extends LitElement {
 | 
				
			|||||||
    static styles = css`
 | 
					    static styles = css`
 | 
				
			||||||
        :host {
 | 
					        :host {
 | 
				
			||||||
            display: block;
 | 
					            display: block;
 | 
				
			||||||
            transform: translate3d(0, 0, 0);
 | 
					            transition: opacity 0.3s ease-in, transform 0.3s ease-in;
 | 
				
			||||||
            backface-visibility: hidden;
 | 
					            will-change: opacity, transform;
 | 
				
			||||||
            transition: opacity 0.25s ease-out;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        :host(.sliding-out) {
 | 
					        :host(.sliding-out) {
 | 
				
			||||||
            animation: slideOutUp 0.3s ease-in forwards;
 | 
					            opacity: 0;
 | 
				
			||||||
            will-change: opacity, transform;
 | 
					            transform: translateY(-20px);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        :host(.hidden) {
 | 
					        :host(.hidden) {
 | 
				
			||||||
@ -19,17 +18,6 @@ export class PermissionHeader extends LitElement {
 | 
				
			|||||||
            pointer-events: none;
 | 
					            pointer-events: none;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @keyframes slideOutUp {
 | 
					 | 
				
			||||||
            from {
 | 
					 | 
				
			||||||
                opacity: 1;
 | 
					 | 
				
			||||||
                transform: translateY(0);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            to {
 | 
					 | 
				
			||||||
                opacity: 0;
 | 
					 | 
				
			||||||
                transform: translateY(-20px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        * {
 | 
					        * {
 | 
				
			||||||
            font-family: 'Helvetica Neue', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
 | 
					            font-family: 'Helvetica Neue', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
 | 
				
			||||||
            cursor: default;
 | 
					            cursor: default;
 | 
				
			||||||
@ -38,6 +26,7 @@ export class PermissionHeader extends LitElement {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        .container {
 | 
					        .container {
 | 
				
			||||||
 | 
					            -webkit-app-region: drag;
 | 
				
			||||||
            width: 285px;
 | 
					            width: 285px;
 | 
				
			||||||
            height: 220px;
 | 
					            height: 220px;
 | 
				
			||||||
            padding: 18px 20px;
 | 
					            padding: 18px 20px;
 | 
				
			||||||
@ -67,6 +56,7 @@ export class PermissionHeader extends LitElement {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        .close-button {
 | 
					        .close-button {
 | 
				
			||||||
 | 
					            -webkit-app-region: no-drag;
 | 
				
			||||||
            position: absolute;
 | 
					            position: absolute;
 | 
				
			||||||
            top: 10px;
 | 
					            top: 10px;
 | 
				
			||||||
            right: 10px;
 | 
					            right: 10px;
 | 
				
			||||||
@ -157,6 +147,7 @@ export class PermissionHeader extends LitElement {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        .action-button {
 | 
					        .action-button {
 | 
				
			||||||
 | 
					            -webkit-app-region: no-drag;
 | 
				
			||||||
            width: 100%;
 | 
					            width: 100%;
 | 
				
			||||||
            height: 34px;
 | 
					            height: 34px;
 | 
				
			||||||
            background: rgba(255, 255, 255, 0.2);
 | 
					            background: rgba(255, 255, 255, 0.2);
 | 
				
			||||||
@ -198,6 +189,7 @@ export class PermissionHeader extends LitElement {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        .continue-button {
 | 
					        .continue-button {
 | 
				
			||||||
 | 
					            -webkit-app-region: no-drag;
 | 
				
			||||||
            width: 100%;
 | 
					            width: 100%;
 | 
				
			||||||
            height: 34px;
 | 
					            height: 34px;
 | 
				
			||||||
            background: rgba(34, 197, 94, 0.8);
 | 
					            background: rgba(34, 197, 94, 0.8);
 | 
				
			||||||
@ -237,30 +229,6 @@ export class PermissionHeader extends LitElement {
 | 
				
			|||||||
            background: rgba(255, 255, 255, 0.2);
 | 
					            background: rgba(255, 255, 255, 0.2);
 | 
				
			||||||
            cursor: not-allowed;
 | 
					            cursor: not-allowed;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* ────────────────[ GLASS BYPASS ]─────────────── */
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .container,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .action-button,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .continue-button,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .close-button {
 | 
					 | 
				
			||||||
            background: transparent !important;
 | 
					 | 
				
			||||||
            border: none !important;
 | 
					 | 
				
			||||||
            box-shadow: none !important;
 | 
					 | 
				
			||||||
            filter: none !important;
 | 
					 | 
				
			||||||
            backdrop-filter: none !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .container::after,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .action-button::after,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .continue-button::after {
 | 
					 | 
				
			||||||
            display: none !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .action-button:hover,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .continue-button:hover,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .close-button:hover {
 | 
					 | 
				
			||||||
            background: transparent !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    `;
 | 
					    `;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static properties = {
 | 
					    static properties = {
 | 
				
			||||||
@ -276,9 +244,6 @@ export class PermissionHeader extends LitElement {
 | 
				
			|||||||
        this.screenGranted = 'unknown';
 | 
					        this.screenGranted = 'unknown';
 | 
				
			||||||
        this.isChecking = false;
 | 
					        this.isChecking = false;
 | 
				
			||||||
        this.continueCallback = null;
 | 
					        this.continueCallback = null;
 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.handleMouseMove = this.handleMouseMove.bind(this);
 | 
					 | 
				
			||||||
        this.handleMouseUp = this.handleMouseUp.bind(this);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async connectedCallback() {
 | 
					    async connectedCallback() {
 | 
				
			||||||
@ -298,61 +263,6 @@ export class PermissionHeader extends LitElement {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async handleMouseDown(e) {
 | 
					 | 
				
			||||||
        if (e.target.tagName === 'BUTTON') {
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        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);
 | 
					 | 
				
			||||||
        window.addEventListener('mouseup', this.handleMouseUp, { once: 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);
 | 
					 | 
				
			||||||
        this.dragState = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (wasDragged) {
 | 
					 | 
				
			||||||
            this.wasJustDragged = true;
 | 
					 | 
				
			||||||
            setTimeout(() => {
 | 
					 | 
				
			||||||
                this.wasJustDragged = false;
 | 
					 | 
				
			||||||
            }, 200);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    async checkPermissions() {
 | 
					    async checkPermissions() {
 | 
				
			||||||
        if (!window.require || this.isChecking) return;
 | 
					        if (!window.require || this.isChecking) return;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
@ -390,7 +300,7 @@ export class PermissionHeader extends LitElement {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async handleMicrophoneClick() {
 | 
					    async handleMicrophoneClick() {
 | 
				
			||||||
        if (!window.require || this.microphoneGranted === 'granted' || this.wasJustDragged) return;
 | 
					        if (!window.require || this.microphoneGranted === 'granted') return;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        console.log('[PermissionHeader] Requesting microphone permission...');
 | 
					        console.log('[PermissionHeader] Requesting microphone permission...');
 | 
				
			||||||
        const { ipcRenderer } = window.require('electron');
 | 
					        const { ipcRenderer } = window.require('electron');
 | 
				
			||||||
@ -423,7 +333,7 @@ export class PermissionHeader extends LitElement {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async handleScreenClick() {
 | 
					    async handleScreenClick() {
 | 
				
			||||||
        if (!window.require || this.screenGranted === 'granted' || this.wasJustDragged) return;
 | 
					        if (!window.require || this.screenGranted === 'granted') return;
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        console.log('[PermissionHeader] Checking screen recording permission...');
 | 
					        console.log('[PermissionHeader] Checking screen recording permission...');
 | 
				
			||||||
        const { ipcRenderer } = window.require('electron');
 | 
					        const { ipcRenderer } = window.require('electron');
 | 
				
			||||||
@ -453,8 +363,7 @@ export class PermissionHeader extends LitElement {
 | 
				
			|||||||
    async handleContinue() {
 | 
					    async handleContinue() {
 | 
				
			||||||
        if (this.continueCallback && 
 | 
					        if (this.continueCallback && 
 | 
				
			||||||
            this.microphoneGranted === 'granted' && 
 | 
					            this.microphoneGranted === 'granted' && 
 | 
				
			||||||
            this.screenGranted === 'granted' && 
 | 
					            this.screenGranted === 'granted') {
 | 
				
			||||||
            !this.wasJustDragged) {
 | 
					 | 
				
			||||||
            // Mark permissions as completed
 | 
					            // Mark permissions as completed
 | 
				
			||||||
            if (window.require) {
 | 
					            if (window.require) {
 | 
				
			||||||
                const { ipcRenderer } = window.require('electron');
 | 
					                const { ipcRenderer } = window.require('electron');
 | 
				
			||||||
@ -481,7 +390,7 @@ export class PermissionHeader extends LitElement {
 | 
				
			|||||||
        const allGranted = this.microphoneGranted === 'granted' && this.screenGranted === 'granted';
 | 
					        const allGranted = this.microphoneGranted === 'granted' && this.screenGranted === 'granted';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return html`
 | 
					        return html`
 | 
				
			||||||
            <div class="container" @mousedown=${this.handleMouseDown}>
 | 
					            <div class="container">
 | 
				
			||||||
                <button class="close-button" @click=${this.handleClose} title="Close application">
 | 
					                <button class="close-button" @click=${this.handleClose} title="Close application">
 | 
				
			||||||
                    <svg width="8" height="8" viewBox="0 0 10 10" fill="currentColor">
 | 
					                    <svg width="8" height="8" viewBox="0 0 10 10" fill="currentColor">
 | 
				
			||||||
                        <path d="M1 1L9 9M9 1L1 9" stroke="currentColor" stroke-width="1.2" />
 | 
					                        <path d="M1 1L9 9M9 1L1 9" stroke="currentColor" stroke-width="1.2" />
 | 
				
			||||||
 | 
				
			|||||||
@ -136,16 +136,6 @@ export class PickleGlassApp extends LitElement {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    requestWindowResize() {
 | 
					 | 
				
			||||||
        if (window.require) {
 | 
					 | 
				
			||||||
            const { ipcRenderer } = window.require('electron');
 | 
					 | 
				
			||||||
            ipcRenderer.invoke('resize-window', {
 | 
					 | 
				
			||||||
                isMainViewVisible: this.isMainViewVisible,
 | 
					 | 
				
			||||||
                view: this.currentView,
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    setStatus(text) {
 | 
					    setStatus(text) {
 | 
				
			||||||
        this.statusText = text;
 | 
					        this.statusText = text;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -237,63 +237,62 @@
 | 
				
			|||||||
        <script>
 | 
					        <script>
 | 
				
			||||||
            window.addEventListener('DOMContentLoaded', () => {
 | 
					            window.addEventListener('DOMContentLoaded', () => {
 | 
				
			||||||
                const app = document.getElementById('pickle-glass');
 | 
					                const app = document.getElementById('pickle-glass');
 | 
				
			||||||
                let animationTimeout = null;
 | 
					        
 | 
				
			||||||
 | 
					 | 
				
			||||||
                if (window.require) {
 | 
					                if (window.require) {
 | 
				
			||||||
                    const { ipcRenderer } = window.require('electron');
 | 
					                    const { ipcRenderer } = window.require('electron');
 | 
				
			||||||
                    
 | 
					        
 | 
				
			||||||
 | 
					                    // --- REFACTORED: Event-driven animation handling ---
 | 
				
			||||||
 | 
					                    app.addEventListener('animationend', (event) => {
 | 
				
			||||||
 | 
					                        // 숨김 애니메이션이 끝나면 main 프로세스에 알려 창을 실제로 숨깁니다.
 | 
				
			||||||
 | 
					                        if (event.animationName === 'slideUpToHeader' || event.animationName === 'settingsCollapseToButton') {
 | 
				
			||||||
 | 
					                            console.log(`Animation finished: ${event.animationName}. Notifying main process.`);
 | 
				
			||||||
 | 
					                            ipcRenderer.send('animation-finished');
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					                            // 완료 후 애니메이션 클래스 정리
 | 
				
			||||||
 | 
					                            app.classList.remove('window-sliding-up', 'settings-window-hide');
 | 
				
			||||||
 | 
					                            app.classList.add('window-hidden');
 | 
				
			||||||
 | 
					                        } else if (event.animationName === 'slideDownFromHeader' || event.animationName === 'settingsPopFromButton') {
 | 
				
			||||||
 | 
					                             // 보이기 애니메이션 완료 후 클래스 정리
 | 
				
			||||||
 | 
					                            app.classList.remove('window-sliding-down', 'settings-window-show');
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
                    ipcRenderer.on('window-show-animation', () => {
 | 
					                    ipcRenderer.on('window-show-animation', () => {
 | 
				
			||||||
                        console.log('Starting window show animation');
 | 
					                        console.log('Starting window show animation');
 | 
				
			||||||
                        app.classList.remove('window-hidden', 'window-sliding-up', 'settings-window-hide');
 | 
					                        app.classList.remove('window-hidden', 'window-sliding-up', 'settings-window-hide');
 | 
				
			||||||
                        app.classList.add('window-sliding-down');
 | 
					                        app.classList.add('window-sliding-down');
 | 
				
			||||||
                        
 | 
					 | 
				
			||||||
                        if (animationTimeout) clearTimeout(animationTimeout);
 | 
					 | 
				
			||||||
                        animationTimeout = setTimeout(() => {
 | 
					 | 
				
			||||||
                            app.classList.remove('window-sliding-down');
 | 
					 | 
				
			||||||
                        }, 120);
 | 
					 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    
 | 
					        
 | 
				
			||||||
                    ipcRenderer.on('window-hide-animation', () => {
 | 
					                    ipcRenderer.on('window-hide-animation', () => {
 | 
				
			||||||
                        console.log('Starting window hide animation');
 | 
					                        console.log('Starting window hide animation');
 | 
				
			||||||
                        app.classList.remove('window-sliding-down', 'settings-window-show');
 | 
					                        app.classList.remove('window-sliding-down', 'settings-window-show');
 | 
				
			||||||
                        app.classList.add('window-sliding-up');
 | 
					                        app.classList.add('window-sliding-up');
 | 
				
			||||||
                        
 | 
					 | 
				
			||||||
                        if (animationTimeout) clearTimeout(animationTimeout);
 | 
					 | 
				
			||||||
                        animationTimeout = setTimeout(() => {
 | 
					 | 
				
			||||||
                            app.classList.remove('window-sliding-up');
 | 
					 | 
				
			||||||
                            app.classList.add('window-hidden');
 | 
					 | 
				
			||||||
                        }, 100);
 | 
					 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                    
 | 
					        
 | 
				
			||||||
                    ipcRenderer.on('settings-window-hide-animation', () => {
 | 
					                    ipcRenderer.on('settings-window-hide-animation', () => {
 | 
				
			||||||
                        console.log('Starting settings window hide animation');
 | 
					                        console.log('Starting settings window hide animation');
 | 
				
			||||||
                        app.classList.remove('window-sliding-down', 'settings-window-show');
 | 
					                        app.classList.remove('window-sliding-down', 'settings-window-show');
 | 
				
			||||||
                        app.classList.add('settings-window-hide');
 | 
					                        app.classList.add('settings-window-hide');
 | 
				
			||||||
                        
 | 
					 | 
				
			||||||
                        if (animationTimeout) clearTimeout(animationTimeout);
 | 
					 | 
				
			||||||
                        animationTimeout = setTimeout(() => {
 | 
					 | 
				
			||||||
                            app.classList.remove('settings-window-hide');
 | 
					 | 
				
			||||||
                            app.classList.add('window-hidden');
 | 
					 | 
				
			||||||
                        }, 100);
 | 
					 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					                    // --- UNCHANGED: Existing logic for listen window movement ---
 | 
				
			||||||
                    ipcRenderer.on('listen-window-move-to-center', () => {
 | 
					                    ipcRenderer.on('listen-window-move-to-center', () => {
 | 
				
			||||||
                        console.log('Moving listen window to center');
 | 
					                        console.log('Moving listen window to center');
 | 
				
			||||||
                        app.classList.add('listen-window-moving');
 | 
					                        app.classList.add('listen-window-moving');
 | 
				
			||||||
                        app.classList.remove('listen-window-left');
 | 
					                        app.classList.remove('listen-window-left');
 | 
				
			||||||
                        app.classList.add('listen-window-center');
 | 
					                        app.classList.add('listen-window-center');
 | 
				
			||||||
                        
 | 
					        
 | 
				
			||||||
                        setTimeout(() => {
 | 
					                        setTimeout(() => {
 | 
				
			||||||
                            app.classList.remove('listen-window-moving');
 | 
					                            app.classList.remove('listen-window-moving');
 | 
				
			||||||
                        }, 350);
 | 
					                        }, 350);
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
                    ipcRenderer.on('listen-window-move-to-left', () => {
 | 
					                    ipcRenderer.on('listen-window-move-to-left', () => {
 | 
				
			||||||
                        console.log('Moving listen window to left');
 | 
					                        console.log('Moving listen window to left');
 | 
				
			||||||
                        app.classList.add('listen-window-moving');
 | 
					                        app.classList.add('listen-window-moving');
 | 
				
			||||||
                        app.classList.remove('listen-window-center');
 | 
					                        app.classList.remove('listen-window-center');
 | 
				
			||||||
                        app.classList.add('listen-window-left');
 | 
					                        app.classList.add('listen-window-left');
 | 
				
			||||||
                        
 | 
					        
 | 
				
			||||||
                        setTimeout(() => {
 | 
					                        setTimeout(() => {
 | 
				
			||||||
                            app.classList.remove('listen-window-moving');
 | 
					                            app.classList.remove('listen-window-moving');
 | 
				
			||||||
                        }, 350);
 | 
					                        }, 350);
 | 
				
			||||||
@ -305,6 +304,11 @@
 | 
				
			|||||||
            const params = new URLSearchParams(window.location.search);
 | 
					            const params = new URLSearchParams(window.location.search);
 | 
				
			||||||
            if (params.get('glass') === 'true') {
 | 
					            if (params.get('glass') === 'true') {
 | 
				
			||||||
                document.body.classList.add('has-glass');
 | 
					                document.body.classList.add('has-glass');
 | 
				
			||||||
 | 
					                // --- ADDED: Link to centralized glass-bypass styles ---
 | 
				
			||||||
 | 
					                const link = document.createElement('link');
 | 
				
			||||||
 | 
					                link.rel = 'stylesheet';
 | 
				
			||||||
 | 
					                link.href = '../common/styles/glass-bypass.css';
 | 
				
			||||||
 | 
					                document.head.appendChild(link);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        </script>
 | 
					        </script>
 | 
				
			||||||
    </body>
 | 
					    </body>
 | 
				
			||||||
 | 
				
			|||||||
@ -22,6 +22,11 @@
 | 
				
			|||||||
            const params = new URLSearchParams(window.location.search);
 | 
					            const params = new URLSearchParams(window.location.search);
 | 
				
			||||||
            if (params.get('glass') === 'true') {
 | 
					            if (params.get('glass') === 'true') {
 | 
				
			||||||
                document.body.classList.add('has-glass');
 | 
					                document.body.classList.add('has-glass');
 | 
				
			||||||
 | 
					                // --- ADDED: Link to centralized glass-bypass styles ---
 | 
				
			||||||
 | 
					                const link = document.createElement('link');
 | 
				
			||||||
 | 
					                link.rel = 'stylesheet';
 | 
				
			||||||
 | 
					                link.href = '../common/styles/glass-bypass.css';
 | 
				
			||||||
 | 
					                document.head.appendChild(link);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        </script>
 | 
					        </script>
 | 
				
			||||||
    </body>
 | 
					    </body>
 | 
				
			||||||
 | 
				
			|||||||
@ -213,13 +213,21 @@ class ModelStateService {
 | 
				
			|||||||
        const llmModels = PROVIDERS['openai-glass']?.llmModels;
 | 
					        const llmModels = PROVIDERS['openai-glass']?.llmModels;
 | 
				
			||||||
        const sttModels = PROVIDERS['openai-glass']?.sttModels;
 | 
					        const sttModels = PROVIDERS['openai-glass']?.sttModels;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!this.state.selectedModels.llm && llmModels?.length > 0) {
 | 
					        // When logging in with Pickle, prioritize Pickle's models over existing selections
 | 
				
			||||||
 | 
					        if (virtualKey && llmModels?.length > 0) {
 | 
				
			||||||
            this.state.selectedModels.llm = llmModels[0].id;
 | 
					            this.state.selectedModels.llm = llmModels[0].id;
 | 
				
			||||||
 | 
					            console.log(`[ModelStateService] Prioritized Pickle LLM model: ${llmModels[0].id}`);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (!this.state.selectedModels.stt && sttModels?.length > 0) {
 | 
					        if (virtualKey && sttModels?.length > 0) {
 | 
				
			||||||
            this.state.selectedModels.stt = sttModels[0].id;
 | 
					            this.state.selectedModels.stt = sttModels[0].id;
 | 
				
			||||||
 | 
					            console.log(`[ModelStateService] Prioritized Pickle STT model: ${sttModels[0].id}`);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        this._autoSelectAvailableModels();
 | 
					        
 | 
				
			||||||
 | 
					        // If logging out (virtualKey is null), run auto-selection to find alternatives
 | 
				
			||||||
 | 
					        if (!virtualKey) {
 | 
				
			||||||
 | 
					            this._autoSelectAvailableModels();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        this._saveState();
 | 
					        this._saveState();
 | 
				
			||||||
        this._logCurrentSelection();
 | 
					        this._logCurrentSelection();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										12
									
								
								src/common/styles/glass-bypass.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/common/styles/glass-bypass.css
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					  이 파일은 body.has-glass 클래스가 적용되었을 때 모든 애니메이션, 트랜지션,
 | 
				
			||||||
 | 
					  배경, 테두리 등을 비활성화하여 깨끗한 투명 효과(Glass)를 보장합니다.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					body.has-glass * {
 | 
				
			||||||
 | 
					    animation: none !important;
 | 
				
			||||||
 | 
					    transition: none !important;
 | 
				
			||||||
 | 
					    background: transparent !important;
 | 
				
			||||||
 | 
					    border: none !important;
 | 
				
			||||||
 | 
					    box-shadow: none !important;
 | 
				
			||||||
 | 
					    backdrop-filter: none !important;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -78,13 +78,6 @@ function updateLayout() {
 | 
				
			|||||||
let movementManager = null;
 | 
					let movementManager = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const featureWindows = ['listen','ask','settings'];
 | 
					 | 
				
			||||||
// const featureWindows = ['listen','ask','settings','shortcut-settings'];
 | 
					 | 
				
			||||||
function isAllowed(name) {
 | 
					 | 
				
			||||||
    if (name === 'header') return true;
 | 
					 | 
				
			||||||
    return featureWindows.includes(name) && currentHeaderState === 'main';
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function createFeatureWindows(header, namesToCreate) {
 | 
					function createFeatureWindows(header, namesToCreate) {
 | 
				
			||||||
    // if (windowPool.has('listen')) return;
 | 
					    // if (windowPool.has('listen')) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -305,6 +298,7 @@ function createFeatureWindows(header, namesToCreate) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function destroyFeatureWindows() {
 | 
					function destroyFeatureWindows() {
 | 
				
			||||||
 | 
					    const featureWindows = ['listen','ask','settings','shortcut-settings'];
 | 
				
			||||||
    if (settingsHideTimer) {
 | 
					    if (settingsHideTimer) {
 | 
				
			||||||
        clearTimeout(settingsHideTimer);
 | 
					        clearTimeout(settingsHideTimer);
 | 
				
			||||||
        settingsHideTimer = null;
 | 
					        settingsHideTimer = null;
 | 
				
			||||||
@ -337,78 +331,35 @@ function getDisplayById(displayId) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function toggleAllWindowsVisibility(movementManager) {
 | 
					function toggleAllWindowsVisibility() {
 | 
				
			||||||
    const header = windowPool.get('header');
 | 
					    const header = windowPool.get('header');
 | 
				
			||||||
    if (!header) return;
 | 
					    if (!header) return;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
    if (header.isVisible()) {
 | 
					    if (header.isVisible()) {
 | 
				
			||||||
        console.log('[Visibility] Smart hiding - calculating nearest edge');
 | 
					      lastVisibleWindows.clear();
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
        const headerBounds = header.getBounds();
 | 
					      windowPool.forEach((win, name) => {
 | 
				
			||||||
        const display = screen.getPrimaryDisplay();
 | 
					        if (win && !win.isDestroyed() && win.isVisible()) {
 | 
				
			||||||
        const { width: screenWidth, height: screenHeight } = display.workAreaSize;
 | 
					          lastVisibleWindows.add(name);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        const centerX = headerBounds.x + headerBounds.width / 2;
 | 
					      });
 | 
				
			||||||
        const centerY = headerBounds.y + headerBounds.height / 2;
 | 
					  
 | 
				
			||||||
 | 
					      lastVisibleWindows.forEach(name => {
 | 
				
			||||||
        const distances = {
 | 
					        if (name === 'header') return;
 | 
				
			||||||
            top: centerY,
 | 
					        const win = windowPool.get(name);
 | 
				
			||||||
            bottom: screenHeight - centerY,
 | 
					        if (win && !win.isDestroyed()) win.hide();
 | 
				
			||||||
            left: centerX,
 | 
					      });
 | 
				
			||||||
            right: screenWidth - centerX,
 | 
					      header.hide();
 | 
				
			||||||
        };
 | 
					  
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
        const nearestEdge = Object.keys(distances).reduce((nearest, edge) => (distances[edge] < distances[nearest] ? edge : nearest));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        console.log(`[Visibility] Nearest edge: ${nearestEdge} (distance: ${distances[nearestEdge].toFixed(1)}px)`);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        lastVisibleWindows.clear();
 | 
					 | 
				
			||||||
        lastVisibleWindows.add('header');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        windowPool.forEach((win, name) => {
 | 
					 | 
				
			||||||
            if (win.isVisible()) {
 | 
					 | 
				
			||||||
                lastVisibleWindows.add(name);
 | 
					 | 
				
			||||||
                if (name !== 'header') {
 | 
					 | 
				
			||||||
                    // win.webContents.send('window-hide-animation');
 | 
					 | 
				
			||||||
                    // setTimeout(() => {
 | 
					 | 
				
			||||||
                    //     if (!win.isDestroyed()) {
 | 
					 | 
				
			||||||
                    //         win.hide();
 | 
					 | 
				
			||||||
                    //     }
 | 
					 | 
				
			||||||
                    // }, 200);
 | 
					 | 
				
			||||||
                    win.hide();
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        console.log('[Visibility] Visible windows before hide:', Array.from(lastVisibleWindows));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        movementManager.hideToEdge(nearestEdge, () => {
 | 
					 | 
				
			||||||
            header.hide();
 | 
					 | 
				
			||||||
            console.log('[Visibility] Smart hide completed');
 | 
					 | 
				
			||||||
        }, { instant: true });
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        console.log('[Visibility] Smart showing from hidden position');
 | 
					 | 
				
			||||||
        console.log('[Visibility] Restoring windows:', Array.from(lastVisibleWindows));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        header.show();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        movementManager.showFromEdge(() => {
 | 
					 | 
				
			||||||
            lastVisibleWindows.forEach(name => {
 | 
					 | 
				
			||||||
                if (name === 'header') return;
 | 
					 | 
				
			||||||
                const win = windowPool.get(name);
 | 
					 | 
				
			||||||
                if (win && !win.isDestroyed()) {
 | 
					 | 
				
			||||||
                    win.show();
 | 
					 | 
				
			||||||
                    win.webContents.send('window-show-animation');
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            setImmediate(updateLayout);
 | 
					 | 
				
			||||||
            setTimeout(updateLayout, 120);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            console.log('[Visibility] Smart show completed');
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					  
 | 
				
			||||||
 | 
					    lastVisibleWindows.forEach(name => {
 | 
				
			||||||
 | 
					      const win = windowPool.get(name);
 | 
				
			||||||
 | 
					      if (win && !win.isDestroyed())
 | 
				
			||||||
 | 
					        win.show();
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function createWindows() {
 | 
					function createWindows() {
 | 
				
			||||||
@ -470,6 +421,7 @@ function createWindows() {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    windowPool.set('header', header);
 | 
					    windowPool.set('header', header);
 | 
				
			||||||
 | 
					    header.on('moved', updateLayout);
 | 
				
			||||||
    layoutManager = new WindowLayoutManager(windowPool);
 | 
					    layoutManager = new WindowLayoutManager(windowPool);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    header.webContents.once('dom-ready', () => {
 | 
					    header.webContents.once('dom-ready', () => {
 | 
				
			||||||
@ -513,7 +465,7 @@ function createWindows() {
 | 
				
			|||||||
        updateLayout();
 | 
					        updateLayout();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ipcMain.handle('toggle-all-windows-visibility', () => toggleAllWindowsVisibility(movementManager));
 | 
					    ipcMain.handle('toggle-all-windows-visibility', () => toggleAllWindowsVisibility());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ipcMain.handle('toggle-feature', async (event, featureName) => {
 | 
					    ipcMain.handle('toggle-feature', async (event, featureName) => {
 | 
				
			||||||
        if (!windowPool.get(featureName) && currentHeaderState === 'main') {
 | 
					        if (!windowPool.get(featureName) && currentHeaderState === 'main') {
 | 
				
			||||||
@ -596,13 +548,6 @@ function createWindows() {
 | 
				
			|||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        console.log('[WindowManager] No response found, closing window');
 | 
					                        console.log('[WindowManager] No response found, closing window');
 | 
				
			||||||
                        askWindow.webContents.send('window-hide-animation');
 | 
					                        askWindow.webContents.send('window-hide-animation');
 | 
				
			||||||
 | 
					 | 
				
			||||||
                        setTimeout(() => {
 | 
					 | 
				
			||||||
                            if (!askWindow.isDestroyed()) {
 | 
					 | 
				
			||||||
                                askWindow.hide();
 | 
					 | 
				
			||||||
                                updateLayout();
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        }, 250);
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                } catch (error) {
 | 
					                } catch (error) {
 | 
				
			||||||
                    console.error('[WindowManager] Error checking Ask window state:', error);
 | 
					                    console.error('[WindowManager] Error checking Ask window state:', error);
 | 
				
			||||||
@ -631,13 +576,6 @@ function createWindows() {
 | 
				
			|||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        windowToToggle.webContents.send('window-hide-animation');
 | 
					                        windowToToggle.webContents.send('window-hide-animation');
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
                    setTimeout(() => {
 | 
					 | 
				
			||||||
                        if (!windowToToggle.isDestroyed()) {
 | 
					 | 
				
			||||||
                            windowToToggle.hide();
 | 
					 | 
				
			||||||
                            updateLayout();
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }, 250);
 | 
					 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    try {
 | 
					                    try {
 | 
				
			||||||
                        windowToToggle.show();
 | 
					                        windowToToggle.show();
 | 
				
			||||||
@ -773,9 +711,17 @@ function setupIpcHandlers(movementManager) {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ipcMain.on('show-window', (event, args) => {
 | 
					    ipcMain.on('animation-finished', (event) => {
 | 
				
			||||||
        const { name, bounds } = typeof args === 'object' && args !== null ? args : { name: args, bounds: null };
 | 
					        const win = BrowserWindow.fromWebContents(event.sender);
 | 
				
			||||||
        const win = windowPool.get(name);
 | 
					        if (win && !win.isDestroyed()) {
 | 
				
			||||||
 | 
					            console.log(`[WindowManager] Hiding window after animation.`);
 | 
				
			||||||
 | 
					            win.hide();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ipcMain.on('show-settings-window', (event, bounds) => {
 | 
				
			||||||
 | 
					        if (!bounds) return;  
 | 
				
			||||||
 | 
					        const win = windowPool.get('settings');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (win && !win.isDestroyed()) {
 | 
					        if (win && !win.isDestroyed()) {
 | 
				
			||||||
            if (settingsHideTimer) {
 | 
					            if (settingsHideTimer) {
 | 
				
			||||||
@ -783,78 +729,60 @@ function setupIpcHandlers(movementManager) {
 | 
				
			|||||||
                settingsHideTimer = null;
 | 
					                settingsHideTimer = null;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (name === 'settings') {
 | 
					            // Adjust position based on button bounds
 | 
				
			||||||
                // Adjust position based on button bounds
 | 
					            const header = windowPool.get('header');
 | 
				
			||||||
                const header = windowPool.get('header');
 | 
					            const headerBounds = header?.getBounds() ?? { x: 0, y: 0 };
 | 
				
			||||||
                const headerBounds = header?.getBounds() ?? { x: 0, y: 0 };
 | 
					            const settingsBounds = win.getBounds();
 | 
				
			||||||
                const settingsBounds = win.getBounds();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                const disp = getCurrentDisplay(header);
 | 
					            const disp = getCurrentDisplay(header);
 | 
				
			||||||
                const { x: waX, y: waY, width: waW, height: waH } = disp.workArea;
 | 
					            const { x: waX, y: waY, width: waW, height: waH } = disp.workArea;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                let x = Math.round(headerBounds.x + (bounds?.x ?? 0) + (bounds?.width ?? 0) / 2 - settingsBounds.width / 2);
 | 
					            let x = Math.round(headerBounds.x + (bounds?.x ?? 0) + (bounds?.width ?? 0) / 2 - settingsBounds.width / 2);
 | 
				
			||||||
                let y = Math.round(headerBounds.y + (bounds?.y ?? 0) + (bounds?.height ?? 0) + 31);
 | 
					            let y = Math.round(headerBounds.y + (bounds?.y ?? 0) + (bounds?.height ?? 0) + 31);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                x = Math.max(waX + 10, Math.min(waX + waW - settingsBounds.width - 10, x));
 | 
					            x = Math.max(waX + 10, Math.min(waX + waW - settingsBounds.width - 10, x));
 | 
				
			||||||
                y = Math.max(waY + 10, Math.min(waY + waH - settingsBounds.height - 10, y));
 | 
					            y = Math.max(waY + 10, Math.min(waY + waH - settingsBounds.height - 10, y));
 | 
				
			||||||
 | 
					 | 
				
			||||||
                win.setBounds({ x, y });
 | 
					 | 
				
			||||||
                win.__lockedByButton = true;
 | 
					 | 
				
			||||||
                console.log(`[WindowManager] Positioning settings window at (${x}, ${y}) based on button bounds.`);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            win.setBounds({ x, y });
 | 
				
			||||||
 | 
					            win.__lockedByButton = true;
 | 
				
			||||||
 | 
					            console.log(`[WindowManager] Positioning settings window at (${x}, ${y}) based on button bounds.`);
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
            win.show();
 | 
					            win.show();
 | 
				
			||||||
            win.moveTop();
 | 
					            win.moveTop();
 | 
				
			||||||
 | 
					            win.setAlwaysOnTop(true);
 | 
				
			||||||
            if (name === 'settings') {
 | 
					 | 
				
			||||||
                win.setAlwaysOnTop(true);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            // updateLayout();
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ipcMain.on('hide-window', (event, name) => {
 | 
					    ipcMain.on('hide-settings-window', (event) => {
 | 
				
			||||||
        const window = windowPool.get(name);
 | 
					        const window = windowPool.get("settings");
 | 
				
			||||||
        if (window && !window.isDestroyed()) {
 | 
					        if (window && !window.isDestroyed()) {
 | 
				
			||||||
            if (name === 'settings') {
 | 
					            if (settingsHideTimer) {
 | 
				
			||||||
                if (settingsHideTimer) {
 | 
					                clearTimeout(settingsHideTimer);
 | 
				
			||||||
                    clearTimeout(settingsHideTimer);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                settingsHideTimer = setTimeout(() => {
 | 
					 | 
				
			||||||
                    // window.setAlwaysOnTop(false);
 | 
					 | 
				
			||||||
                    // window.hide();
 | 
					 | 
				
			||||||
                    if (window && !window.isDestroyed()) {
 | 
					 | 
				
			||||||
                        window.setAlwaysOnTop(false);
 | 
					 | 
				
			||||||
                        window.hide();
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    settingsHideTimer = null;
 | 
					 | 
				
			||||||
                }, 200);
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                window.hide();
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            settingsHideTimer = setTimeout(() => {
 | 
				
			||||||
 | 
					                if (window && !window.isDestroyed()) {
 | 
				
			||||||
 | 
					                    window.setAlwaysOnTop(false);
 | 
				
			||||||
 | 
					                    window.hide();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                settingsHideTimer = null;
 | 
				
			||||||
 | 
					            }, 200);
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
            window.__lockedByButton = false;
 | 
					            window.__lockedByButton = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ipcMain.on('cancel-hide-window', (event, name) => {
 | 
					    ipcMain.on('cancel-hide-settings-window', (event) => {
 | 
				
			||||||
        if (name === 'settings' && settingsHideTimer) {
 | 
					        if (settingsHideTimer) {
 | 
				
			||||||
            clearTimeout(settingsHideTimer);
 | 
					            clearTimeout(settingsHideTimer);
 | 
				
			||||||
            settingsHideTimer = null;
 | 
					            settingsHideTimer = null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ipcMain.handle('hide-all', () => {
 | 
					 | 
				
			||||||
        windowPool.forEach(win => {
 | 
					 | 
				
			||||||
            if (win.isFocused()) return;
 | 
					 | 
				
			||||||
            win.hide();
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ipcMain.handle('quit-application', () => {
 | 
					    ipcMain.handle('quit-application', () => {
 | 
				
			||||||
        app.quit();
 | 
					        app.quit();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ipcMain.handle('is-window-visible', (event, windowName) => {
 | 
					    ipcMain.handle('is-ask-window-visible', (event, windowName) => {
 | 
				
			||||||
        const window = windowPool.get(windowName);
 | 
					        const window = windowPool.get(windowName);
 | 
				
			||||||
        if (window && !window.isDestroyed()) {
 | 
					        if (window && !window.isDestroyed()) {
 | 
				
			||||||
            return window.isVisible();
 | 
					            return window.isVisible();
 | 
				
			||||||
@ -888,15 +816,6 @@ function setupIpcHandlers(movementManager) {
 | 
				
			|||||||
            destroyFeatureWindows();
 | 
					            destroyFeatureWindows();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        loadAndRegisterShortcuts(movementManager);
 | 
					        loadAndRegisterShortcuts(movementManager);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (const [name, win] of windowPool) {
 | 
					 | 
				
			||||||
            if (!isAllowed(name) && !win.isDestroyed()) {
 | 
					 | 
				
			||||||
                win.hide();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if (isAllowed(name) && win.isVisible()) {
 | 
					 | 
				
			||||||
                win.show();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ipcMain.on('update-keybinds', (event, newKeybinds) => {
 | 
					    ipcMain.on('update-keybinds', (event, newKeybinds) => {
 | 
				
			||||||
@ -969,9 +888,6 @@ function setupIpcHandlers(movementManager) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    setupApiKeyIPC();
 | 
					    setupApiKeyIPC();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ipcMain.handle('resize-window', () => {});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ipcMain.handle('resize-for-view', () => {});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ipcMain.handle('resize-header-window', (event, { width, height }) => {
 | 
					    ipcMain.handle('resize-header-window', (event, { width, height }) => {
 | 
				
			||||||
        const header = windowPool.get('header');
 | 
					        const header = windowPool.get('header');
 | 
				
			||||||
@ -1024,74 +940,19 @@ function setupIpcHandlers(movementManager) {
 | 
				
			|||||||
        return { success: false, error: 'Header window not found' };
 | 
					        return { success: false, error: 'Header window not found' };
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ipcMain.on('header-animation-complete', (event, state) => {
 | 
					    ipcMain.on('header-animation-finished', (event, state) => {
 | 
				
			||||||
        const header = windowPool.get('header');
 | 
					        const header = windowPool.get('header');
 | 
				
			||||||
        if (!header) return;
 | 
					        if (!header || header.isDestroyed()) return;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
        if (state === 'hidden') {
 | 
					        if (state === 'hidden') {
 | 
				
			||||||
            header.hide();
 | 
					            header.hide();
 | 
				
			||||||
 | 
					            console.log('[WindowManager] Header hidden after animation.');
 | 
				
			||||||
        } else if (state === 'visible') {
 | 
					        } else if (state === 'visible') {
 | 
				
			||||||
            lastVisibleWindows.forEach(name => {
 | 
					            console.log('[WindowManager] Header shown after animation.');
 | 
				
			||||||
                if (name === 'header') return;
 | 
					 | 
				
			||||||
                const win = windowPool.get(name);
 | 
					 | 
				
			||||||
                if (win) win.show();
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            setImmediate(updateLayout);
 | 
					 | 
				
			||||||
            setTimeout(updateLayout, 120);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ipcMain.handle('get-header-position', () => {
 | 
					 | 
				
			||||||
        const header = windowPool.get('header');
 | 
					 | 
				
			||||||
        if (header) {
 | 
					 | 
				
			||||||
            const [x, y] = header.getPosition();
 | 
					 | 
				
			||||||
            return { x, y };
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return { x: 0, y: 0 };
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ipcMain.handle('move-header', (event, newX, newY) => {
 | 
					 | 
				
			||||||
        const header = windowPool.get('header');
 | 
					 | 
				
			||||||
        if (header) {
 | 
					 | 
				
			||||||
            const currentY = newY !== undefined ? newY : header.getBounds().y;
 | 
					 | 
				
			||||||
            header.setPosition(newX, currentY, false);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            updateLayout();
 | 
					            updateLayout();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ipcMain.handle('move-header-to', (event, newX, newY) => {
 | 
					 | 
				
			||||||
        const header = windowPool.get('header');
 | 
					 | 
				
			||||||
        if (header) {
 | 
					 | 
				
			||||||
            const targetDisplay = screen.getDisplayNearestPoint({ x: newX, y: newY });
 | 
					 | 
				
			||||||
            const { x: workAreaX, y: workAreaY, width, height } = targetDisplay.workArea;
 | 
					 | 
				
			||||||
            const headerBounds = header.getBounds();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Only clamp if the new position would actually go out of bounds
 | 
					 | 
				
			||||||
            // This prevents progressive restriction of movement
 | 
					 | 
				
			||||||
            let clampedX = newX;
 | 
					 | 
				
			||||||
            let clampedY = newY;
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            // Check if we need to clamp X position
 | 
					 | 
				
			||||||
            if (newX < workAreaX) {
 | 
					 | 
				
			||||||
                clampedX = workAreaX;
 | 
					 | 
				
			||||||
            } else if (newX + headerBounds.width > workAreaX + width) {
 | 
					 | 
				
			||||||
                clampedX = workAreaX + width - headerBounds.width;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            // Check if we need to clamp Y position  
 | 
					 | 
				
			||||||
            if (newY < workAreaY) {
 | 
					 | 
				
			||||||
                clampedY = workAreaY;
 | 
					 | 
				
			||||||
            } else if (newY + headerBounds.height > workAreaY + height) {
 | 
					 | 
				
			||||||
                clampedY = workAreaY + height - headerBounds.height;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            header.setPosition(clampedX, clampedY, false);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            updateLayout();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ipcMain.handle('move-window-step', (event, direction) => {
 | 
					    ipcMain.handle('move-window-step', (event, direction) => {
 | 
				
			||||||
        if (movementManager) {
 | 
					        if (movementManager) {
 | 
				
			||||||
@ -1105,13 +966,6 @@ function setupIpcHandlers(movementManager) {
 | 
				
			|||||||
            console.log(`[WindowManager] Force closing window: ${windowName}`);
 | 
					            console.log(`[WindowManager] Force closing window: ${windowName}`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            window.webContents.send('window-hide-animation');
 | 
					            window.webContents.send('window-hide-animation');
 | 
				
			||||||
 | 
					 | 
				
			||||||
            setTimeout(() => {
 | 
					 | 
				
			||||||
                if (!window.isDestroyed()) {
 | 
					 | 
				
			||||||
                    window.hide();
 | 
					 | 
				
			||||||
                    updateLayout();
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }, 250);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1405,7 +1259,7 @@ function updateGlobalShortcuts(keybinds, mainWindow, sendToRenderer, movementMan
 | 
				
			|||||||
    if (state === 'apikey') {
 | 
					    if (state === 'apikey') {
 | 
				
			||||||
        if (keybinds.toggleVisibility) {
 | 
					        if (keybinds.toggleVisibility) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                globalShortcut.register(keybinds.toggleVisibility, () => toggleAllWindowsVisibility(movementManager));
 | 
					                globalShortcut.register(keybinds.toggleVisibility, () => toggleAllWindowsVisibility());
 | 
				
			||||||
            } catch (error) {
 | 
					            } catch (error) {
 | 
				
			||||||
                console.error(`Failed to register toggleVisibility (${keybinds.toggleVisibility}):`, error);
 | 
					                console.error(`Failed to register toggleVisibility (${keybinds.toggleVisibility}):`, error);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -1441,7 +1295,7 @@ function updateGlobalShortcuts(keybinds, mainWindow, sendToRenderer, movementMan
 | 
				
			|||||||
            let callback;
 | 
					            let callback;
 | 
				
			||||||
            switch(action) {
 | 
					            switch(action) {
 | 
				
			||||||
                case 'toggleVisibility':
 | 
					                case 'toggleVisibility':
 | 
				
			||||||
                    callback = () => toggleAllWindowsVisibility(movementManager);
 | 
					                    callback = () => toggleAllWindowsVisibility();
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                case 'nextStep':
 | 
					                case 'nextStep':
 | 
				
			||||||
                    callback = () => {
 | 
					                    callback = () => {
 | 
				
			||||||
@ -1611,9 +1465,6 @@ module.exports = {
 | 
				
			|||||||
    createWindows,
 | 
					    createWindows,
 | 
				
			||||||
    windowPool,
 | 
					    windowPool,
 | 
				
			||||||
    fixedYPosition,
 | 
					    fixedYPosition,
 | 
				
			||||||
    //////// before_modelStateService ////////
 | 
					 | 
				
			||||||
    // setApiKey,
 | 
					 | 
				
			||||||
    //////// before_modelStateService ////////
 | 
					 | 
				
			||||||
    getStoredApiKey,
 | 
					    getStoredApiKey,
 | 
				
			||||||
    getStoredProvider,
 | 
					    getStoredProvider,
 | 
				
			||||||
    getCurrentModelInfo,
 | 
					    getCurrentModelInfo,
 | 
				
			||||||
 | 
				
			|||||||
@ -41,56 +41,6 @@ export class AskView extends LitElement {
 | 
				
			|||||||
            pointer-events: none;
 | 
					            pointer-events: none;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @keyframes slideUp {
 | 
					 | 
				
			||||||
            0% {
 | 
					 | 
				
			||||||
                opacity: 1;
 | 
					 | 
				
			||||||
                transform: translateY(0) scale(1);
 | 
					 | 
				
			||||||
                filter: blur(0px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            30% {
 | 
					 | 
				
			||||||
                opacity: 0.7;
 | 
					 | 
				
			||||||
                transform: translateY(-20%) scale(0.98);
 | 
					 | 
				
			||||||
                filter: blur(0.5px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            70% {
 | 
					 | 
				
			||||||
                opacity: 0.3;
 | 
					 | 
				
			||||||
                transform: translateY(-80%) scale(0.92);
 | 
					 | 
				
			||||||
                filter: blur(1.5px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            100% {
 | 
					 | 
				
			||||||
                opacity: 0;
 | 
					 | 
				
			||||||
                transform: translateY(-150%) scale(0.85);
 | 
					 | 
				
			||||||
                filter: blur(2px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        @keyframes slideDown {
 | 
					 | 
				
			||||||
            0% {
 | 
					 | 
				
			||||||
                opacity: 0;
 | 
					 | 
				
			||||||
                transform: translateY(-150%) scale(0.85);
 | 
					 | 
				
			||||||
                filter: blur(2px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            30% {
 | 
					 | 
				
			||||||
                opacity: 0.5;
 | 
					 | 
				
			||||||
                transform: translateY(-50%) scale(0.92);
 | 
					 | 
				
			||||||
                filter: blur(1px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            65% {
 | 
					 | 
				
			||||||
                opacity: 0.9;
 | 
					 | 
				
			||||||
                transform: translateY(-5%) scale(0.99);
 | 
					 | 
				
			||||||
                filter: blur(0.2px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            85% {
 | 
					 | 
				
			||||||
                opacity: 0.98;
 | 
					 | 
				
			||||||
                transform: translateY(2%) scale(1.005);
 | 
					 | 
				
			||||||
                filter: blur(0px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            100% {
 | 
					 | 
				
			||||||
                opacity: 1;
 | 
					 | 
				
			||||||
                transform: translateY(0) scale(1);
 | 
					 | 
				
			||||||
                filter: blur(0px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        * {
 | 
					        * {
 | 
				
			||||||
            font-family: 'Helvetica Neue', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
 | 
					            font-family: 'Helvetica Neue', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
 | 
				
			||||||
@ -252,20 +202,6 @@ export class AskView extends LitElement {
 | 
				
			|||||||
            animation: fadeInOut 0.3s ease-in-out;
 | 
					            animation: fadeInOut 0.3s ease-in-out;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @keyframes fadeInOut {
 | 
					 | 
				
			||||||
            0% {
 | 
					 | 
				
			||||||
                opacity: 1;
 | 
					 | 
				
			||||||
                transform: translateY(0);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            50% {
 | 
					 | 
				
			||||||
                opacity: 0;
 | 
					 | 
				
			||||||
                transform: translateY(-10px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            100% {
 | 
					 | 
				
			||||||
                opacity: 1;
 | 
					 | 
				
			||||||
                transform: translateY(0);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        .header-right {
 | 
					        .header-right {
 | 
				
			||||||
            display: flex;
 | 
					            display: flex;
 | 
				
			||||||
@ -422,19 +358,6 @@ export class AskView extends LitElement {
 | 
				
			|||||||
            animation-delay: 0.4s;
 | 
					            animation-delay: 0.4s;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @keyframes pulse {
 | 
					 | 
				
			||||||
            0%,
 | 
					 | 
				
			||||||
            80%,
 | 
					 | 
				
			||||||
            100% {
 | 
					 | 
				
			||||||
                opacity: 0.3;
 | 
					 | 
				
			||||||
                transform: scale(0.8);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            40% {
 | 
					 | 
				
			||||||
                opacity: 1;
 | 
					 | 
				
			||||||
                transform: scale(1.2);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        .response-line {
 | 
					        .response-line {
 | 
				
			||||||
            position: relative;
 | 
					            position: relative;
 | 
				
			||||||
            padding: 2px 0;
 | 
					            padding: 2px 0;
 | 
				
			||||||
@ -596,42 +519,6 @@ export class AskView extends LitElement {
 | 
				
			|||||||
            color: rgba(255, 255, 255, 0.5);
 | 
					            color: rgba(255, 255, 255, 0.5);
 | 
				
			||||||
            font-size: 14px;
 | 
					            font-size: 14px;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        /* ────────────────[ GLASS BYPASS ]─────────────── */
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .ask-container,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .response-header,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .response-icon,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .copy-button,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .close-button,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .line-copy-button,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .text-input-container,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .response-container pre,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .response-container p code,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .response-container pre code {
 | 
					 | 
				
			||||||
            background: transparent !important;
 | 
					 | 
				
			||||||
            border: none !important;
 | 
					 | 
				
			||||||
            outline: none !important;
 | 
					 | 
				
			||||||
            box-shadow: none !important;
 | 
					 | 
				
			||||||
            filter: none !important;
 | 
					 | 
				
			||||||
            backdrop-filter: none !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .ask-container::before {
 | 
					 | 
				
			||||||
            display: none !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .copy-button:hover,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .close-button:hover,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .line-copy-button,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .line-copy-button:hover,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .response-line:hover {
 | 
					 | 
				
			||||||
            background: transparent !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .response-container::-webkit-scrollbar-track,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .response-container::-webkit-scrollbar-thumb {
 | 
					 | 
				
			||||||
            background: transparent !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    `;
 | 
					    `;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor() {
 | 
					    constructor() {
 | 
				
			||||||
 | 
				
			|||||||
@ -27,56 +27,6 @@ export class AssistantView extends LitElement {
 | 
				
			|||||||
            pointer-events: none;
 | 
					            pointer-events: none;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @keyframes slideUp {
 | 
					 | 
				
			||||||
            0% {
 | 
					 | 
				
			||||||
                opacity: 1;
 | 
					 | 
				
			||||||
                transform: translateY(0) scale(1);
 | 
					 | 
				
			||||||
                filter: blur(0px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            30% {
 | 
					 | 
				
			||||||
                opacity: 0.7;
 | 
					 | 
				
			||||||
                transform: translateY(-20%) scale(0.98);
 | 
					 | 
				
			||||||
                filter: blur(0.5px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            70% {
 | 
					 | 
				
			||||||
                opacity: 0.3;
 | 
					 | 
				
			||||||
                transform: translateY(-80%) scale(0.92);
 | 
					 | 
				
			||||||
                filter: blur(1.5px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            100% {
 | 
					 | 
				
			||||||
                opacity: 0;
 | 
					 | 
				
			||||||
                transform: translateY(-150%) scale(0.85);
 | 
					 | 
				
			||||||
                filter: blur(2px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        @keyframes slideDown {
 | 
					 | 
				
			||||||
            0% {
 | 
					 | 
				
			||||||
                opacity: 0;
 | 
					 | 
				
			||||||
                transform: translateY(-150%) scale(0.85);
 | 
					 | 
				
			||||||
                filter: blur(2px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            30% {
 | 
					 | 
				
			||||||
                opacity: 0.5;
 | 
					 | 
				
			||||||
                transform: translateY(-50%) scale(0.92);
 | 
					 | 
				
			||||||
                filter: blur(1px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            65% {
 | 
					 | 
				
			||||||
                opacity: 0.9;
 | 
					 | 
				
			||||||
                transform: translateY(-5%) scale(0.99);
 | 
					 | 
				
			||||||
                filter: blur(0.2px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            85% {
 | 
					 | 
				
			||||||
                opacity: 0.98;
 | 
					 | 
				
			||||||
                transform: translateY(2%) scale(1.005);
 | 
					 | 
				
			||||||
                filter: blur(0px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            100% {
 | 
					 | 
				
			||||||
                opacity: 1;
 | 
					 | 
				
			||||||
                transform: translateY(0) scale(1);
 | 
					 | 
				
			||||||
                filter: blur(0px);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        * {
 | 
					        * {
 | 
				
			||||||
            font-family: 'Helvetica Neue', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
 | 
					            font-family: 'Helvetica Neue', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
 | 
				
			||||||
@ -245,17 +195,6 @@ export class AssistantView extends LitElement {
 | 
				
			|||||||
            animation: slideIn 0.3s ease forwards;
 | 
					            animation: slideIn 0.3s ease forwards;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @keyframes slideIn {
 | 
					 | 
				
			||||||
            from {
 | 
					 | 
				
			||||||
                transform: translateX(10%);
 | 
					 | 
				
			||||||
                opacity: 0;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            to {
 | 
					 | 
				
			||||||
                transform: translateX(0);
 | 
					 | 
				
			||||||
                opacity: 1;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        .bar-controls {
 | 
					        .bar-controls {
 | 
				
			||||||
            display: flex;
 | 
					            display: flex;
 | 
				
			||||||
            gap: 4px;
 | 
					            gap: 4px;
 | 
				
			||||||
@ -349,134 +288,6 @@ export class AssistantView extends LitElement {
 | 
				
			|||||||
            font-size: 10px;
 | 
					            font-size: 10px;
 | 
				
			||||||
            color: rgba(255, 255, 255, 0.7);
 | 
					            color: rgba(255, 255, 255, 0.7);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        /* ────────────────[ GLASS BYPASS ]─────────────── */
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .assistant-container,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .top-bar,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .toggle-button,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .copy-button,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .transcription-container,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .insights-container,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .stt-message,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .outline-item,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .request-item,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .markdown-content,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .insights-container pre,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .insights-container p code,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .insights-container pre code {
 | 
					 | 
				
			||||||
            background: transparent !important;
 | 
					 | 
				
			||||||
            border: none !important;
 | 
					 | 
				
			||||||
            outline: none !important;
 | 
					 | 
				
			||||||
            box-shadow: none !important;
 | 
					 | 
				
			||||||
            filter: none !important;
 | 
					 | 
				
			||||||
            backdrop-filter: none !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .assistant-container::before,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .assistant-container::after {
 | 
					 | 
				
			||||||
            display: none !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .toggle-button:hover,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .copy-button:hover,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .outline-item:hover,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .request-item.clickable:hover,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .markdown-content:hover {
 | 
					 | 
				
			||||||
            background: transparent !important;
 | 
					 | 
				
			||||||
            transform: none !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .transcription-container::-webkit-scrollbar-track,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .transcription-container::-webkit-scrollbar-thumb,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .insights-container::-webkit-scrollbar-track,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .insights-container::-webkit-scrollbar-thumb {
 | 
					 | 
				
			||||||
            background: transparent !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) * {
 | 
					 | 
				
			||||||
            animation: none !important;
 | 
					 | 
				
			||||||
            transition: none !important;
 | 
					 | 
				
			||||||
            transform: none !important;
 | 
					 | 
				
			||||||
            filter: none !important;
 | 
					 | 
				
			||||||
            backdrop-filter: none !important;
 | 
					 | 
				
			||||||
            box-shadow: none !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .assistant-container,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .stt-message,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .toggle-button,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .copy-button {
 | 
					 | 
				
			||||||
            border-radius: 0 !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) ::-webkit-scrollbar,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) ::-webkit-scrollbar-track,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) ::-webkit-scrollbar-thumb {
 | 
					 | 
				
			||||||
            background: transparent !important;
 | 
					 | 
				
			||||||
            width: 0 !important;      /* 스크롤바 자체 숨기기 */
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .assistant-container,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .top-bar,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .toggle-button,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .copy-button,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .transcription-container,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .insights-container,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .stt-message,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .outline-item,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .request-item,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .markdown-content,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .insights-container pre,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .insights-container p code,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .insights-container pre code {
 | 
					 | 
				
			||||||
            background: transparent !important;
 | 
					 | 
				
			||||||
            border: none !important;
 | 
					 | 
				
			||||||
            outline: none !important;
 | 
					 | 
				
			||||||
            box-shadow: none !important;
 | 
					 | 
				
			||||||
            filter: none !important;
 | 
					 | 
				
			||||||
            backdrop-filter: none !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .assistant-container::before,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .assistant-container::after {
 | 
					 | 
				
			||||||
            display: none !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .toggle-button:hover,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .copy-button:hover,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .outline-item:hover,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .request-item.clickable:hover,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .markdown-content:hover {
 | 
					 | 
				
			||||||
            background: transparent !important;
 | 
					 | 
				
			||||||
            transform: none !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .transcription-container::-webkit-scrollbar-track,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .transcription-container::-webkit-scrollbar-thumb,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .insights-container::-webkit-scrollbar-track,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .insights-container::-webkit-scrollbar-thumb {
 | 
					 | 
				
			||||||
            background: transparent !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) * {
 | 
					 | 
				
			||||||
            animation: none !important;
 | 
					 | 
				
			||||||
            transition: none !important;
 | 
					 | 
				
			||||||
            transform: none !important;
 | 
					 | 
				
			||||||
            filter: none !important;
 | 
					 | 
				
			||||||
            backdrop-filter: none !important;
 | 
					 | 
				
			||||||
            box-shadow: none !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .assistant-container,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .stt-message,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .toggle-button,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) .copy-button {
 | 
					 | 
				
			||||||
            border-radius: 0 !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) ::-webkit-scrollbar,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) ::-webkit-scrollbar-track,
 | 
					 | 
				
			||||||
        :host-context(body.has-glass) ::-webkit-scrollbar-thumb {
 | 
					 | 
				
			||||||
            background: transparent !important;
 | 
					 | 
				
			||||||
            width: 0 !important;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    `;
 | 
					    `;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static properties = {
 | 
					    static properties = {
 | 
				
			||||||
 | 
				
			|||||||
@ -412,7 +412,7 @@ export class SummaryView extends LitElement {
 | 
				
			|||||||
            const { ipcRenderer } = window.require('electron');
 | 
					            const { ipcRenderer } = window.require('electron');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                const isAskViewVisible = await ipcRenderer.invoke('is-window-visible', 'ask');
 | 
					                const isAskViewVisible = await ipcRenderer.invoke('is-ask-window-visible', 'ask');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (!isAskViewVisible) {
 | 
					                if (!isAskViewVisible) {
 | 
				
			||||||
                    await ipcRenderer.invoke('toggle-feature', 'ask');
 | 
					                    await ipcRenderer.invoke('toggle-feature', 'ask');
 | 
				
			||||||
 | 
				
			|||||||
@ -367,11 +367,6 @@ export class SettingsView extends LitElement {
 | 
				
			|||||||
            margin-right: 6px;
 | 
					            margin-right: 6px;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @keyframes spin {
 | 
					 | 
				
			||||||
            0% { transform: rotate(0deg); }
 | 
					 | 
				
			||||||
            100% { transform: rotate(360deg); }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        .hidden {
 | 
					        .hidden {
 | 
				
			||||||
            display: none;
 | 
					            display: none;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -1030,14 +1025,14 @@ export class SettingsView extends LitElement {
 | 
				
			|||||||
    handleMouseEnter = () => {
 | 
					    handleMouseEnter = () => {
 | 
				
			||||||
        if (window.require) {
 | 
					        if (window.require) {
 | 
				
			||||||
            const { ipcRenderer } = window.require('electron');
 | 
					            const { ipcRenderer } = window.require('electron');
 | 
				
			||||||
            ipcRenderer.send('cancel-hide-window', 'settings');
 | 
					            ipcRenderer.send('cancel-hide-settings-window');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    handleMouseLeave = () => {
 | 
					    handleMouseLeave = () => {
 | 
				
			||||||
        if (window.require) {
 | 
					        if (window.require) {
 | 
				
			||||||
            const { ipcRenderer } = window.require('electron');
 | 
					            const { ipcRenderer } = window.require('electron');
 | 
				
			||||||
            ipcRenderer.send('hide-window', 'settings');
 | 
					            ipcRenderer.send('hide-settings-window');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user