`;
this.createWindow('Windows Media Player', content, '🎧', '500px', '300px');
}
openNotepad(fileName = null) {
let initialContent = '';
if (fileName) {
const file = this.vfs.getFile(fileName);
if (file) initialContent = file.content;
}
const id = this.createWindow('Notepad - ' + (fileName || 'Nou'), `
`, '📝', '500px', '350px');
window._notepadFile = fileName;
}
saveNotepad(currentFile) {
const text = document.getElementById('notepadText')?.value;
if (!text) return;
let fileName = currentFile;
if (!fileName) {
fileName = prompt('Nume fișier:', 'document.txt');
if (!fileName) return;
}
this.vfs.createFile(fileName, text);
this.notify('📄 Fișier salvat');
this.saveState();
}
loadNotepad() {
const fileName = prompt('Nume fișier de deschis:');
if (fileName) {
this.openNotepad(fileName);
}
}
openCalculator() {
const id = this.createWindow('Calculator', `
${['7','8','9','/','4','5','6','*','1','2','3','-','0','.','=','+'].map(c =>
``
).join('')}
`, '🔢', '300px', '280px');
this.calcExpr = '';
}
calcInput(char) {
if (char === '=') {
try {
this.calcExpr = eval(this.calcExpr).toString();
} catch { this.calcExpr = 'Eroare'; }
} else {
this.calcExpr += char;
}
const disp = document.getElementById('calcDisplay');
if (disp) disp.value = this.calcExpr;
}
calcClear() {
this.calcExpr = '';
const disp = document.getElementById('calcDisplay');
if (disp) disp.value = '';
}
calcSqrt() {
try {
this.calcExpr = Math.sqrt(eval(this.calcExpr)).toString();
} catch { this.calcExpr = 'Eroare'; }
const disp = document.getElementById('calcDisplay');
if (disp) disp.value = this.calcExpr;
}
openPaint() {
const id = this.createWindow('Paint', `
`, '🎨', '550px', '400px');
setTimeout(() => {
const canvas = document.getElementById('paintCanvas');
if (!canvas) return;
const ctx = canvas.getContext('2d');
let painting = false;
canvas.onmousedown = e => { painting = true; ctx.beginPath(); ctx.moveTo(e.offsetX, e.offsetY); };
canvas.onmousemove = e => {
if (!painting) return;
ctx.lineTo(e.offsetX, e.offsetY);
ctx.strokeStyle = document.getElementById('paintColor').value;
ctx.lineWidth = 2;
ctx.stroke();
};
canvas.onmouseup = () => painting = false;
canvas.onmouseleave = () => painting = false;
}, 100);
}
clearPaint() {
const canvas = document.getElementById('paintCanvas');
if (canvas) canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height);
}
savePaint() {
const canvas = document.getElementById('paintCanvas');
if (canvas) {
const link = document.createElement('a');
link.download = 'desen.png';
link.href = canvas.toDataURL();
link.click();
}
}
openMinesweeper() {
const size = 8, mines = 10;
let grid = Array(size).fill().map(() => Array(size).fill(false));
for (let i = 0; i < mines; i++) {
let x, y;
do { x = Math.floor(Math.random()*size); y = Math.floor(Math.random()*size); } while (grid[x][y]);
grid[x][y] = true;
}
let html = '';
for (let i = 0; i < size; i++) {
for (let j = 0; j < size; j++) {
html += ``;
}
}
html += '
';
this.createWindow('Minesweeper', html, '💣', '300px', '330px');
this.mineGrid = grid;
this.mineRevealed = Array(size).fill().map(() => Array(size).fill(false));
}
revealMine(x, y) {
if (this.mineRevealed[x][y]) return;
this.mineRevealed[x][y] = true;
const btn = document.getElementById(`m-${x}-${y}`);
if (this.mineGrid[x][y]) {
btn.textContent = '💣';
this.notify('Game Over!');
// Dezactivează toate butoanele
for (let i=0;i<8;i++) for(let j=0;j<8;j++) document.getElementById(`m-${i}-${j}`).disabled = true;
} else {
let count = 0;
for (let dx=-1;dx<=1;dx++) for (let dy=-1;dy<=1;dy++) {
const nx=x+dx, ny=y+dy;
if (nx>=0&&nx<8&&ny>=0&&ny<8&&this.mineGrid[nx][ny]) count++;
}
btn.textContent = count || '';
btn.disabled = true;
}
}
openSnake() {
const id = this.createWindow('Snake', `
Scor: 0
`, '🐍', '450px', '500px');
}
startSnake() {
const canvas = document.getElementById('snakeCanvas');
if (!canvas) return;
const ctx = canvas.getContext('2d');
const gridSize = 20, tile = canvas.width / gridSize;
let snake = [{x:10,y:10}], dir = {x:0,y:0}, food = {x:15,y:15}, score = 0;
let interval;
document.onkeydown = e => {
if (e.key === 'ArrowUp' && dir.y === 0) dir = {x:0,y:-1};
if (e.key === 'ArrowDown' && dir.y === 0) dir = {x:0,y:1};
if (e.key === 'ArrowLeft' && dir.x === 0) dir = {x:-1,y:0};
if (e.key === 'ArrowRight' && dir.x === 0) dir = {x:1,y:0};
};
function loop() {
const head = {x:snake[0].x+dir.x, y:snake[0].y+dir.y};
snake.unshift(head);
if (head.x === food.x && head.y === food.y) {
score += 10;
document.getElementById('snakeScore').textContent = score;
food = {x:Math.floor(Math.random()*gridSize), y:Math.floor(Math.random()*gridSize)};
} else snake.pop();
if (head.x<0||head.x>=gridSize||head.y<0||head.y>=gridSize) {
clearInterval(interval);
alert('Game Over! Scor: ' + score);
return;
}
ctx.fillStyle = '#000';
ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.fillStyle = '#0f0';
snake.forEach(s => ctx.fillRect(s.x*tile, s.y*tile, tile-2, tile-2));
ctx.fillStyle = '#f00';
ctx.fillRect(food.x*tile, food.y*tile, tile-2, tile-2);
}
interval = setInterval(loop, 100);
}
openExplorer() {
const content = `
`;
const id = this.createWindow('Windows Explorer', content, '📂', '600px', '400px');
this.renderExplorer();
}
renderExplorer() {
const tree = document.getElementById('explorerTree');
const content = document.getElementById('explorerContent');
if (!tree || !content) return;
const current = this.vfs.getCurrentFolder();
let treeHTML = '📁 C:\\';
for (let name in this.vfs.root.children) {
treeHTML += `- 📁 ${name}
`;
}
treeHTML += '
';
tree.innerHTML = treeHTML;
let items = '';
for (let name in current.children) {
const item = current.children[name];
const icon = item.type === 'folder' ? '📁' : '📄';
items += ``;
}
items += `
`;
content.innerHTML = items;
}
// ============ Task Manager ============
openTaskManager() {
let list = '';
document.querySelectorAll('.window').forEach(win => {
if (win.style.display !== 'none') {
const title = win.querySelector('.window-titlebar span:last-child').textContent;
list += ``;
}
});
this.createWindow('Task Manager', list || 'Nicio fereastră deschisă
', '📋', '350px', '250px');
}
// ============ Setări ============
openSettings() {
this.createWindow('Setări', `
WebOS Windows 98
Găzduit pe iprs.ro
`, '⚙️');
}
openThemeSettings() {
const btns = Object.keys(this.themes).map(t =>
``
).join('');
this.createWindow('Teme', btns, '🎨', '300px', '200px');
}
openScreenSaverSettings() {
const btns = [1,5,10,30].map(m =>
``
).join('');
this.createWindow('Screen Saver', btns + '
', '💤');
}
// ============ 4. SISTEM DE FIȘIERE VIRTUAL ============
initVFS() {
this.vfs = {
root: {
type: 'folder',
name: 'C:',
children: {
'Windows': { type:'folder', name:'Windows', children: { 'System':{type:'folder',name:'System',children:{}}, 'win.ini':{type:'file',name:'win.ini',content:'[windows]\nload=\nrun=',size:'0.5 KB'} } },
'Documente': { type:'folder', name:'Documente', children: { 'readme.txt':{type:'file',name:'readme.txt',content:'Bun venit!',size:'10 B'}, 'proiect.doc':{type:'file',name:'proiect.doc',content:'Proiect WebOS',size:'1 KB'} } },
'Program Files': { type:'folder', name:'Program Files', children: {} }
}
}
};
this.currentPath = ['root'];
}
getCurrentFolder() {
let cur = this.vfs.root;
for (let i=1; i document.addEventListener(ev, () => {
this.lastActivity = Date.now();
if (this.saverActive) {
this.stopScreenSaver();
this.resetSaverTimer();
}
}));
}
resetSaverTimer() {
if (this.saverTimer) clearTimeout(this.saverTimer);
this.saverTimer = setTimeout(() => {
if (Date.now() - this.lastActivity >= this.saverTimeout) this.activateScreenSaver();
}, this.saverTimeout);
}
activateScreenSaver() {
if (this.saverActive) return;
this.saverActive = true;
const el = document.createElement('div');
el.id = 'saver';
el.style = 'position:fixed;top:0;left:0;width:100%;height:100%;background:black;z-index:99999;cursor:none;';
const canvas = document.createElement('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
el.appendChild(canvas);
document.body.appendChild(el);
this.saverEl = el;
this.animateScreenSaver(canvas);
}
animateScreenSaver(canvas) {
const ctx = canvas.getContext('2d');
const stars = Array.from({length:100}, () => ({
x: Math.random()*canvas.width,
y: Math.random()*canvas.height,
speed: Math.random()*2+0.5,
size: Math.random()*3+1
}));
const draw = () => {
if (!this.saverActive) return;
ctx.fillStyle = 'rgba(0,0,0,0.1)';
ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.fillStyle = '#0f0';
stars.forEach(s => {
ctx.beginPath();
ctx.arc(s.x, s.y, s.size, 0, Math.PI*2);
ctx.fill();
s.y += s.speed;
if (s.y > canvas.height) { s.y = 0; s.x = Math.random()*canvas.width; }
});
requestAnimationFrame(draw);
};
draw();
}
stopScreenSaver() {
if (this.saverEl) {
this.saverEl.remove();
this.saverEl = null;
}
this.saverActive = false;
}
setSaverTimeout(minutes) {
this.saverTimeout = minutes * 60 * 1000;
this.resetSaverTimer();
this.saveState();
this.notify(`⏰ Screen saver: ${minutes} minute`);
}
// ============ INTERFAȚA DESKTOP ============
initDesktopIcons() {
const icons = [
{ name: 'Computer', icon: '💻', action: 'computer' },
{ name: 'Documente', icon: '📁', action: 'documents' },
{ name: 'Muzică', icon: '🎵', action: 'music' },
{ name: 'Arhive', icon: '📦', action: 'archive' },
{ name: 'Media Player', icon: '🎧', action: 'player' },
{ name: 'Notepad', icon: '📝', action: 'notepad' },
{ name: 'Calculator', icon: '🔢', action: 'calculator' },
{ name: 'Paint', icon: '🎨', action: 'paint' },
{ name: 'Minesweeper', icon: '💣', action: 'minesweeper' },
{ name: 'Snake', icon: '🐍', action: 'snake' },
{ name: 'Explorer', icon: '📂', action: 'explorer' },
{ name: 'Task Manager', icon: '📋', action: 'taskmgr' },
{ name: 'Setări', icon: '⚙️', action: 'settings' }
];
const desktop = document.getElementById('desktop');
icons.forEach(item => {
const div = document.createElement('div');
div.className = 'desktop-icon';
div.innerHTML = `${item.icon}
${item.name}`;
div.ondblclick = () => this.openApp(item.action);
desktop.appendChild(div);
});
}
initStartMenu() {
const menu = document.getElementById('startMenuItems');
const items = [
{ text: 'Computer', icon: '💻', action: 'computer' },
{ text: 'Documente', icon: '📁', action: 'documents' },
{ text: 'Muzică', icon: '🎵', action: 'music' },
{ text: 'Arhive', icon: '📦', action: 'archive' },
{ type: 'separator' },
{ text: 'Media Player', icon: '🎧', action: 'player' },
{ text: 'Notepad', icon: '📝', action: 'notepad' },
{ text: 'Calculator', icon: '🔢', action: 'calculator' },
{ text: 'Paint', icon: '🎨', action: 'paint' },
{ type: 'separator' },
{ text: 'Minesweeper', icon: '💣', action: 'minesweeper' },
{ text: 'Snake', icon: '🐍', action: 'snake' },
{ text: 'Explorer', icon: '📂', action: 'explorer' },
{ text: 'Task Manager', icon: '📋', action: 'taskmgr' },
{ type: 'separator' },
{ text: 'Setări', icon: '⚙️', action: 'settings' },
{ text: 'Teme', icon: '🎨', action: 'theme' },
{ text: 'Screen Saver', icon: '💤', action: 'screensaver' },
{ text: 'Sunet ON/OFF', icon: '🔊', action: 'toggleSound' },
{ text: 'Salvează starea', icon: '💾', action: 'saveState' }
];
items.forEach(item => {
if (item.type === 'separator') {
const sep = document.createElement('div');
sep.className = 'separator';
menu.appendChild(sep);
} else {
const div = document.createElement('div');
div.className = 'menu-item';
div.innerHTML = `${item.icon} ${item.text}`;
div.onclick = () => {
if (item.action === 'toggleSound') this.toggleSound();
else if (item.action === 'saveState') this.saveState();
else this.openApp(item.action);
this.toggleStartMenu(false);
};
menu.appendChild(div);
}
});
}
toggleStartMenu(show = null) {
const menu = document.getElementById('start-menu');
if (show === null) show = menu.style.display === 'none';
menu.style.display = show ? 'block' : 'none';
this.startMenuOpen = show;
}
initEventListeners() {
document.getElementById('startBtn').addEventListener('click', (e) => {
e.stopPropagation();
this.toggleStartMenu();
});
document.addEventListener('click', (e) => {
if (!e.target.closest('.start-menu') && !e.target.closest('#startBtn')) {
this.toggleStartMenu(false);
}
});
document.getElementById('soundToggle').addEventListener('click', () => this.toggleSound());
}
startClock() {
const update = () => {
const d = new Date();
document.getElementById('clock').textContent = d.getHours().toString().padStart(2,'0') + ':' + d.getMinutes().toString().padStart(2,'0');
};
update();
setInterval(update, 1000);
}
notify(msg) {
const n = document.createElement('div');
n.className = 'notification';
n.textContent = msg;
document.body.appendChild(n);
setTimeout(() => n.remove(), 3000);
}
}
// Inițializare globală
const webOS = new WebOS();
// Expune pentru onclick din HTML
window.webOS = webOS;