|
|
|
|
|
|
|
|
|
|
|
|
|
|
class EventHandler { |
|
|
constructor(core) { |
|
|
this.core = core; |
|
|
} |
|
|
|
|
|
setup(core) { |
|
|
this.core = core; |
|
|
|
|
|
|
|
|
document.querySelectorAll('.desktop-icon').forEach(icon => { |
|
|
icon.addEventListener('dblclick', this.handleIconDoubleClick.bind(this)); |
|
|
icon.addEventListener('click', this.handleIconClick.bind(this)); |
|
|
}); |
|
|
|
|
|
|
|
|
document.getElementById('start-button').addEventListener('click', this.toggleStartMenu.bind(this)); |
|
|
|
|
|
|
|
|
document.querySelectorAll('.menu-app').forEach(app => { |
|
|
app.addEventListener('click', this.handleMenuAppClick.bind(this)); |
|
|
}); |
|
|
|
|
|
|
|
|
document.getElementById('desktop').addEventListener('contextmenu', this.showContextMenu.bind(this)); |
|
|
|
|
|
|
|
|
document.addEventListener('click', this.hideContextMenu.bind(this)); |
|
|
|
|
|
|
|
|
document.addEventListener('click', (e) => { |
|
|
if (!e.target.closest('.start-button') && !e.target.closest('.start-menu')) { |
|
|
this.hideStartMenu(); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
document.addEventListener('keydown', this.handleKeyboard.bind(this)); |
|
|
|
|
|
|
|
|
document.getElementById('windows-container').addEventListener('click', (e) => { |
|
|
if (e.target.id === 'windows-container') { |
|
|
this.deselectAllIcons(); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
document.querySelectorAll('.context-item').forEach(item => { |
|
|
item.addEventListener('click', this.handleContextMenuAction.bind(this)); |
|
|
}); |
|
|
} |
|
|
|
|
|
|
|
|
handleIconClick(e) { |
|
|
this.deselectAllIcons(); |
|
|
e.currentTarget.classList.add('selected'); |
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
|
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'); |
|
|
}); |
|
|
} |
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
|
this.hideStartMenu(); |
|
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
this.core.appManager.launchApp(appType); |
|
|
}, 150); |
|
|
} |
|
|
|
|
|
|
|
|
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'); |
|
|
|
|
|
|
|
|
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'); |
|
|
} |
|
|
|
|
|
|
|
|
handleKeyboard(e) { |
|
|
|
|
|
if (e.ctrlKey || e.metaKey) { |
|
|
switch(e.key) { |
|
|
case '`': |
|
|
e.preventDefault(); |
|
|
this.core.appManager.launchApp('terminal'); |
|
|
break; |
|
|
case 'r': |
|
|
if (e.target.tagName !== 'INPUT' && e.target.tagName !== 'TEXTAREA') { |
|
|
e.preventDefault(); |
|
|
this.refreshDesktop(); |
|
|
} |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
switch(e.key) { |
|
|
case 'F1': |
|
|
e.preventDefault(); |
|
|
this.core.appManager.launchApp('about'); |
|
|
break; |
|
|
case 'F5': |
|
|
e.preventDefault(); |
|
|
this.refreshDesktop(); |
|
|
break; |
|
|
case 'Delete': |
|
|
|
|
|
const selected = document.querySelector('.desktop-icon.selected'); |
|
|
if (selected) { |
|
|
this.core.showNotification('ποΈ Cannot Delete', 'System items are protected by cat law! πΉ'); |
|
|
} |
|
|
break; |
|
|
case 'Escape': |
|
|
|
|
|
this.hideContextMenu({ target: document.body }); |
|
|
if (this.core.startMenuOpen) { |
|
|
this.hideStartMenu(); |
|
|
} |
|
|
break; |
|
|
} |
|
|
|
|
|
|
|
|
this.handleEasterEggs(e); |
|
|
} |
|
|
|
|
|
handleEasterEggs(e) { |
|
|
|
|
|
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 = []; |
|
|
} |
|
|
|
|
|
|
|
|
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! πΈ'); |
|
|
|
|
|
|
|
|
document.body.style.animation = 'rainbow 2s infinite'; |
|
|
|
|
|
|
|
|
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); |
|
|
} |
|
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
document.body.style.animation = ''; |
|
|
}, 5000); |
|
|
} |
|
|
|
|
|
playMeowSound() { |
|
|
|
|
|
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; |
|
|
`; |
|
|
|
|
|
|
|
|
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); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
window.CatOSEventHandler = EventHandler; |