Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>BrowserOS</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
<script> | |
tailwind.config = { | |
theme: { | |
extend: { | |
colors: { | |
'os-primary': '#4f46e5', | |
'os-secondary': '#6366f1', | |
'os-dark': '#1e293b', | |
'os-darker': '#0f172a', | |
'os-light': '#f1f5f9', | |
'os-accent': '#8b5cf6' | |
} | |
} | |
} | |
} | |
</script> | |
<style> | |
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); | |
* { | |
margin: 0; | |
padding: 0; | |
box-sizing: border-box; | |
font-family: 'Inter', sans-serif; | |
user-select: none; | |
} | |
body { | |
overflow: hidden; | |
background-color: #0f172a; | |
height: 100vh; | |
width: 100vw; | |
} | |
#desktop { | |
background-image: url('https://images.unsplash.com/photo-1505506874110-0a3a6a03b9c3?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1887&q=80'); | |
background-size: cover; | |
background-position: center; | |
height: calc(100vh - 50px); | |
position: relative; | |
overflow: hidden; | |
} | |
.desktop-icon { | |
position: absolute; | |
width: 80px; | |
height: 80px; | |
display: flex; | |
flex-direction: column; | |
align-items: center; | |
justify-content: center; | |
cursor: pointer; | |
transition: all 0.2s ease; | |
text-align: center; | |
color: white; | |
text-shadow: 0 1px 3px rgba(0,0,0,0.5); | |
} | |
.desktop-icon:hover { | |
background: rgba(255,255,255,0.1); | |
border-radius: 5px; | |
} | |
.desktop-icon i { | |
font-size: 32px; | |
margin-bottom: 5px; | |
} | |
.desktop-icon span { | |
font-size: 12px; | |
font-weight: 500; | |
} | |
.window { | |
position: absolute; | |
border-radius: 8px; | |
overflow: hidden; | |
box-shadow: 0 10px 30px rgba(0,0,0,0.2); | |
display: flex; | |
flex-direction: column; | |
min-width: 400px; | |
min-height: 300px; | |
background: #f8fafc; | |
resize: both; | |
overflow: auto; | |
} | |
.window-header { | |
background: linear-gradient(to right, #4f46e5, #6366f1); | |
color: white; | |
padding: 8px 12px; | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
cursor: move; | |
} | |
.window-title { | |
font-weight: 600; | |
font-size: 14px; | |
display: flex; | |
align-items: center; | |
gap: 8px; | |
} | |
.window-controls { | |
display: flex; | |
gap: 8px; | |
} | |
.window-control { | |
width: 30px; | |
height: 30px; | |
border-radius: 50%; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
cursor: pointer; | |
transition: all 0.2s ease; | |
} | |
.window-control:hover { | |
background: rgba(255,255,255,0.2); | |
} | |
.window-content { | |
flex: 1; | |
padding: 15px; | |
overflow: auto; | |
} | |
#taskbar { | |
height: 50px; | |
background: rgba(30, 41, 59, 0.9); | |
backdrop-filter: blur(10px); | |
display: flex; | |
align-items: center; | |
padding: 0 10px; | |
position: relative; | |
z-index: 1000; | |
} | |
#start-menu-btn { | |
background: linear-gradient(to right, #4f46e5, #6366f1); | |
color: white; | |
border: none; | |
border-radius: 5px; | |
padding: 5px 15px; | |
display: flex; | |
align-items: center; | |
gap: 8px; | |
font-weight: 500; | |
cursor: pointer; | |
transition: all 0.2s ease; | |
} | |
#start-menu-btn:hover { | |
transform: scale(1.05); | |
} | |
#app-tray { | |
display: flex; | |
gap: 5px; | |
margin-left: 15px; | |
} | |
.tray-app { | |
width: 40px; | |
height: 40px; | |
border-radius: 5px; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
color: white; | |
background: rgba(255,255,255,0.1); | |
cursor: pointer; | |
transition: all 0.2s ease; | |
} | |
.tray-app:hover { | |
background: rgba(255,255,255,0.2); | |
} | |
.tray-app.active { | |
background: rgba(79, 70, 229, 0.5); | |
} | |
#system-tray { | |
margin-left: auto; | |
display: flex; | |
align-items: center; | |
gap: 10px; | |
color: white; | |
padding: 0 10px; | |
} | |
.tray-icon { | |
padding: 5px; | |
cursor: pointer; | |
border-radius: 3px; | |
transition: all 0.2s ease; | |
} | |
.tray-icon:hover { | |
background: rgba(255,255,255,0.1); | |
} | |
#clock { | |
font-size: 14px; | |
font-weight: 500; | |
} | |
#start-menu { | |
position: absolute; | |
bottom: 50px; | |
left: 10px; | |
width: 350px; | |
height: 450px; | |
background: rgba(30, 41, 59, 0.95); | |
backdrop-filter: blur(10px); | |
border-radius: 10px; | |
box-shadow: 0 10px 30px rgba(0,0,0,0.3); | |
display: none; | |
flex-direction: column; | |
overflow: hidden; | |
z-index: 999; | |
} | |
.app-grid { | |
display: grid; | |
grid-template-columns: repeat(3, 1fr); | |
gap: 15px; | |
padding: 20px; | |
flex: 1; | |
} | |
.app-item { | |
display: flex; | |
flex-direction: column; | |
align-items: center; | |
justify-content: center; | |
gap: 8px; | |
color: white; | |
padding: 15px 5px; | |
border-radius: 8px; | |
cursor: pointer; | |
transition: all 0.2s ease; | |
} | |
.app-item:hover { | |
background: rgba(255,255,255,0.1); | |
} | |
.app-item i { | |
font-size: 28px; | |
} | |
.app-item span { | |
font-size: 12px; | |
font-weight: 500; | |
} | |
.file-item { | |
display: flex; | |
align-items: center; | |
padding: 8px 12px; | |
border-radius: 5px; | |
cursor: pointer; | |
transition: all 0.2s ease; | |
} | |
.file-item:hover { | |
background: #e2e8f0; | |
} | |
.context-menu { | |
position: absolute; | |
background: white; | |
border-radius: 5px; | |
box-shadow: 0 5px 15px rgba(0,0,0,0.2); | |
min-width: 200px; | |
z-index: 1001; | |
display: none; | |
} | |
.context-menu-item { | |
padding: 8px 15px; | |
cursor: pointer; | |
transition: all 0.2s ease; | |
display: flex; | |
align-items: center; | |
gap: 8px; | |
} | |
.context-menu-item:hover { | |
background: #f1f5f9; | |
} | |
.tab-container { | |
display: flex; | |
border-bottom: 1px solid #cbd5e1; | |
padding: 0 15px; | |
} | |
.tab { | |
padding: 10px 20px; | |
cursor: pointer; | |
border-bottom: 2px solid transparent; | |
transition: all 0.2s ease; | |
} | |
.tab.active { | |
border-bottom: 2px solid #4f46e5; | |
color: #4f46e5; | |
font-weight: 500; | |
} | |
.tab-content { | |
display: none; | |
} | |
.tab-content.active { | |
display: block; | |
} | |
.file-grid { | |
display: grid; | |
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); | |
gap: 15px; | |
padding: 15px; | |
} | |
.file-grid-item { | |
display: flex; | |
flex-direction: column; | |
align-items: center; | |
gap: 5px; | |
padding: 10px; | |
border-radius: 5px; | |
cursor: pointer; | |
transition: all 0.2s ease; | |
} | |
.file-grid-item:hover { | |
background: #e2e8f0; | |
} | |
.file-grid-item i { | |
font-size: 32px; | |
} | |
.file-grid-item span { | |
font-size: 12px; | |
text-align: center; | |
word-break: break-word; | |
} | |
.settings-grid { | |
display: grid; | |
grid-template-columns: repeat(2, 1fr); | |
gap: 15px; | |
padding: 15px; | |
} | |
.wallpaper-preview { | |
width: 100%; | |
aspect-ratio: 16/9; | |
border-radius: 5px; | |
overflow: hidden; | |
cursor: pointer; | |
border: 2px solid transparent; | |
transition: all 0.2s ease; | |
} | |
.wallpaper-preview:hover { | |
transform: scale(1.03); | |
} | |
.wallpaper-preview.selected { | |
border-color: #4f46e5; | |
} | |
.wallpaper-preview img { | |
width: 100%; | |
height: 100%; | |
object-fit: cover; | |
} | |
.editor-toolbar { | |
display: flex; | |
gap: 5px; | |
padding: 8px; | |
background: #e2e8f0; | |
border-bottom: 1px solid #cbd5e1; | |
} | |
.editor-btn { | |
padding: 5px 10px; | |
border-radius: 3px; | |
background: white; | |
border: 1px solid #cbd5e1; | |
cursor: pointer; | |
transition: all 0.2s ease; | |
} | |
.editor-btn:hover { | |
background: #f1f5f9; | |
} | |
#editor-content { | |
width: 100%; | |
height: 100%; | |
padding: 15px; | |
border: none; | |
resize: none; | |
font-family: 'Inter', sans-serif; | |
font-size: 14px; | |
} | |
#editor-content:focus { | |
outline: none; | |
} | |
.browser-nav { | |
display: flex; | |
gap: 10px; | |
padding: 10px; | |
background: #e2e8f0; | |
border-bottom: 1px solid #cbd5e1; | |
} | |
.browser-input { | |
flex: 1; | |
padding: 8px 15px; | |
border-radius: 20px; | |
border: 1px solid #cbd5e1; | |
} | |
.browser-btn { | |
padding: 8px 15px; | |
border-radius: 5px; | |
background: #4f46e5; | |
color: white; | |
border: none; | |
cursor: pointer; | |
} | |
#browser-frame { | |
flex: 1; | |
border: none; | |
} | |
.minimized-window { | |
opacity: 0.7; | |
} | |
.window.snapped-left { | |
width: 50% ; | |
height: calc(100vh - 50px) ; | |
top: 0 ; | |
left: 0 ; | |
resize: none; | |
} | |
.window.snapped-right { | |
width: 50% ; | |
height: calc(100vh - 50px) ; | |
top: 0 ; | |
left: 50% ; | |
resize: none; | |
} | |
.window.maximized { | |
width: 100% ; | |
height: calc(100vh - 50px) ; | |
top: 0 ; | |
left: 0 ; | |
resize: none; | |
} | |
.window.maximized .window-control.maximize i:before { | |
content: "\f2d0"; | |
} | |
@media (max-width: 768px) { | |
.window { | |
min-width: 300px; | |
min-height: 250px; | |
} | |
#start-menu { | |
width: 300px; | |
height: 400px; | |
} | |
.app-grid { | |
grid-template-columns: repeat(2, 1fr); | |
} | |
} | |
</style> | |
</head> | |
<body> | |
<!-- Desktop with icons --> | |
<div id="desktop"> | |
<div class="desktop-icon" style="top: 20px; left: 20px;" data-app="file-manager"> | |
<i class="fas fa-folder"></i> | |
<span>Files</span> | |
</div> | |
<div class="desktop-icon" style="top: 20px; left: 120px;" data-app="text-editor"> | |
<i class="fas fa-file-alt"></i> | |
<span>Notes</span> | |
</div> | |
<div class="desktop-icon" style="top: 120px; left: 20px;" data-app="browser"> | |
<i class="fas fa-globe"></i> | |
<span>Browser</span> | |
</div> | |
<div class="desktop-icon" style="top: 120px; left: 120px;" data-app="settings"> | |
<i class="fas fa-cog"></i> | |
<span>Settings</span> | |
</div> | |
<!-- Windows will be appended here dynamically --> | |
</div> | |
<!-- Taskbar --> | |
<div id="taskbar"> | |
<button id="start-menu-btn"> | |
<i class="fas fa-logo"></i> | |
<span>Start</span> | |
</button> | |
<div id="app-tray"> | |
<!-- App icons will be added here when apps are opened --> | |
</div> | |
<div id="system-tray"> | |
<div class="tray-icon" id="wifi-icon" title="WiFi: Connected"> | |
<i class="fas fa-wifi"></i> | |
</div> | |
<div class="tray-icon" id="volume-icon" title="Volume: 75%"> | |
<i class="fas fa-volume-up"></i> | |
<div class="volume-control hidden absolute bottom-10 right-0 bg-white p-3 rounded shadow-lg w-40"> | |
<input type="range" min="0" max="100" value="75" class="w-full"> | |
</div> | |
</div> | |
<div class="tray-icon" id="battery-icon" title="Battery: 85%"> | |
<i class="fas fa-battery-three-quarters"></i> | |
</div> | |
<div id="clock">10:30 AM</div> | |
</div> | |
</div> | |
<!-- Start Menu --> | |
<div id="start-menu"> | |
<div class="bg-gradient-to-r from-os-primary to-os-secondary p-4 text-white"> | |
<div class="text-xl font-bold">BrowserOS</div> | |
<div class="text-sm opacity-80">v1.0.0</div> | |
</div> | |
<div class="app-grid"> | |
<div class="app-item" data-app="file-manager"> | |
<i class="fas fa-folder"></i> | |
<span>File Manager</span> | |
</div> | |
<div class="app-item" data-app="text-editor"> | |
<i class="fas fa-file-alt"></i> | |
<span>Text Editor</span> | |
</div> | |
<div class="app-item" data-app="browser"> | |
<i class="fas fa-globe"></i> | |
<span>Web Browser</span> | |
</div> | |
<div class="app-item" data-app="settings"> | |
<i class="fas fa-cog"></i> | |
<span>Settings</span> | |
</div> | |
<div class="app-item" data-app="terminal"> | |
<i class="fas fa-terminal"></i> | |
<span>Terminal</span> | |
</div> | |
<div class="app-item" data-app="calculator"> | |
<i class="fas fa-calculator"></i> | |
<span>Calculator</span> | |
</div> | |
</div> | |
<div class="mt-auto bg-os-dark p-3 text-white flex justify-between"> | |
<div class="flex items-center gap-2"> | |
<i class="fas fa-user"></i> | |
<span>User</span> | |
</div> | |
<div class="flex items-center gap-2"> | |
<i class="fas fa-power-off"></i> | |
<span>Power</span> | |
</div> | |
</div> | |
</div> | |
<!-- Notifications --> | |
<div id="notifications" class="fixed bottom-16 right-4 w-80 z-1002"></div> | |
<!-- Power Menu --> | |
<div id="power-menu" class="fixed bottom-16 left-4 bg-white rounded-lg shadow-lg p-2 hidden z-1001"> | |
<div class="power-option p-2 hover:bg-gray-100 rounded cursor-pointer"> | |
<i class="fas fa-moon mr-2"></i> Sleep | |
</div> | |
<div class="power-option p-2 hover:bg-gray-100 rounded cursor-pointer"> | |
<i class="fas fa-redo mr-2"></i> Restart | |
</div> | |
<div class="power-option p-2 hover:bg-gray-100 rounded cursor-pointer text-red-500"> | |
<i class="fas fa-power-off mr-2"></i> Shut Down | |
</div> | |
</div> | |
<!-- Context Menu --> | |
<div class="context-menu"> | |
<div class="context-menu-item" id="context-new-folder"> | |
<i class="fas fa-folder-plus"></i> | |
<span>New Folder</span> | |
</div> | |
<div class="context-menu-item" id="context-new-file"> | |
<i class="fas fa-file"></i> | |
<span>New File</span> | |
</div> | |
<div class="context-menu-divider border-t border-gray-200 my-1"></div> | |
<div class="context-menu-item" id="context-cut"> | |
<i class="fas fa-cut"></i> | |
<span>Cut</span> | |
</div> | |
<div class="context-menu-item" id="context-copy"> | |
<i class="fas fa-copy"></i> | |
<span>Copy</span> | |
</div> | |
<div class="context-menu-item" id="context-paste"> | |
<i class="fas fa-paste"></i> | |
<span>Paste</span> | |
</div> | |
<div class="context-menu-divider border-t border-gray-200 my-1"></div> | |
<div class="context-menu-item" id="context-refresh"> | |
<i class="fas fa-sync"></i> | |
<span>Refresh</span> | |
</div> | |
<div class="context-menu-item" id="context-properties"> | |
<i class="fas fa-info-circle"></i> | |
<span>Properties</span> | |
</div> | |
</div> | |
<!-- File Manager Template --> | |
<template id="file-manager-template"> | |
<div class="window"> | |
<div class="window-header"> | |
<div class="window-title"> | |
<i class="fas fa-folder"></i> | |
<span>File Manager</span> | |
</div> | |
<div class="window-controls"> | |
<div class="window-control minimize"> | |
<i class="fas fa-minus"></i> | |
</div> | |
<div class="window-control maximize"> | |
<i class="fas fa-square"></i> | |
</div> | |
<div class="window-control close"> | |
<i class="fas fa-times"></i> | |
</div> | |
</div> | |
</div> | |
<div class="window-content"> | |
<div class="tab-container"> | |
<div class="tab active" data-tab="home">Home</div> | |
<div class="tab" data-tab="documents">Documents</div> | |
<div class="tab" data-tab="pictures">Pictures</div> | |
<div class="tab" data-tab="downloads">Downloads</div> | |
</div> | |
<div class="tab-content active" id="home-tab"> | |
<div class="file-grid"> | |
<div class="file-grid-item"> | |
<i class="fas fa-folder text-yellow-500"></i> | |
<span>Documents</span> | |
</div> | |
<div class="file-grid-item"> | |
<i class="fas fa-folder text-blue-500"></i> | |
<span>Downloads</span> | |
</div> | |
<div class="file-grid-item"> | |
<i class="fas fa-folder text-green-500"></i> | |
<span>Pictures</span> | |
</div> | |
<div class="file-grid-item"> | |
<i class="fas fa-folder text-purple-500"></i> | |
<span>Music</span> | |
</div> | |
<div class="file-grid-item"> | |
<i class="fas fa-file-pdf text-red-500"></i> | |
<span>Report.pdf</span> | |
</div> | |
<div class="file-grid-item"> | |
<i class="fas fa-file-word text-blue-600"></i> | |
<span>Document.docx</span> | |
</div> | |
</div> | |
</div> | |
<div class="tab-content" id="documents-tab"> | |
<div class="p-4">Documents folder content</div> | |
</div> | |
</div> | |
</div> | |
</template> | |
<!-- Text Editor Template --> | |
<template id="text-editor-template"> | |
<div class="window"> | |
<div class="window-header"> | |
<div class="window-title"> | |
<i class="fas fa-file-alt"></i> | |
<span>Text Editor - Untitled</span> | |
</div> | |
<div class="window-controls"> | |
<div class="window-control minimize"> | |
<i class="fas fa-minus"></i> | |
</div> | |
<div class="window-control maximize"> | |
<i class="fas fa-square"></i> | |
</div> | |
<div class="window-control close"> | |
<i class="fas fa-times"></i> | |
</div> | |
</div> | |
</div> | |
<div class="editor-toolbar"> | |
<button class="editor-btn"><i class="fas fa-bold"></i></button> | |
<button class="editor-btn"><i class="fas fa-italic"></i></button> | |
<button class="editor-btn"><i class="fas fa-underline"></i></button> | |
<button class="editor-btn"><i class="fas fa-list-ul"></i></button> | |
<button class="editor-btn"><i class="fas fa-list-ol"></i></button> | |
</div> | |
<textarea id="editor-content">Welcome to BrowserOS Text Editor! | |
Start typing your notes here...</textarea> | |
</div> | |
</template> | |
<!-- Browser Template --> | |
<template id="browser-template"> | |
<div class="window"> | |
<div class="window-header"> | |
<div class="window-title"> | |
<i class="fas fa-globe"></i> | |
<span>Web Browser</span> | |
</div> | |
<div class="window-controls"> | |
<div class="window-control minimize"> | |
<i class="fas fa-minus"></i> | |
</div> | |
<div class="window-control maximize"> | |
<i class="fas fa-square"></i> | |
</div> | |
<div class="window-control close"> | |
<i class="fas fa-times"></i> | |
</div> | |
</div> | |
</div> | |
<div class="browser-nav"> | |
<button class="browser-btn"><i class="fas fa-arrow-left"></i></button> | |
<button class="browser-btn"><i class="fas fa-arrow-right"></i></button> | |
<button class="browser-btn"><i class="fas fa-sync"></i></button> | |
<input type="text" class="browser-input" value="https://browseros.com" placeholder="Search or enter address"> | |
<button class="browser-btn"><i class="fas fa-search"></i></button> | |
</div> | |
<iframe id="browser-frame" src="about:blank"></iframe> | |
</div> | |
</template> | |
<!-- Terminal Template --> | |
<template id="terminal-template"> | |
<div class="window"> | |
<div class="window-header"> | |
<div class="window-title"> | |
<i class="fas fa-terminal"></i> | |
<span>Terminal</span> | |
</div> | |
<div class="window-controls"> | |
<div class="window-control minimize"> | |
<i class="fas fa-minus"></i> | |
</div> | |
<div class="window-control maximize"> | |
<i class="fas fa-square"></i> | |
</div> | |
<div class="window-control close"> | |
<i class="fas fa-times"></i> | |
</div> | |
</div> | |
</div> | |
<div class="window-content bg-os-darker text-white p-4 font-mono"> | |
<div id="terminal-output"></div> | |
<div class="flex items-center"> | |
<span class="text-green-400 mr-2">user@browseros:~$</span> | |
<input type="text" id="terminal-input" class="bg-transparent border-none text-white outline-none flex-1" autofocus> | |
</div> | |
</div> | |
</div> | |
</template> | |
<!-- Calculator Template --> | |
<template id="calculator-template"> | |
<div class="window"> | |
<div class="window-header"> | |
<div class="window-title"> | |
<i class="fas fa-calculator"></i> | |
<span>Calculator</span> | |
</div> | |
<div class="window-controls"> | |
<div class="window-control minimize"> | |
<i class="fas fa-minus"></i> | |
</div> | |
<div class="window-control maximize"> | |
<i class="fas fa-square"></i> | |
</div> | |
<div class="window-control close"> | |
<i class="fas fa-times"></i> | |
</div> | |
</div> | |
</div> | |
<div class="window-content p-4"> | |
<div class="bg-gray-100 rounded p-3 mb-3 text-right text-2xl font-semibold" id="calc-display">0</div> | |
<div class="grid grid-cols-4 gap-2"> | |
<button class="calc-btn bg-gray-200">C</button> | |
<button class="calc-btn bg-gray-200">±</button> | |
<button class="calc-btn bg-gray-200">%</button> | |
<button class="calc-btn bg-os-primary text-white">÷</button> | |
<button class="calc-btn">7</button> | |
<button class="calc-btn">8</button> | |
<button class="calc-btn">9</button> | |
<button class="calc-btn bg-os-primary text-white">×</button> | |
<button class="calc-btn">4</button> | |
<button class="calc-btn">5</button> | |
<button class="calc-btn">6</button> | |
<button class="calc-btn bg-os-primary text-white">-</button> | |
<button class="calc-btn">1</button> | |
<button class="calc-btn">2</button> | |
<button class="calc-btn">3</button> | |
<button class="calc-btn bg-os-primary text-white">+</button> | |
<button class="calc-btn col-span-2">0</button> | |
<button class="calc-btn">.</button> | |
<button class="calc-btn bg-green-500 text-white">=</button> | |
</div> | |
</div> | |
</div> | |
</template> | |
<!-- Settings Template --> | |
<template id="settings-template"> | |
<div class="window"> | |
<div class="window-header"> | |
<div class="window-title"> | |
<i class="fas fa-cog"></i> | |
<span>System Settings</span> | |
</div> | |
<div class="window-controls"> | |
<div class="window-control minimize"> | |
<i class="fas fa-minus"></i> | |
</div> | |
<div class="window-control maximize"> | |
<i class="fas fa-square"></i> | |
</div> | |
<div class="window-control close"> | |
<i class="fas fa-times"></i> | |
</div> | |
</div> | |
</div> | |
<div class="window-content"> | |
<h2 class="text-xl font-bold mb-4">Personalization</h2> | |
<div class="mb-6"> | |
<h3 class="font-semibold mb-2">Wallpaper</h3> | |
<div class="settings-grid"> | |
<div class="wallpaper-preview selected" data-wallpaper="1"> | |
<img src="https://images.unsplash.com/photo-1505506874110-0a3a6a03b9c3?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1887&q=80" alt="Mountain Landscape"> | |
</div> | |
<div class="wallpaper-preview" data-wallpaper="2"> | |
<img src="https://images.unsplash.com/photo-1501854140801-50d01698950b?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2048&q=80" alt="Forest"> | |
</div> | |
<div class="wallpaper-preview" data-wallpaper="3"> | |
<img src="https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2048&q=80" alt="Nature"> | |
</div> | |
<div class="wallpaper-preview" data-wallpaper="4"> | |
<img src="https://images.unsplash.com/photo-1469474968028-56623f02e42e?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2048&q=80" alt="Landscape"> | |
</div> | |
</div> | |
</div> | |
<div class="mb-6"> | |
<h3 class="font-semibold mb-2">Theme</h3> | |
<div class="flex gap-4"> | |
<div class="cursor-pointer p-3 rounded border-2 border-transparent bg-gradient-to-r from-blue-500 to-purple-500 w-16 h-16" data-theme="default"></div> | |
<div class="cursor-pointer p-3 rounded border-2 border-transparent bg-gradient-to-r from-green-500 to-teal-500 w-16 h-16" data-theme="green"></div> | |
<div class="cursor-pointer p-3 rounded border-2 border-transparent bg-gradient-to-r from-red-500 to-orange-500 w-16 h-16" data-theme="red"></div> | |
<div class="cursor-pointer p-3 rounded border-2 border-transparent bg-gradient-to-r from-gray-700 to-gray-900 w-16 h-16" data-theme="dark"></div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</template> | |
<script> | |
document.addEventListener('DOMContentLoaded', function() { | |
// Add to getAppIcon function | |
function getAppIcon(appName) { | |
const icons = { | |
'file-manager': 'fa-folder', | |
'text-editor': 'fa-file-alt', | |
'browser': 'fa-globe', | |
'settings': 'fa-cog', | |
'terminal': 'fa-terminal', | |
'calculator': 'fa-calculator' | |
}; | |
return icons[appName] || 'fa-question'; | |
} | |
// Add power menu functionality | |
document.querySelector('.fa-power-off').addEventListener('click', function() { | |
document.getElementById('power-menu').classList.toggle('hidden'); | |
}); | |
// Add window snapping | |
document.addEventListener('keydown', function(e) { | |
if (e.key === 'ArrowLeft' && e.altKey && activeWindow) { | |
activeWindow.classList.remove('snapped-right', 'maximized'); | |
activeWindow.classList.add('snapped-left'); | |
} else if (e.key === 'ArrowRight' && e.altKey && activeWindow) { | |
activeWindow.classList.remove('snapped-left', 'maximized'); | |
activeWindow.classList.add('snapped-right'); | |
} else if (e.key === 'ArrowUp' && e.altKey && activeWindow) { | |
activeWindow.classList.remove('snapped-left', 'snapped-right'); | |
activeWindow.classList.add('maximized'); | |
} | |
}); | |
// Add terminal functionality | |
function setupTerminal(terminalWindow) { | |
const terminalInput = terminalWindow.querySelector('#terminal-input'); | |
const terminalOutput = terminalWindow.querySelector('#terminal-output'); | |
terminalInput.addEventListener('keydown', function(e) { | |
if (e.key === 'Enter') { | |
const command = terminalInput.value.trim(); | |
terminalInput.value = ''; | |
// Add command to output | |
terminalOutput.innerHTML += ` | |
<div class="mb-1"> | |
<span class="text-green-400">user@browseros:~$</span> ${command} | |
</div> | |
`; | |
// Process command | |
let output = ''; | |
if (command === 'help') { | |
output = `Available commands: help, clear, about, echo`; | |
} else if (command === 'clear') { | |
terminalOutput.innerHTML = ''; | |
return; | |
} else if (command.startsWith('echo ')) { | |
output = command.substring(5); | |
} else if (command === 'about') { | |
output = 'BrowserOS Terminal v1.0'; | |
} else if (command) { | |
output = `Command not found: ${command}`; | |
} | |
if (output) { | |
terminalOutput.innerHTML += `<div class="mb-2">${output}</div>`; | |
} | |
// Scroll to bottom | |
terminalOutput.scrollTop = terminalOutput.scrollHeight; | |
} | |
}); | |
} | |
// Add calculator functionality | |
function setupCalculator(calcWindow) { | |
const display = calcWindow.querySelector('#calc-display'); | |
const buttons = calcWindow.querySelectorAll('.calc-btn'); | |
let currentInput = '0'; | |
let previousInput = ''; | |
let operation = null; | |
let resetInput = false; | |
function updateDisplay() { | |
display.textContent = currentInput; | |
} | |
buttons.forEach(button => { | |
button.addEventListener('click', function() { | |
const value = this.textContent; | |
if (value >= '0' && value <= '9') { | |
if (currentInput === '0' || resetInput) { | |
currentInput = value; | |
resetInput = false; | |
} else { | |
currentInput += value; | |
} | |
} else if (value === '.') { | |
if (!currentInput.includes('.')) { | |
currentInput += '.'; | |
} | |
} else if (value === 'C') { | |
currentInput = '0'; | |
previousInput = ''; | |
operation = null; | |
} else if (value === '±') { | |
currentInput = (parseFloat(currentInput) * -1).toString(); | |
} else if (value === '%') { | |
currentInput = (parseFloat(currentInput) / 100).toString(); | |
} else if (['+', '-', '×', '÷'].includes(value)) { | |
if (operation !== null) calculate(); | |
previousInput = currentInput; | |
operation = value; | |
resetInput = true; | |
} else if (value === '=') { | |
calculate(); | |
} | |
updateDisplay(); | |
}); | |
}); | |
function calculate() { | |
let result; | |
const prev = parseFloat(previousInput); | |
const current = parseFloat(currentInput); | |
if (isNaN(prev) || isNaN(current)) return; | |
switch (operation) { | |
case '+': result = prev + current; break; | |
case '-': result = prev - current; break; | |
case '×': result = prev * current; break; | |
case '÷': result = prev / current; break; | |
default: return; | |
} | |
currentInput = result.toString(); | |
operation = null; | |
resetInput = true; | |
} | |
} | |
// DOM Elements | |
const desktop = document.getElementById('desktop'); | |
const taskbar = document.getElementById('taskbar'); | |
const startMenuBtn = document.getElementById('start-menu-btn'); | |
const startMenu = document.getElementById('start-menu'); | |
const appTray = document.getElementById('app-tray'); | |
const clock = document.getElementById('clock'); | |
const contextMenu = document.querySelector('.context-menu'); | |
// State management | |
let openWindows = []; | |
let activeWindow = null; | |
let dragOffset = {x: 0, y: 0}; | |
let isDragging = false; | |
let currentDraggedElement = null; | |
// Initialize clock | |
function updateClock() { | |
const now = new Date(); | |
const hours = now.getHours().toString().padStart(2, '0'); | |
const minutes = now.getMinutes().toString().padStart(2, '0'); | |
clock.textContent = `${hours}:${minutes}`; | |
} | |
updateClock(); | |
setInterval(updateClock, 60000); | |
// Start menu toggle | |
startMenuBtn.addEventListener('click', function(e) { | |
e.stopPropagation(); | |
startMenu.style.display = startMenu.style.display === 'flex' ? 'none' : 'flex'; | |
}); | |
// Close start menu when clicking elsewhere | |
document.addEventListener('click', function(e) { | |
if (!startMenu.contains(e.target) && e.target !== startMenuBtn) { | |
startMenu.style.display = 'none'; | |
} | |
}); | |
// Desktop icon click handler | |
document.querySelectorAll('.desktop-icon, .app-item').forEach(icon => { | |
icon.addEventListener('click', function(e) { | |
e.stopPropagation(); | |
const appName = this.getAttribute('data-app'); | |
openApp(appName); | |
}); | |
}); | |
// Context menu handling | |
desktop.addEventListener('contextmenu', function(e) { | |
e.preventDefault(); | |
contextMenu.style.display = 'block'; | |
contextMenu.style.left = `${e.pageX}px`; | |
contextMenu.style.top = `${e.pageY}px`; | |
}); | |
document.addEventListener('click', function() { | |
contextMenu.style.display = 'none'; | |
}); | |
// Open application function | |
function openApp(appName) { | |
// Setup app-specific functionality | |
if (appName === 'terminal') { | |
setupTerminal(windowElement); | |
} else if (appName === 'calculator') { | |
setupCalculator(windowElement); | |
} | |
// Close start menu | |
startMenu.style.display = 'none'; | |
// Check if app is already open | |
const existingWindow = openWindows.find(win => win.appName === appName); | |
if (existingWindow) { | |
// Bring to front | |
bringToFront(existingWindow.element); | |
return; | |
} | |
// Create new window | |
const template = document.getElementById(`${appName}-template`); | |
if (!template) return; | |
const clone = template.content.cloneNode(true); | |
const windowElement = clone.querySelector('.window'); | |
// Position window randomly but within view | |
const maxX = window.innerWidth - 400; | |
const maxY = window.innerHeight - 300 - 50; // Account for taskbar | |
const x = Math.max(50, Math.min(maxX, Math.floor(Math.random() * maxX))); | |
const y = Math.max(50, Math.min(maxY, Math.floor(Math.random() * maxY))); | |
windowElement.style.left = `${x}px`; | |
windowElement.style.top = `${y}px`; | |
// Add to desktop | |
desktop.appendChild(windowElement); | |
// Add to app tray | |
const trayApp = document.createElement('div'); | |
trayApp.className = 'tray-app'; | |
trayApp.innerHTML = `<i class="fas ${getAppIcon(appName)}"></i>`; | |
trayApp.setAttribute('data-app', appName); | |
trayApp.addEventListener('click', function() { | |
const win = openWindows.find(w => w.appName === appName); | |
if (win) { | |
if (win.element.classList.contains('minimized-window')) { | |
win.element.classList.remove('minimized-window'); | |
win.element.style.display = 'flex'; | |
} else { | |
win.element.classList.add('minimized-window'); | |
win.element.style.display = 'none'; | |
} | |
} | |
}); | |
appTray.appendChild(trayApp); | |
// Store window reference | |
const windowObj = { | |
element: windowElement, | |
appName: appName, | |
trayElement: trayApp | |
}; | |
openWindows.push(windowObj); | |
// Set as active window | |
bringToFront(windowElement); | |
// Add window controls | |
const header = windowElement.querySelector('.window-header'); | |
const minimizeBtn = windowElement.querySelector('.window-control.minimize'); | |
const maximizeBtn = windowElement.querySelector('.window-control.maximize'); | |
const closeBtn = windowElement.querySelector('.window-control.close'); | |
// Window dragging | |
header.addEventListener('mousedown', function(e) { | |
if (e.target.classList.contains('window-control')) return; | |
isDragging = true; | |
currentDraggedElement = windowElement; | |
dragOffset.x = e.clientX - windowElement.offsetLeft; | |
dragOffset.y = e.clientY - windowElement.offsetTop; | |
bringToFront(windowElement); | |
}); | |
// Minimize window | |
minimizeBtn.addEventListener('click', function(e) { | |
e.stopPropagation(); | |
windowElement.classList.add('minimized-window'); | |
windowElement.style.display = 'none'; | |
}); | |
// Maximize window | |
maximizeBtn.addEventListener('click', function(e) { | |
e.stopPropagation(); | |
windowElement.classList.toggle('maximized'); | |
// Update maximize icon | |
const icon = maximizeBtn.querySelector('i'); | |
if (windowElement.classList.contains('maximized')) { | |
icon.classList.remove('fa-square'); | |
icon.classList.add('fa-clone'); | |
} else { | |
icon.classList.add('fa-square'); | |
icon.classList.remove('fa-clone'); | |
} | |
}); | |
// Close window | |
closeBtn.addEventListener('click', function(e) { | |
e.stopPropagation(); | |
windowElement.remove(); | |
trayApp.remove(); | |
// Remove from open windows | |
openWindows = openWindows.filter(win => win.element !== windowElement); | |
// Activate next window if available | |
if (openWindows.length > 0) { | |
bringToFront(openWindows[openWindows.length - 1].element); | |
} | |
}); | |
// Tab switching for file manager | |
if (appName === 'file-manager') { | |
const tabs = windowElement.querySelectorAll('.tab'); | |
tabs.forEach(tab => { | |
tab.addEventListener('click', function() { | |
// Remove active class from all tabs | |
tabs.forEach(t => t.classList.remove('active')); | |
// Add active class to clicked tab | |
this.classList.add('active'); | |
// Hide all tab content | |
const tabContents = windowElement.querySelectorAll('.tab-content'); | |
tabContents.forEach(content => content.classList.remove('active')); | |
// Show corresponding tab content | |
const tabName = this.getAttribute('data-tab'); | |
const content = windowElement.querySelector(`#${tabName}-tab`); | |
if (content) content.classList.add('active'); | |
}); | |
}); | |
} | |
// Wallpaper selection for settings | |
if (appName === 'settings') { | |
const wallpaperPreviews = windowElement.querySelectorAll('.wallpaper-preview'); | |
wallpaperPreviews.forEach(preview => { | |
preview.addEventListener('click', function() { | |
// Remove selected class from all | |
wallpaperPreviews.forEach(p => p.classList.remove('selected')); | |
// Add selected class to clicked | |
this.classList.add('selected'); | |
// Change desktop background | |
const img = this.querySelector('img'); | |
desktop.style.backgroundImage = `url('${img.src}')`; | |
}); | |
}); | |
} | |
} | |
// Get app icon based on app name | |
function getAppIcon(appName) { | |
const icons = { | |
'file-manager': 'fa-folder', | |
'text-editor': 'fa-file-alt', | |
'browser': 'fa-globe', | |
'settings': 'fa-cog', | |
'terminal': 'fa-terminal', | |
'calculator': 'fa-calculator' | |
}; | |
return icons[appName] || 'fa-question'; | |
} | |
// Bring window to front | |
function bringToFront(windowElement) { | |
// Move to top of z-index stack | |
const windows = document.querySelectorAll('.window'); | |
let maxZ = 10; | |
windows.forEach(win => { | |
const z = parseInt(win.style.zIndex) || 0; | |
if (z > maxZ) maxZ = z; | |
win.style.zIndex = z; | |
}); | |
windowElement.style.zIndex = maxZ + 1; | |
activeWindow = windowElement; | |
// Update tray app active state | |
const appName = openWindows.find(win => win.element === windowElement)?.appName; | |
if (appName) { | |
document.querySelectorAll('.tray-app').forEach(app => { | |
app.classList.remove('active'); | |
}); | |
const trayApp = document.querySelector(`.tray-app[data-app="${appName}"]`); | |
if (trayApp) trayApp.classList.add('active'); | |
} | |
} | |
// Global mouse events for dragging | |
document.addEventListener('mousemove', function(e) { | |
if (isDragging && currentDraggedElement) { | |
const x = e.clientX - dragOffset.x; | |
const y = e.clientY - dragOffset.y; | |
// Keep window within bounds | |
const maxX = window.innerWidth - currentDraggedElement.offsetWidth; | |
const maxY = window.innerHeight - currentDraggedElement.offsetHeight - 50; // Account for taskbar | |
currentDraggedElement.style.left = `${Math.max(0, Math.min(maxX, x))}px`; | |
currentDraggedElement.style.top = `${Math.max(0, Math.min(maxY, y))}px`; | |
} | |
}); | |
document.addEventListener('mouseup', function() { | |
isDragging = false; | |
currentDraggedElement = null; | |
}); | |
// Window click to bring to front | |
desktop.addEventListener('click', function(e) { | |
const windowElement = e.target.closest('.window'); | |
if (windowElement) { | |
bringToFront(windowElement); | |
} | |
}); | |
// Context menu actions | |
document.getElementById('context-new-folder').addEventListener('click', function() { | |
alert('New folder created!'); | |
contextMenu.style.display = 'none'; | |
}); | |
document.getElementById('context-new-file').addEventListener('click', function() { | |
alert('New file created!'); | |
contextMenu.style.display = 'none'; | |
}); | |
// Initialize with File Manager open | |
openApp('file-manager'); | |
}); | |
</script> | |
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=TechITProfessional/hfos" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
</html> |