CatPortal / modules /EventHandler.js
NikaMimi's picture
Upload 17 files
06163ac verified
/**
* CatOS Event Handler Module
* Manages all user interactions and system events
*/
class EventHandler {
constructor(core) {
this.core = core;
}
setup(core) {
this.core = core;
// Desktop icon interactions
document.querySelectorAll('.desktop-icon').forEach(icon => {
icon.addEventListener('dblclick', this.handleIconDoubleClick.bind(this));
icon.addEventListener('click', this.handleIconClick.bind(this));
});
// Start button
document.getElementById('start-button').addEventListener('click', this.toggleStartMenu.bind(this));
// Start menu apps
document.querySelectorAll('.menu-app').forEach(app => {
app.addEventListener('click', this.handleMenuAppClick.bind(this));
});
// Desktop context menu
document.getElementById('desktop').addEventListener('contextmenu', this.showContextMenu.bind(this));
// Close context menu on click
document.addEventListener('click', this.hideContextMenu.bind(this));
// Close start menu on outside click
document.addEventListener('click', (e) => {
if (!e.target.closest('.start-button') && !e.target.closest('.start-menu')) {
this.hideStartMenu();
}
});
// Keyboard shortcuts
document.addEventListener('keydown', this.handleKeyboard.bind(this));
// Window container clicks (deselect icons)
document.getElementById('windows-container').addEventListener('click', (e) => {
if (e.target.id === 'windows-container') {
this.deselectAllIcons();
}
});
// Context menu actions
document.querySelectorAll('.context-item').forEach(item => {
item.addEventListener('click', this.handleContextMenuAction.bind(this));
});
}
// Icon interactions
handleIconClick(e) {
this.deselectAllIcons();
e.currentTarget.classList.add('selected');
// Add cat-like feedback
e.currentTarget.style.transform = 'scale(0.95)';
setTimeout(() => {
e.currentTarget.style.transform = '';
}, 150);
}
handleIconDoubleClick(e) {
const icon = e.currentTarget;
const appType = icon.dataset.app;
const projectId = icon.dataset.project;
// Add launch animation
icon.style.animation = 'bounce 0.5s ease';
setTimeout(() => {
icon.style.animation = '';
}, 500);
if (appType === 'project-viewer' && projectId) {
this.core.appManager.launchApp('project-viewer', { projectId });
} else {
this.core.appManager.launchApp(appType);
}
}
deselectAllIcons() {
document.querySelectorAll('.desktop-icon.selected').forEach(icon => {
icon.classList.remove('selected');
});
}
// Start Menu Management
toggleStartMenu() {
const menu = document.getElementById('start-menu');
const button = document.getElementById('start-button');
if (this.core.startMenuOpen) {
this.hideStartMenu();
} else {
menu.classList.add('show');
button.classList.add('active');
this.core.startMenuOpen = true;
}
}
hideStartMenu() {
const menu = document.getElementById('start-menu');
const button = document.getElementById('start-button');
menu.classList.remove('show');
button.classList.remove('active');
this.core.startMenuOpen = false;
}
handleMenuAppClick(e) {
const app = e.currentTarget;
const appType = app.dataset.app;
// Close start menu with animation
this.hideStartMenu();
// Small delay for better UX
setTimeout(() => {
this.core.appManager.launchApp(appType);
}, 150);
}
// Context Menu
showContextMenu(e) {
e.preventDefault();
const contextMenu = document.getElementById('context-menu');
contextMenu.style.left = e.clientX + 'px';
contextMenu.style.top = e.clientY + 'px';
contextMenu.classList.add('show');
// Ensure menu stays within viewport
const rect = contextMenu.getBoundingClientRect();
if (rect.right > window.innerWidth) {
contextMenu.style.left = (window.innerWidth - rect.width - 10) + 'px';
}
if (rect.bottom > window.innerHeight) {
contextMenu.style.top = (window.innerHeight - rect.height - 10) + 'px';
}
}
hideContextMenu(e) {
const contextMenu = document.getElementById('context-menu');
if (!e.target.closest('.context-menu')) {
contextMenu.classList.remove('show');
}
}
handleContextMenuAction(e) {
const action = e.currentTarget.dataset.action;
switch(action) {
case 'refresh':
this.refreshDesktop();
break;
case 'new-folder':
this.createNewFolder();
break;
case 'properties':
this.showDesktopProperties();
break;
}
this.hideContextMenu({ target: document.body });
}
refreshDesktop() {
this.core.setRandomWallpaper();
this.core.showNotification('πŸ”„ Desktop Refreshed', 'New wallpaper loaded! Looking purrfect! 😸');
}
createNewFolder() {
this.core.showNotification('πŸ“ Feature Coming Soon', 'Folder creation will be available in the next CatOS update! πŸ±β€πŸ’»');
}
showDesktopProperties() {
this.core.appManager.launchApp('about');
}
// Keyboard shortcuts
handleKeyboard(e) {
// System shortcuts
if (e.ctrlKey || e.metaKey) {
switch(e.key) {
case '`': // Ctrl+` opens terminal
e.preventDefault();
this.core.appManager.launchApp('terminal');
break;
case 'r': // Ctrl+R refreshes desktop
if (e.target.tagName !== 'INPUT' && e.target.tagName !== 'TEXTAREA') {
e.preventDefault();
this.refreshDesktop();
}
break;
}
}
// Special keys
switch(e.key) {
case 'F1':
e.preventDefault();
this.core.appManager.launchApp('about');
break;
case 'F5':
e.preventDefault();
this.refreshDesktop();
break;
case 'Delete':
// Delete selected desktop items (if any)
const selected = document.querySelector('.desktop-icon.selected');
if (selected) {
this.core.showNotification('πŸ—‘οΈ Cannot Delete', 'System items are protected by cat law! 😹');
}
break;
case 'Escape':
// Close context menu and start menu
this.hideContextMenu({ target: document.body });
if (this.core.startMenuOpen) {
this.hideStartMenu();
}
break;
}
// Easter eggs
this.handleEasterEggs(e);
}
handleEasterEggs(e) {
// Konami code for cats: ↑↑↓↓←→←→BA
if (!this.konamiSequence) {
this.konamiSequence = [];
}
const konamiCode = ['ArrowUp', 'ArrowUp', 'ArrowDown', 'ArrowDown',
'ArrowLeft', 'ArrowRight', 'ArrowLeft', 'ArrowRight', 'KeyB', 'KeyA'];
if (e.code === konamiCode[this.konamiSequence.length]) {
this.konamiSequence.push(e.code);
if (this.konamiSequence.length === konamiCode.length) {
this.activateCatMode();
this.konamiSequence = [];
}
} else {
this.konamiSequence = [];
}
// Cat sound effects
if (e.key === 'm' && !e.target.matches('input, textarea')) {
this.playMeowSound();
}
}
activateCatMode() {
this.core.showNotification('πŸŽ‰ Cat Mode Activated!', 'You found the secret cat code! Enjoy the purr-ks! 😸');
// Add some fun visual effects
document.body.style.animation = 'rainbow 2s infinite';
// Add temporary CSS for rainbow effect
if (!document.getElementById('cat-mode-styles')) {
const style = document.createElement('style');
style.id = 'cat-mode-styles';
style.textContent = `
@keyframes rainbow {
0% { filter: hue-rotate(0deg); }
100% { filter: hue-rotate(360deg); }
}
`;
document.head.appendChild(style);
}
// Reset after 5 seconds
setTimeout(() => {
document.body.style.animation = '';
}, 5000);
}
playMeowSound() {
// Visual feedback for meow (since we can't guarantee audio)
const meows = ['😸', 'πŸ™€', '😻', '😹', '😾', '🐱'];
const meow = meows[Math.floor(Math.random() * meows.length)];
const meowElement = document.createElement('div');
meowElement.textContent = meow;
meowElement.style.cssText = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 3rem;
z-index: 9999;
pointer-events: none;
animation: meowPop 1s ease forwards;
`;
// Add meow animation CSS if not already present
if (!document.getElementById('meow-styles')) {
const style = document.createElement('style');
style.id = 'meow-styles';
style.textContent = `
@keyframes meowPop {
0% { transform: translate(-50%, -50%) scale(0); opacity: 1; }
50% { transform: translate(-50%, -50%) scale(1.2); opacity: 1; }
100% { transform: translate(-50%, -50%) scale(1.5); opacity: 0; }
}
`;
document.head.appendChild(style);
}
document.body.appendChild(meowElement);
setTimeout(() => {
if (meowElement.parentNode) {
meowElement.parentNode.removeChild(meowElement);
}
}, 1000);
}
}
// Export for use in main system
window.CatOSEventHandler = EventHandler;