File size: 9,419 Bytes
adca48b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
/**
* PIPS - Main Application Bootstrap
* Initializes the modular PIPS application
*/
// Import core modules
import { Logger } from './core/logger.js';
import { appState } from './core/state.js';
import { socketManager } from './network/socket.js';
import { storageManager } from './core/storage.js';
// Import UI modules
import { domManager } from './ui/dom-manager.js';
import { messageManager } from './ui/message-manager.js';
import { settingsManager } from './ui/settings-manager.js';
import { sessionManager } from './ui/session-manager.js';
import { imageHandler } from './ui/image-handler.js';
// Import handlers
import { socketEventHandlers } from './handlers/socket-handlers.js';
// Global error handlers
window.addEventListener('error', (event) => {
Logger.error('Global JavaScript error:', event.error);
Logger.error('Error message:', event.message);
Logger.error('Error filename:', event.filename);
Logger.error('Error line:', event.lineno);
Logger.error('Error column:', event.colno);
});
window.addEventListener('unhandledrejection', (event) => {
Logger.error('Unhandled promise rejection:', event.reason);
});
/**
* Main Application class - Coordinates all modules
*/
class PIPSApplication {
constructor() {
this.isInitialized = false;
}
async initialize() {
if (this.isInitialized) {
Logger.warn('App', 'Application already initialized');
return;
}
try {
Logger.log('App', 'Initializing PIPS application...');
// Initialize managers
domManager.setupDOMReferences();
await domManager.initializeIcons();
// Set up event handlers
socketManager.initialize();
sessionManager.initialize();
settingsManager.initialize();
imageHandler.initialize();
// Load user settings from storage
settingsManager.loadUserSettingsFromStorage();
// Perform first-run seeding of default sessions
await this.performFirstRunSeeding();
// Set up additional image features
imageHandler.setupPasteHandler();
// Set up core functionality event listeners
this.setupCoreEventListeners();
// Register *all* socket & connection handlers BEFORE connecting
this.setupSocketHandlers();
// Connect socket *after* handlers are registered
await socketManager.initialize();
// Set initial status
domManager.updateStatus('Connecting to PIPS server...', 'info');
this.isInitialized = true;
Logger.log('App', 'PIPS application initialized successfully');
} catch (error) {
Logger.error('App', 'Error during initialization:', error);
domManager.updateStatus('Failed to initialize application', 'error');
}
}
async performFirstRunSeeding() {
try {
// Check if this is the first run
if (!localStorage.getItem('pips_first_run_completed')) {
Logger.debug('App', 'First run detected, seeding default sessions...');
try {
const result = await storageManager.importSessionsFromUrl('/static/default_sessions/builtin_sessions.json');
Logger.log('App', `Seeded ${result.imported} default sessions successfully`);
// Track which sessions are defaults by storing their IDs
if (result.imported > 0) {
const sessions = storageManager.loadSessions();
const defaultSessionIds = Object.keys(sessions);
storageManager.saveDefaultSessionIds(defaultSessionIds);
Logger.debug('App', `Tracked ${defaultSessionIds.length} default session IDs`);
}
// Mark first run as completed
localStorage.setItem('pips_first_run_completed', 'yes');
localStorage.setItem('pips_default_sessions_loaded', new Date().toISOString());
} catch (error) {
Logger.warn('App', 'Could not load default sessions (this is normal in development):', error.message);
// Still mark as completed to avoid repeated attempts
localStorage.setItem('pips_first_run_completed', 'yes');
}
} else {
Logger.debug('App', 'Not first run, skipping default session seeding');
}
} catch (error) {
Logger.error('App', 'Error during first-run seeding:', error);
}
}
setupCoreEventListeners() {
// Core problem solving functionality
domManager.getElement('solveBtn')?.addEventListener('click', () => this.solveProblem());
domManager.getElement('interruptBtn')?.addEventListener('click', () => this.interruptSolving());
domManager.getElement('downloadBtn')?.addEventListener('click', () => messageManager.downloadChat());
Logger.debug('App', 'Core event listeners set up');
// Set up emergency cleanup handler for page unload
window.addEventListener('beforeunload', () => {
Logger.debug('App', 'Page unloading - performing emergency cleanup');
sessionManager.emergencyCleanupAndSave();
});
}
setupSocketHandlers() {
console.log('[DEBUG] Setting up socket handlers...');
// Register all socket event handlers (these are real Socket.IO events)
const eventHandlers = socketEventHandlers.getEventHandlers();
console.log('[DEBUG] Event handlers to register:', Object.keys(eventHandlers));
socketManager.registerEventHandlers(eventHandlers);
// Register connection handlers (these are internal socketManager events)
const connectionHandlers = socketEventHandlers.getConnectionHandlers();
console.log('[DEBUG] Connection handlers to register:', Object.keys(connectionHandlers));
Object.entries(connectionHandlers).forEach(([event, handler]) => {
socketManager.on(event, handler);
});
Logger.debug('App', 'Socket event handlers set up successfully');
}
// Core functionality methods
solveProblem() {
const questionInput = domManager.getElement('questionInput');
const text = questionInput?.value.trim();
if (!text) {
domManager.updateStatus('Please enter a problem description', 'warning');
return;
}
// Check if the current session is used and should be read-only
if (appState.currentSessionData && sessionManager.isSessionUsed(appState.currentSessionData)) {
domManager.updateStatus('This session has been used. Please start a new session to solve another problem.', 'warning');
// Automatically start a new session
sessionManager.startNewSession();
return;
}
// Get image data if available
const imageData = imageHandler.getImageForSubmission();
// Handle session creation/management through session manager
const sessionId = sessionManager.handleSolveProblem(text, imageData);
// Send current settings to server first to ensure PIPS mode is included
settingsManager.sendCurrentSettingsToServer();
// Send problem to server
socketManager.send('solve_problem', {
text: text,
image: imageData,
session_id: sessionId
});
Logger.debug('App', 'Problem submitted for solving');
}
interruptSolving() {
Logger.debug('App', 'Interrupt button clicked');
socketManager.send('interrupt_solving');
domManager.updateStatus('Interrupting current task...', 'warning');
}
// Global method for message expansion (called from HTML)
toggleExpandMessage(button) {
messageManager.toggleExpandMessage(button);
}
// Global methods for session management (called from HTML)
get sessionManager() {
return sessionManager;
}
// Expose modules for debugging and external access
getModules() {
return {
domManager,
messageManager,
settingsManager,
sessionManager,
imageHandler,
socketEventHandlers,
appState,
socketManager,
storageManager
};
}
}
// Initialize application when DOM is ready
document.addEventListener('DOMContentLoaded', async () => {
Logger.log('DOM content loaded');
try {
const app = new PIPSApplication();
await app.initialize();
// Store app instance globally for debugging and HTML callbacks
window.pipsApp = app;
// Also expose key functions globally for HTML access
window.toggleExpandMessage = (button) => app.toggleExpandMessage(button);
} catch (error) {
Logger.error('Failed to initialize PIPS application:', error);
}
});
|