minor fix
This commit is contained in:
		
							parent
							
								
									4c51d5133c
								
							
						
					
					
						commit
						ba8401345b
					
				@ -1,17 +0,0 @@
 | 
			
		||||
FROM python:3.11-slim
 | 
			
		||||
 | 
			
		||||
WORKDIR /app
 | 
			
		||||
 | 
			
		||||
RUN apt-get update && apt-get install -y \
 | 
			
		||||
    gcc \
 | 
			
		||||
    && rm -rf /var/lib/apt/lists/*
 | 
			
		||||
 | 
			
		||||
COPY requirements.txt .
 | 
			
		||||
 | 
			
		||||
RUN pip install --no-cache-dir -r requirements.txt
 | 
			
		||||
 | 
			
		||||
COPY backend/ .
 | 
			
		||||
 | 
			
		||||
EXPOSE 8000
 | 
			
		||||
 | 
			
		||||
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"] 
 | 
			
		||||
@ -1,15 +0,0 @@
 | 
			
		||||
FROM node:18-alpine
 | 
			
		||||
 | 
			
		||||
WORKDIR /app
 | 
			
		||||
 | 
			
		||||
COPY package*.json ./
 | 
			
		||||
 | 
			
		||||
RUN npm ci --only=production
 | 
			
		||||
 | 
			
		||||
COPY . .
 | 
			
		||||
 | 
			
		||||
RUN npm run build
 | 
			
		||||
 | 
			
		||||
EXPOSE 3000
 | 
			
		||||
 | 
			
		||||
CMD ["npm", "start"] 
 | 
			
		||||
@ -1,35 +0,0 @@
 | 
			
		||||
version: '3.8'
 | 
			
		||||
 | 
			
		||||
services:
 | 
			
		||||
  backend:
 | 
			
		||||
    build:
 | 
			
		||||
      context: .
 | 
			
		||||
      dockerfile: Dockerfile.backend
 | 
			
		||||
    container_name: pickleglass-backend
 | 
			
		||||
    restart: always
 | 
			
		||||
    ports:
 | 
			
		||||
      - "8000:8000"
 | 
			
		||||
    environment:
 | 
			
		||||
      - DATABASE_URL=/app/data/pickleglass.db
 | 
			
		||||
    volumes:
 | 
			
		||||
      - ./backend:/app
 | 
			
		||||
      - ./data:/app/data
 | 
			
		||||
 | 
			
		||||
  frontend:
 | 
			
		||||
    build:
 | 
			
		||||
      context: .
 | 
			
		||||
      dockerfile: Dockerfile.frontend
 | 
			
		||||
    container_name: pickleglass-frontend
 | 
			
		||||
    restart: always
 | 
			
		||||
    ports:
 | 
			
		||||
      - "3000:3000"
 | 
			
		||||
    environment:
 | 
			
		||||
      - NEXT_PUBLIC_API_URL=http://localhost:8000
 | 
			
		||||
    depends_on:
 | 
			
		||||
      - backend
 | 
			
		||||
    volumes:
 | 
			
		||||
      - .:/app
 | 
			
		||||
      - /app/node_modules
 | 
			
		||||
 | 
			
		||||
volumes:
 | 
			
		||||
  mongodb_data: 
 | 
			
		||||
@ -346,9 +346,18 @@ export class ApiKeyHeader extends LitElement {
 | 
			
		||||
            const isValid = await this.validateApiKey(this.apiKey.trim());
 | 
			
		||||
 | 
			
		||||
            if (isValid) {
 | 
			
		||||
                console.log('API key valid - starting slide out animation');
 | 
			
		||||
                this.startSlideOutAnimation();
 | 
			
		||||
                this.validatedApiKey = this.apiKey.trim();
 | 
			
		||||
                console.log('API key valid - checking system permissions...');
 | 
			
		||||
                
 | 
			
		||||
                const permissionResult = await this.checkAndRequestPermissions();
 | 
			
		||||
                
 | 
			
		||||
                if (permissionResult.success) {
 | 
			
		||||
                    console.log('All permissions granted - starting slide out animation');
 | 
			
		||||
                    this.startSlideOutAnimation();
 | 
			
		||||
                    this.validatedApiKey = this.apiKey.trim();
 | 
			
		||||
                } else {
 | 
			
		||||
                    this.errorMessage = permissionResult.error || 'Permission setup required';
 | 
			
		||||
                    console.log('Permission setup incomplete:', permissionResult);
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                this.errorMessage = 'Invalid API key - please check and try again';
 | 
			
		||||
                console.log('API key validation failed');
 | 
			
		||||
@ -398,6 +407,58 @@ export class ApiKeyHeader extends LitElement {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async checkAndRequestPermissions() {
 | 
			
		||||
        if (!window.require) {
 | 
			
		||||
            return { success: true };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const { ipcRenderer } = window.require('electron');
 | 
			
		||||
        
 | 
			
		||||
        try {
 | 
			
		||||
            const permissions = await ipcRenderer.invoke('check-system-permissions');
 | 
			
		||||
            console.log('[Permissions] Current status:', permissions);
 | 
			
		||||
            
 | 
			
		||||
            if (!permissions.needsSetup) {
 | 
			
		||||
                return { success: true };
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!permissions.microphone) {
 | 
			
		||||
                console.log('[Permissions] Requesting microphone permission...');
 | 
			
		||||
                const micResult = await ipcRenderer.invoke('request-microphone-permission');
 | 
			
		||||
                
 | 
			
		||||
                if (!micResult.success) {
 | 
			
		||||
                    console.log('[Permissions] Microphone permission denied');
 | 
			
		||||
                    await ipcRenderer.invoke('open-system-preferences', 'microphone');
 | 
			
		||||
                    return { 
 | 
			
		||||
                        success: false, 
 | 
			
		||||
                        error: 'Please grant microphone access in System Preferences' 
 | 
			
		||||
                    };
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!permissions.screen) {
 | 
			
		||||
                console.log('[Permissions] Screen recording permission needed');
 | 
			
		||||
                await ipcRenderer.invoke('open-system-preferences', 'screen-recording');
 | 
			
		||||
                
 | 
			
		||||
                this.errorMessage = 'Please grant screen recording permission and try again';
 | 
			
		||||
                this.requestUpdate();
 | 
			
		||||
                
 | 
			
		||||
                return { 
 | 
			
		||||
                    success: false, 
 | 
			
		||||
                    error: 'Please grant screen recording access in System Preferences' 
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return { success: true };
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            console.error('[Permissions] Error checking/requesting permissions:', error);
 | 
			
		||||
            return { 
 | 
			
		||||
                success: false, 
 | 
			
		||||
                error: 'Failed to check permissions' 
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    startSlideOutAnimation() {
 | 
			
		||||
        this.classList.add('sliding-out');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -10,25 +10,25 @@ export class AppHeader extends LitElement {
 | 
			
		||||
            display: block;
 | 
			
		||||
            transform: translate3d(0, 0, 0);
 | 
			
		||||
            backface-visibility: hidden;
 | 
			
		||||
            transition: transform 0.25s cubic-bezier(0.23, 1, 0.32, 1), opacity 0.25s 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) {
 | 
			
		||||
            animation: slideUp 0.45s cubic-bezier(0.55, 0.085, 0.68, 0.53) forwards;
 | 
			
		||||
            animation: slideUp 0.3s cubic-bezier(0.4, 0, 0.6, 1) forwards;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        :host(.showing) {
 | 
			
		||||
            animation: slideDown 0.5s cubic-bezier(0.25, 0.8, 0.25, 1) forwards;
 | 
			
		||||
            animation: slideDown 0.35s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        :host(.sliding-in) {
 | 
			
		||||
            animation: fadeIn 0.25s ease-out forwards;
 | 
			
		||||
            will-change: opacity;
 | 
			
		||||
            animation: fadeIn 0.2s ease-out forwards;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        :host(.hidden) {
 | 
			
		||||
            opacity: 0;
 | 
			
		||||
            transform: translateY(-180%) scale(0.8);
 | 
			
		||||
            transform: translateY(-150%) scale(0.85);
 | 
			
		||||
            pointer-events: none;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -36,65 +36,50 @@ export class AppHeader extends LitElement {
 | 
			
		||||
            0% {
 | 
			
		||||
                opacity: 1;
 | 
			
		||||
                transform: translateY(0) scale(1);
 | 
			
		||||
                filter: blur(0px) brightness(1);
 | 
			
		||||
                box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
 | 
			
		||||
                filter: blur(0px);
 | 
			
		||||
            }
 | 
			
		||||
            25% {
 | 
			
		||||
                opacity: 0.85;
 | 
			
		||||
                transform: translateY(-20%) scale(0.96);
 | 
			
		||||
                filter: blur(0px) brightness(0.95);
 | 
			
		||||
                box-shadow: 0 6px 28px rgba(0, 0, 0, 0.25);
 | 
			
		||||
            30% {
 | 
			
		||||
                opacity: 0.7;
 | 
			
		||||
                transform: translateY(-20%) scale(0.98);
 | 
			
		||||
                filter: blur(0.5px);
 | 
			
		||||
            }
 | 
			
		||||
            50% {
 | 
			
		||||
                opacity: 0.5;
 | 
			
		||||
                transform: translateY(-60%) scale(0.9);
 | 
			
		||||
                filter: blur(1px) brightness(0.85);
 | 
			
		||||
                box-shadow: 0 3px 15px rgba(0, 0, 0, 0.15);
 | 
			
		||||
            }
 | 
			
		||||
            75% {
 | 
			
		||||
                opacity: 0.15;
 | 
			
		||||
                transform: translateY(-120%) scale(0.85);
 | 
			
		||||
                filter: blur(2px) brightness(0.75);
 | 
			
		||||
                box-shadow: 0 1px 8px rgba(0, 0, 0, 0.08);
 | 
			
		||||
            70% {
 | 
			
		||||
                opacity: 0.3;
 | 
			
		||||
                transform: translateY(-80%) scale(0.92);
 | 
			
		||||
                filter: blur(1.5px);
 | 
			
		||||
            }
 | 
			
		||||
            100% {
 | 
			
		||||
                opacity: 0;
 | 
			
		||||
                transform: translateY(-180%) scale(0.8);
 | 
			
		||||
                filter: blur(3px) brightness(0.7);
 | 
			
		||||
                box-shadow: 0 0px 0px rgba(0, 0, 0, 0);
 | 
			
		||||
                transform: translateY(-150%) scale(0.85);
 | 
			
		||||
                filter: blur(2px);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @keyframes slideDown {
 | 
			
		||||
            0% {
 | 
			
		||||
                opacity: 0;
 | 
			
		||||
                transform: translateY(-180%) scale(0.8);
 | 
			
		||||
                filter: blur(3px) brightness(0.7);
 | 
			
		||||
                box-shadow: 0 0px 0px rgba(0, 0, 0, 0);
 | 
			
		||||
                transform: translateY(-150%) scale(0.85);
 | 
			
		||||
                filter: blur(2px);
 | 
			
		||||
            }
 | 
			
		||||
            40% {
 | 
			
		||||
                opacity: 0.6;
 | 
			
		||||
                transform: translateY(-30%) scale(0.95);
 | 
			
		||||
                filter: blur(1px) brightness(0.9);
 | 
			
		||||
                box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
 | 
			
		||||
            30% {
 | 
			
		||||
                opacity: 0.5;
 | 
			
		||||
                transform: translateY(-50%) scale(0.92);
 | 
			
		||||
                filter: blur(1px);
 | 
			
		||||
            }
 | 
			
		||||
            70% {
 | 
			
		||||
            65% {
 | 
			
		||||
                opacity: 0.9;
 | 
			
		||||
                transform: translateY(-5%) scale(1.01);
 | 
			
		||||
                filter: blur(0.3px) brightness(1.02);
 | 
			
		||||
                box-shadow: 0 7px 28px rgba(0, 0, 0, 0.28);
 | 
			
		||||
                transform: translateY(-5%) scale(0.99);
 | 
			
		||||
                filter: blur(0.2px);
 | 
			
		||||
            }
 | 
			
		||||
            85% {
 | 
			
		||||
                opacity: 0.98;
 | 
			
		||||
                transform: translateY(1%) scale(0.995);
 | 
			
		||||
                filter: blur(0.1px) brightness(1.01);
 | 
			
		||||
                box-shadow: 0 8px 30px rgba(0, 0, 0, 0.31);
 | 
			
		||||
                transform: translateY(2%) scale(1.005);
 | 
			
		||||
                filter: blur(0px);
 | 
			
		||||
            }
 | 
			
		||||
            100% {
 | 
			
		||||
                opacity: 1;
 | 
			
		||||
                transform: translateY(0) scale(1);
 | 
			
		||||
                filter: blur(0px) brightness(1);
 | 
			
		||||
                box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
 | 
			
		||||
                filter: blur(0px);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -318,6 +303,7 @@ export class AppHeader extends LitElement {
 | 
			
		||||
        this.hasSlidIn = false;
 | 
			
		||||
        this.settingsHideTimer = null;
 | 
			
		||||
        this.isSessionActive = false;
 | 
			
		||||
        this.animationEndTimer = null;
 | 
			
		||||
 | 
			
		||||
        if (window.require) {
 | 
			
		||||
            const { ipcRenderer } = window.require('electron');
 | 
			
		||||
@ -388,7 +374,15 @@ export class AppHeader extends LitElement {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    toggleVisibility() {
 | 
			
		||||
        if (this.isAnimating) return;
 | 
			
		||||
        if (this.isAnimating) {
 | 
			
		||||
            console.log('[AppHeader] Animation already in progress, ignoring toggle');
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        if (this.animationEndTimer) {
 | 
			
		||||
            clearTimeout(this.animationEndTimer);
 | 
			
		||||
            this.animationEndTimer = null;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        this.isAnimating = true;
 | 
			
		||||
        
 | 
			
		||||
@ -403,17 +397,34 @@ export class AppHeader extends LitElement {
 | 
			
		||||
        this.classList.remove('showing', 'hidden');
 | 
			
		||||
        this.classList.add('hiding');
 | 
			
		||||
        this.isVisible = false;
 | 
			
		||||
        
 | 
			
		||||
        this.animationEndTimer = setTimeout(() => {
 | 
			
		||||
            if (this.classList.contains('hiding')) {
 | 
			
		||||
                this.handleAnimationEnd({ target: this });
 | 
			
		||||
            }
 | 
			
		||||
        }, 350);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    show() {
 | 
			
		||||
        this.classList.remove('hiding', 'hidden');
 | 
			
		||||
        this.classList.add('showing');
 | 
			
		||||
        this.isVisible = true;
 | 
			
		||||
        
 | 
			
		||||
        this.animationEndTimer = setTimeout(() => {
 | 
			
		||||
            if (this.classList.contains('showing')) {
 | 
			
		||||
                this.handleAnimationEnd({ target: this });
 | 
			
		||||
            }
 | 
			
		||||
        }, 400);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    handleAnimationEnd(e) {
 | 
			
		||||
        if (e.target !== this) return;
 | 
			
		||||
        
 | 
			
		||||
        if (this.animationEndTimer) {
 | 
			
		||||
            clearTimeout(this.animationEndTimer);
 | 
			
		||||
            this.animationEndTimer = null;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        this.isAnimating = false;
 | 
			
		||||
        
 | 
			
		||||
        if (this.classList.contains('hiding')) {
 | 
			
		||||
@ -434,7 +445,7 @@ export class AppHeader extends LitElement {
 | 
			
		||||
        } else if (this.classList.contains('sliding-in')) {
 | 
			
		||||
            this.classList.remove('sliding-in');
 | 
			
		||||
            this.hasSlidIn = true;
 | 
			
		||||
            console.log('AppHeader slide-in animation completed');
 | 
			
		||||
            console.log('[AppHeader] Slide-in animation completed');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -460,6 +471,11 @@ export class AppHeader extends LitElement {
 | 
			
		||||
        super.disconnectedCallback();
 | 
			
		||||
        this.removeEventListener('animationend', this.handleAnimationEnd);
 | 
			
		||||
        
 | 
			
		||||
        if (this.animationEndTimer) {
 | 
			
		||||
            clearTimeout(this.animationEndTimer);
 | 
			
		||||
            this.animationEndTimer = null;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        if (window.require) {
 | 
			
		||||
            const { ipcRenderer } = window.require('electron');
 | 
			
		||||
            ipcRenderer.removeAllListeners('toggle-header-visibility');
 | 
			
		||||
 | 
			
		||||
@ -81,11 +81,31 @@ class HeaderTransitionManager {
 | 
			
		||||
 | 
			
		||||
                    if (error) {
 | 
			
		||||
                        console.warn('[HeaderController] Login payload indicates verification failure. Proceeding to AppHeader UI only.');
 | 
			
		||||
                        this.transitionToAppHeader();
 | 
			
		||||
                        // Check permissions before transitioning
 | 
			
		||||
                        const permissionResult = await this.checkPermissions();
 | 
			
		||||
                        if (permissionResult.success) {
 | 
			
		||||
                            this.transitionToAppHeader();
 | 
			
		||||
                        } else {
 | 
			
		||||
                            console.log('[HeaderController] Permissions not granted after login error');
 | 
			
		||||
                            if (this.apiKeyHeader) {
 | 
			
		||||
                                this.apiKeyHeader.errorMessage = permissionResult.error || 'Permission setup required';
 | 
			
		||||
                                this.apiKeyHeader.requestUpdate();
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                } catch (error) {
 | 
			
		||||
                    console.error('[HeaderController] Sign-in failed', error);
 | 
			
		||||
                    this.transitionToAppHeader();
 | 
			
		||||
                    // Check permissions before transitioning
 | 
			
		||||
                    const permissionResult = await this.checkPermissions();
 | 
			
		||||
                    if (permissionResult.success) {
 | 
			
		||||
                        this.transitionToAppHeader();
 | 
			
		||||
                    } else {
 | 
			
		||||
                        console.log('[HeaderController] Permissions not granted after sign-in failure');
 | 
			
		||||
                        if (this.apiKeyHeader) {
 | 
			
		||||
                            this.apiKeyHeader.errorMessage = permissionResult.error || 'Permission setup required';
 | 
			
		||||
                            this.apiKeyHeader.requestUpdate();
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
            
 | 
			
		||||
@ -125,7 +145,17 @@ class HeaderTransitionManager {
 | 
			
		||||
                        console.log('[HeaderController] Firebase sign-in successful via ID token');
 | 
			
		||||
                    } else {
 | 
			
		||||
                        console.warn('[HeaderController] No ID token received from deeplink, virtual key request may fail');
 | 
			
		||||
                        this.transitionToAppHeader();
 | 
			
		||||
                        // Check permissions before transitioning
 | 
			
		||||
                        const permissionResult = await this.checkPermissions();
 | 
			
		||||
                        if (permissionResult.success) {
 | 
			
		||||
                            this.transitionToAppHeader();
 | 
			
		||||
                        } else {
 | 
			
		||||
                            console.log('[HeaderController] Permissions not granted after Firebase auth');
 | 
			
		||||
                            if (this.apiKeyHeader) {
 | 
			
		||||
                                this.apiKeyHeader.errorMessage = permissionResult.error || 'Permission setup required';
 | 
			
		||||
                                this.apiKeyHeader.requestUpdate();
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                } catch (error) {
 | 
			
		||||
                    console.error('[HeaderController] Firebase auth failed:', error);
 | 
			
		||||
@ -173,11 +203,25 @@ class HeaderTransitionManager {
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (user) {
 | 
			
		||||
                console.log('[HeaderController] User is logged in, transitioning to AppHeader');
 | 
			
		||||
                this.transitionToAppHeader(!this.hasApiKey);
 | 
			
		||||
                console.log('[HeaderController] User is logged in, checking permissions...');
 | 
			
		||||
                const permissionResult = await this.checkPermissions();
 | 
			
		||||
                if (permissionResult.success) {
 | 
			
		||||
                    this.transitionToAppHeader(!this.hasApiKey);
 | 
			
		||||
                } else {
 | 
			
		||||
                    console.log('[HeaderController] Permissions not granted, staying on ApiKeyHeader');
 | 
			
		||||
                    if (this.apiKeyHeader) {
 | 
			
		||||
                        this.apiKeyHeader.errorMessage = permissionResult.error || 'Permission setup required';
 | 
			
		||||
                        this.apiKeyHeader.requestUpdate();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } else if (this.hasApiKey) {
 | 
			
		||||
                console.log('[HeaderController] No Firebase user but API key exists, showing AppHeader');
 | 
			
		||||
                this.transitionToAppHeader(false);
 | 
			
		||||
                console.log('[HeaderController] No Firebase user but API key exists, checking permissions...');
 | 
			
		||||
                const permissionResult = await this.checkPermissions();
 | 
			
		||||
                if (permissionResult.success) {
 | 
			
		||||
                    this.transitionToAppHeader(false);
 | 
			
		||||
                } else {
 | 
			
		||||
                    console.log('[HeaderController] Permissions not granted, staying on ApiKeyHeader');
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                console.log('[HeaderController] No auth & no API key — showing ApiKeyHeader');
 | 
			
		||||
                this.transitionToApiKeyHeader();
 | 
			
		||||
@ -185,7 +229,6 @@ class HeaderTransitionManager {
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    notifyHeaderState(stateOverride) {
 | 
			
		||||
        const state = stateOverride || this.currentHeaderType || 'apikey';
 | 
			
		||||
        if (window.require) {
 | 
			
		||||
@ -193,33 +236,46 @@ class HeaderTransitionManager {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
      async _bootstrap() {
 | 
			
		||||
              let storedKey = null;
 | 
			
		||||
              if (window.require) {
 | 
			
		||||
                  try {
 | 
			
		||||
                      storedKey = await window
 | 
			
		||||
                          .require('electron')
 | 
			
		||||
                          .ipcRenderer.invoke('get-current-api-key');
 | 
			
		||||
                  } catch (_) {}
 | 
			
		||||
              }
 | 
			
		||||
              this.hasApiKey = !!storedKey;
 | 
			
		||||
        
 | 
			
		||||
              const user = await new Promise(resolve => {
 | 
			
		||||
                  const unsubscribe = onAuthStateChanged(auth, u => {
 | 
			
		||||
                      unsubscribe();
 | 
			
		||||
                      resolve(u);
 | 
			
		||||
                  });
 | 
			
		||||
              });
 | 
			
		||||
        
 | 
			
		||||
              if (user || this.hasApiKey) {
 | 
			
		||||
                  await this._resizeForApp();
 | 
			
		||||
                  this.ensureHeader('app');
 | 
			
		||||
              } else {
 | 
			
		||||
                  await this._resizeForApiKey();
 | 
			
		||||
                  this.ensureHeader('apikey');
 | 
			
		||||
              }
 | 
			
		||||
    }
 | 
			
		||||
    async _bootstrap() {
 | 
			
		||||
        let storedKey = null;
 | 
			
		||||
        if (window.require) {
 | 
			
		||||
            try {
 | 
			
		||||
                storedKey = await window
 | 
			
		||||
                    .require('electron')
 | 
			
		||||
                    .ipcRenderer.invoke('get-current-api-key');
 | 
			
		||||
            } catch (_) {}
 | 
			
		||||
        }
 | 
			
		||||
        this.hasApiKey = !!storedKey;
 | 
			
		||||
 | 
			
		||||
        const user = await new Promise(resolve => {
 | 
			
		||||
            const unsubscribe = onAuthStateChanged(auth, u => {
 | 
			
		||||
                unsubscribe();
 | 
			
		||||
                resolve(u);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        if (user || this.hasApiKey) {
 | 
			
		||||
            const permissionResult = await this.checkPermissions();
 | 
			
		||||
            
 | 
			
		||||
            if (permissionResult.success) {
 | 
			
		||||
                await this._resizeForApp();
 | 
			
		||||
                this.ensureHeader('app');
 | 
			
		||||
            } else {
 | 
			
		||||
                await this._resizeForApiKey();
 | 
			
		||||
                this.ensureHeader('apikey');
 | 
			
		||||
                
 | 
			
		||||
                setTimeout(() => {
 | 
			
		||||
                    if (this.apiKeyHeader) {
 | 
			
		||||
                        this.apiKeyHeader.errorMessage = permissionResult.error || 'Permission setup required';
 | 
			
		||||
                        this.apiKeyHeader.requestUpdate();
 | 
			
		||||
                    }
 | 
			
		||||
                }, 100);
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            await this._resizeForApiKey();
 | 
			
		||||
            this.ensureHeader('apikey');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async transitionToAppHeader(animate = true) {
 | 
			
		||||
        if (this.currentHeaderType === 'app') {
 | 
			
		||||
@ -249,23 +305,69 @@ class HeaderTransitionManager {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _resizeForApp() {
 | 
			
		||||
            if (!window.require) return;
 | 
			
		||||
            return window
 | 
			
		||||
                .require('electron')
 | 
			
		||||
                .ipcRenderer.invoke('resize-header-window', { width: 353, height: 60 })
 | 
			
		||||
                .catch(() => {});
 | 
			
		||||
        if (!window.require) return;
 | 
			
		||||
        return window
 | 
			
		||||
            .require('electron')
 | 
			
		||||
            .ipcRenderer.invoke('resize-header-window', { width: 353, height: 60 })
 | 
			
		||||
            .catch(() => {});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async _resizeForApiKey() {
 | 
			
		||||
        if (!window.require) return;
 | 
			
		||||
        return window
 | 
			
		||||
            .require('electron')
 | 
			
		||||
            .ipcRenderer.invoke('resize-header-window', { width: 285, height: 220 })
 | 
			
		||||
            .catch(() => {});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async transitionToApiKeyHeader() {
 | 
			
		||||
        await this._resizeForApiKey();
 | 
			
		||||
        
 | 
			
		||||
        if (this.currentHeaderType !== 'apikey') {
 | 
			
		||||
            this.ensureHeader('apikey');
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        if (this.apiKeyHeader) this.apiKeyHeader.reset();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async checkPermissions() {
 | 
			
		||||
        if (!window.require) {
 | 
			
		||||
            return { success: true };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        async transitionToApiKeyHeader() {
 | 
			
		||||
                await window.require('electron')
 | 
			
		||||
                    .ipcRenderer.invoke('resize-header-window', { width: 285, height: 220 });
 | 
			
		||||
        const { ipcRenderer } = window.require('electron');
 | 
			
		||||
        
 | 
			
		||||
        try {
 | 
			
		||||
            // Check permission status
 | 
			
		||||
            const permissions = await ipcRenderer.invoke('check-system-permissions');
 | 
			
		||||
            console.log('[HeaderController] Current permissions:', permissions);
 | 
			
		||||
            
 | 
			
		||||
                if (this.currentHeaderType !== 'apikey') {
 | 
			
		||||
                    this.ensureHeader('apikey');
 | 
			
		||||
                }
 | 
			
		||||
            
 | 
			
		||||
                 if (this.apiKeyHeader) this.apiKeyHeader.reset();
 | 
			
		||||
            if (!permissions.needsSetup) {
 | 
			
		||||
                return { success: true };
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // If permissions are not set up, return false
 | 
			
		||||
            let errorMessage = '';
 | 
			
		||||
            if (!permissions.microphone && !permissions.screen) {
 | 
			
		||||
                errorMessage = 'Microphone and screen recording access required';
 | 
			
		||||
            } else if (!permissions.microphone) {
 | 
			
		||||
                errorMessage = 'Microphone access required';
 | 
			
		||||
            } else if (!permissions.screen) {
 | 
			
		||||
                errorMessage = 'Screen recording access required';
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            return { 
 | 
			
		||||
                success: false, 
 | 
			
		||||
                error: errorMessage
 | 
			
		||||
            };
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            console.error('[HeaderController] Error checking permissions:', error);
 | 
			
		||||
            return { 
 | 
			
		||||
                success: false, 
 | 
			
		||||
                error: 'Failed to check permissions' 
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
window.addEventListener('DOMContentLoaded', () => {
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										12
									
								
								src/index.js
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								src/index.js
									
									
									
									
									
								
							@ -1,9 +1,9 @@
 | 
			
		||||
try {
 | 
			
		||||
    const reloader = require('electron-reloader');
 | 
			
		||||
    reloader(module, {
 | 
			
		||||
    });
 | 
			
		||||
} catch (err) {
 | 
			
		||||
}
 | 
			
		||||
// try {
 | 
			
		||||
//     const reloader = require('electron-reloader');
 | 
			
		||||
//     reloader(module, {
 | 
			
		||||
//     });
 | 
			
		||||
// } catch (err) {
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
require('dotenv').config();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user