glass/src/app/HeaderController.js

225 lines
8.3 KiB
JavaScript

import './MainHeader.js';
import './ApiKeyHeader.js';
import './PermissionHeader.js';
class HeaderTransitionManager {
constructor() {
this.headerContainer = document.getElementById('header-container');
this.currentHeaderType = null; // 'apikey' | 'main' | 'permission'
this.apiKeyHeader = null;
this.mainHeader = null;
this.permissionHeader = null;
/**
* only one header window is allowed
* @param {'apikey'|'main'|'permission'} type
*/
this.ensureHeader = (type) => {
console.log('[HeaderController] ensureHeader: Ensuring header of type:', type);
if (this.currentHeaderType === type) {
console.log('[HeaderController] ensureHeader: Header of type:', type, 'already exists.');
return;
}
this.headerContainer.innerHTML = '';
this.apiKeyHeader = null;
this.mainHeader = null;
this.permissionHeader = null;
// Create new header element
if (type === 'apikey') {
this.apiKeyHeader = document.createElement('apikey-header');
this.apiKeyHeader.stateUpdateCallback = (userState) => this.handleStateUpdate(userState);
this.headerContainer.appendChild(this.apiKeyHeader);
} else if (type === 'permission') {
this.permissionHeader = document.createElement('permission-setup');
this.permissionHeader.continueCallback = () => this.transitionToMainHeader();
this.headerContainer.appendChild(this.permissionHeader);
} else {
this.mainHeader = document.createElement('main-header');
this.headerContainer.appendChild(this.mainHeader);
this.mainHeader.startSlideInAnimation?.();
}
this.currentHeaderType = type;
this.notifyHeaderState(type === 'permission' ? 'apikey' : type); // Keep permission state as apikey for compatibility
};
console.log('[HeaderController] Manager initialized');
this._bootstrap();
if (window.require) {
const { ipcRenderer } = window.require('electron');
ipcRenderer.on('user-state-changed', (event, userState) => {
console.log('[HeaderController] Received user state change:', userState);
this.handleStateUpdate(userState);
});
ipcRenderer.on('auth-failed', (event, { message }) => {
console.error('[HeaderController] Received auth failure from main process:', message);
if (this.apiKeyHeader) {
this.apiKeyHeader.errorMessage = 'Authentication failed. Please try again.';
this.apiKeyHeader.isLoading = false;
}
});
ipcRenderer.on('force-show-apikey-header', async () => {
console.log('[HeaderController] Received broadcast to show apikey header. Switching now.');
await this._resizeForApiKey();
this.ensureHeader('apikey');
});
}
}
notifyHeaderState(stateOverride) {
const state = stateOverride || this.currentHeaderType || 'apikey';
if (window.require) {
window.require('electron').ipcRenderer.send('header-state-changed', state);
}
}
async _bootstrap() {
// The initial state will be sent by the main process via 'user-state-changed'
// We just need to request it.
if (window.require) {
const userState = await window.require('electron').ipcRenderer.invoke('get-current-user');
console.log('[HeaderController] Bootstrapping with initial user state:', userState);
this.handleStateUpdate(userState);
} else {
// Fallback for non-electron environment (testing/web)
this.ensureHeader('apikey');
}
}
//////// after_modelStateService ////////
async handleStateUpdate(userState) {
const { ipcRenderer } = window.require('electron');
const isConfigured = await ipcRenderer.invoke('model:are-providers-configured');
if (isConfigured) {
const { isLoggedIn } = userState;
if (isLoggedIn) {
const permissionResult = await this.checkPermissions();
if (permissionResult.success) {
this.transitionToMainHeader();
} else {
this.transitionToPermissionHeader();
}
} else {
this.transitionToMainHeader();
}
} else {
await this._resizeForApiKey();
this.ensureHeader('apikey');
}
}
//////// after_modelStateService ////////
async transitionToPermissionHeader() {
// Prevent duplicate transitions
if (this.currentHeaderType === 'permission') {
console.log('[HeaderController] Already showing permission setup, skipping transition');
return;
}
// Check if permissions were previously completed
if (window.require) {
const { ipcRenderer } = window.require('electron');
try {
const permissionsCompleted = await ipcRenderer.invoke('check-permissions-completed');
if (permissionsCompleted) {
console.log('[HeaderController] Permissions were previously completed, checking current status...');
// Double check current permission status
const permissionResult = await this.checkPermissions();
if (permissionResult.success) {
// Skip permission setup if already granted
this.transitionToMainHeader();
return;
}
console.log('[HeaderController] Permissions were revoked, showing setup again');
}
} catch (error) {
console.error('[HeaderController] Error checking permissions completed status:', error);
}
}
await this._resizeForPermissionHeader();
this.ensureHeader('permission');
}
async transitionToMainHeader(animate = true) {
if (this.currentHeaderType === 'main') {
return this._resizeForMain();
}
await this._resizeForMain();
this.ensureHeader('main');
}
_resizeForMain() {
if (!window.require) return;
return window
.require('electron')
.ipcRenderer.invoke('resize-header-window', { width: 353, height: 47 })
.catch(() => {});
}
async _resizeForApiKey() {
if (!window.require) return;
return window
.require('electron')
.ipcRenderer.invoke('resize-header-window', { width: 350, height: 300 })
.catch(() => {});
}
async _resizeForPermissionHeader() {
if (!window.require) return;
return window
.require('electron')
.ipcRenderer.invoke('resize-header-window', { width: 285, height: 220 })
.catch(() => {});
}
async checkPermissions() {
if (!window.require) {
return { success: true };
}
const { ipcRenderer } = window.require('electron');
try {
const permissions = await ipcRenderer.invoke('check-system-permissions');
console.log('[HeaderController] Current permissions:', permissions);
if (!permissions.needsSetup) {
return { success: true };
}
let errorMessage = '';
if (!permissions.microphone && !permissions.screen) {
errorMessage = 'Microphone and 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', () => {
new HeaderTransitionManager();
});