mate-desktop-red / components /desktop-icon.js
mvbhr's picture
criar a tela para simular um sistema de janelas estilo mate do linux
da4c298 verified
class DesktopIcon extends HTMLElement {
connectedCallback() {
this.attachShadow({ mode: 'open' });
const name = this.getAttribute('name') || 'Icon';
const icon = this.getAttribute('icon') || 'file';
const color = this.getAttribute('color') || 'text-zinc-300';
this.shadowRoot.innerHTML = `
<style>
:host {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
padding: 8px 12px;
cursor: pointer;
border-radius: 4px;
transition: all 0.2s;
user-select: none;
}
:host:hover {
background: rgba(255, 255, 255, 0.1);
transform: scale(1.05);
}
:host(.selected) {
background: rgba(239, 68, 68, 0.3);
border: 1px solid rgba(239, 68, 68, 0.5);
}
.icon-container {
display: flex;
align-items: center;
justify-content: center;
width: 48px;
height: 48px;
background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05));
border-radius: 8px;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.icon-label {
color: #e4e4e7;
font-size: 11px;
text-align: center;
max-width: 80px;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8);
word-wrap: break-word;
line-height: 1.2;
}
</style>
<div class="icon-container">
<i data-feather="${icon}" class="${color}" style="width: 24px; height: 24px;"></i>
</div>
<div class="icon-label">${name}</div>
`;
this.initializeEventListeners();
// Re-render feather icon
setTimeout(() => feather.replace(), 0);
}
initializeEventListeners() {
this.addEventListener('dblclick', () => {
this.openApplication();
});
this.addEventListener('click', (e) => {
// Clear other selections
document.querySelectorAll('desktop-icon').forEach(icon => {
icon.classList.remove('selected');
});
// Select this icon
this.classList.add('selected');
});
this.addEventListener('contextmenu', (e) => {
e.preventDefault();
e.stopPropagation();
this.showContextMenu(e);
});
}
openApplication() {
const name = this.getAttribute('name');
const icon = this.getAttribute('icon');
switch(icon) {
case 'terminal':
this.openTerminal();
break;
case 'globe':
this.openBrowser();
break;
case 'edit-3':
this.openTextEditor();
break;
case 'folder':
this.openFileBrowser(name);
break;
case 'image':
this.openImageViewer();
break;
case 'music':
this.openMusicPlayer();
break;
case 'film':
this.openVideoPlayer();
break;
case 'file-text':
this.openDocumentViewer();
break;
case 'home':
this.openHomeFolder();
break;
case 'trash-2':
this.openTrash();
break;
default:
this.showMessage(`Abrindo ${name}...`);
}
}
openTerminal() {
const content = `<div class="bg-black h-full p-4 font-mono text-sm text-green-400 overflow-auto">
<div>mate@mate-desktop:~$ echo "Bem-vindo ao terminal MATE!"</div>
<div>Bem-vindo ao terminal MATE!</div>
<div>mate@mate-desktop:~$ _</div>
</div>`;
createNewWindow('Terminal', 'terminal', 650, 450, content, 100, 150);
}
openBrowser() {
const content = `<div class="bg-zinc-800 h-full flex flex-col">
<div class="bg-zinc-700 p-2 flex items-center gap-2">
<i data-feather="globe" class="text-blue-400" style="width: 16px; height: 16px;"></i>
<span class="text-zinc-200 text-sm">Navegador Web MATE</span>
</div>
<div class="flex-1 flex items-center justify-center text-zinc-400">
<div class="text-center">
<i data-feather="globe" style="width: 48px; height: 48px; margin: 0 auto 16px;"></i>
<p>Digite um endereço na barra de endereços</p>
<input type="text" placeholder="https://..." class="mt-4 px-3 py-2 bg-zinc-700 rounded text-zinc-200 w-64 outline-none">
</div>
</div>
</div>`;
createNewWindow('Navegador Web', 'globe', 800, 600, content, 200, 100);
}
openTextEditor() {
const content = `<div class="bg-zinc-800 h-full p-4">
<textarea class="w-full h-full bg-zinc-900 text-zinc-200 p-3 rounded resize-none outline-none" placeholder="Comece a digitar...">Documento de Texto - MATE Desktop
Este é um documento de exemplo criado com o editor de texto MATE.
O ambiente MATE oferece uma experiência de desktop familiar e produtiva,
com todas as ferramentas necessárias para o seu trabalho diário.</textarea>
</div>`;
createNewWindow('Editor de Texto', 'edit-3', 600, 450, content, 250, 120);
}
openFileBrowser(folderName) {
const content = `<div class="bg-zinc-800 h-full flex flex-col">
<div class="bg-zinc-700 p-2 flex items-center gap-2 border-b border-zinc-600">
<i data-feather="folder" class="text-zinc-300" style="width: 16px; height: 16px;"></i>
<span class="text-zinc-200 text-sm">${folderName}</span>
</div>
<div class="flex-1 p-6 flex items-center justify-center text-zinc-400">
<div class="text-center">
<i data-feather="folder" style="width: 64px; height: 64px; margin: 0 auto 16px;"></i>
<p class="text-lg">Pasta vazia</p>
<p class="text-sm mt-2">Esta pasta não contém arquivos</p>
</div>
</div>
</div>`;
createNewWindow(folderName, 'folder', 700, 500, content, 150, 120);
}
openImageViewer() {
const content = `<div class="bg-zinc-800 h-full p-4 flex items-center justify-center">
<div class="text-center">
<img src="http://static.photos/nature/500x400/42" alt="Imagem" class="rounded shadow-lg mb-4">
<div class="flex justify-center gap-2">
<button class="px-3 py-1 bg-zinc-700 text-zinc-200 rounded hover:bg-zinc-600">
<i data-feather="chevron-left" style="width: 16px; height: 16px;"></i>
</button>
<button class="px-3 py-1 bg-zinc-700 text-zinc-200 rounded hover:bg-zinc-600">
<i data-feather="chevron-right" style="width: 16px; height: 16px;"></i>
</button>
<button class="px-3 py-1 bg-zinc-700 text-zinc-200 rounded hover:bg-zinc-600">
<i data-feather="maximize-2" style="width: 16px; height: 16px;"></i>
</button>
</div>
</div>
</div>`;
createNewWindow('Visualizador de Imagens', 'image', 600, 500, content, 300, 150);
}
openMusicPlayer() {
const content = `<div class="bg-zinc-800 h-full flex flex-col">
<div class="p-6">
<div class="w-48 h-48 mx-auto bg-gradient-to-br from-purple-500 to-pink-500 rounded-lg shadow-xl flex items-center justify-center">
<i data-feather="music" style="width: 64px; height: 64px; color: white;"></i>
</div>
<div class="text-center mt-6">
<h3 class="text-zinc-200 text-lg font-medium">Artista - Música</h3>
<p class="text-zinc-400 text-sm mt-1">Álbum Exemplo</p>
</div>
</div>
<div class="p-4 border-t border-zinc-700">
<div class="bg-zinc-700 h-2 rounded-full overflow-hidden mb-4">
<div class="bg-red-500 h-full rounded-full" style="width: 30%;"></div>
</div>
<div class="flex justify-center gap-4">
<button class="text-zinc-400 hover:text-zinc-200">
<i data-feather="skip-back" style="width: 24px; height: 24px;"></i>
</button>
<button class="text-zinc-400 hover:text-zinc-200">
<i data-feather="play" style="width: 32px; height: 32px;"></i>
</button>
<button class="text-zinc-400 hover:text-zinc-200">
<i data-feather="skip-forward" style="width: 24px; height: 24px;"></i>
</button>
</div>
</div>
</div>`;
createNewWindow('Reprodutor de Música', 'music', 400, 500, content, 400, 100);
}
openVideoPlayer() {
const content = `<div class="bg-black h-full flex items-center justify-center">
<div class="text-center text-white">
<i data-feather="film" style="width: 64px; height: 64px; margin: 0 auto 16px;"></i>
<p>Reprodutor de Vídeo MATE</p>
<p class="text-sm text-zinc-400 mt-2">Selecione um arquivo de vídeo para reproduzir</p>
</div>
</div>`;
createNewWindow('Reprodutor de Vídeo', 'film', 700, 500, content, 350, 100);
}
openDocumentViewer() {
const content = `<div class="bg-zinc-800 h-full p-8">
<div class="bg-white h-full rounded shadow-lg p-6">
<h1 class="text-2xl font-bold mb-4">Documento de Exemplo</h1>
<p class="text-gray-700 mb-4">Este é um documento exemplo no visualizador de documentos MATE.</p>
<p class="text-gray-700 mb-4">O MATE Desktop oferece ferramentas completas para produtividade, incluindo visualização de documentos, planilhas e apresentações.</p>
<ul class="list-disc list-inside text-gray-700">
<li> Suporte para múltiplos formatos </li>
<li> Interface intuitiva </li>
<li> Integração com o sistema </li>
<li> Ferramentas de edição básicas </li>
</ul>
</div>
</div>`;
createNewWindow('Visualizador de Documentos', 'file-text', 650, 500, content, 200, 150);
}
openHomeFolder() {
this.openFileBrowser('Página Inicial');
}
openTrash() {
const content = `<div class="bg-zinc-800 h-full flex flex-col">
<div class="bg-zinc-700 p-2 flex items-center gap-2 border-b border-zinc-600">
<i data-feather="trash-2" class="text-red-400" style="width: 16px; height: 16px;"></i>
<span class="text-zinc-200 text-sm">Lixeira</span>
</div>
<div class="flex-1 p-6 flex items-center justify-center text-zinc-400">
<div class="text-center">
<i data-feather="trash-2" style="width: 64px; height: 64px; margin: 0 auto 16px;"></i>
<p class="text-lg">Lixeira vazia</p>
<p class="text-sm mt-2">Nenhum item na lixeira</p>
<button class="mt-4 px-4 py-2 bg-zinc-700 text-zinc-200 rounded hover:bg-zinc-600">
<i data-feather="refresh-cw" style="width: 16px; height: 16px; display: inline; vertical-align: middle;"></i>
Restaurar itens
</button>
</div>
</div>
</div>`;
createNewWindow('Lixeira', 'trash-2', 600, 450, content, 250, 150);
}
showMessage(text) {
// Create a temporary notification
const notification = document.createElement('div');
notification.className = 'fixed top-40 left-1/2 transform -translate-x-1/2 bg-zinc-800 text-zinc-200 px-4 py-2 rounded shadow-lg z-50';
notification.textContent = text;
document.body.appendChild(notification);
setTimeout(() => {
notification.remove();
}, 2000);
}
showContextMenu(e) {
const contextMenu = document.getElementById('context-menu');
contextMenu.style.left = `${e.clientX}px`;
contextMenu.style.top = `${e.clientY}px`;
contextMenu.classList.remove('hidden');
contextMenu.classList.add('menu-enter');
}
}
customElements.define('desktop-icon', DesktopIcon);