lucide.createIcons())"
@close-report-modal-event.window="isReportModalOpen = false"
@open-enhance-modal.window="isEnhanceModalOpen = true"
@set-permission-status.window="isOwner = $event.detail.isOwner; canEdit = $event.detail.canEdit"
@set-fork-status.window="isForkingAllowed = $event.detail.isAllowed"
@keydown.escape.window="isInspectorOpen = false; isSettingsOpen = false; isCodeModalOpen = false; isReportModalOpen = false; isEnhanceModalOpen = false; isNotificationsOpen = false"
id="main-container" class="h-full flex flex-col">
lucide.createIcons();
function assetsManager() {
return {
allFiles: [],
fileStructure: null,
searchTerm: '',
init() {
window.addEventListener('update-assets-view', (event) => {
this.updateFiles(event.detail.files);
});
window.addEventListener('edit-asset-file', (event) => {
// Dispara evento para mudar a aba e ativar o arquivo
window.dispatchEvent(new CustomEvent('switch-tab', { detail: { tab: 'code', file: event.detail.file }}));
});
// --- INÍCIO: LÓGICA DE UPLOAD (EVENT LISTENERS) ---
const dropZone = document.getElementById('asset-drop-zone');
const browseButton = document.getElementById('asset-browse-button');
const fileInput = document.getElementById('asset-upload-input');
if (dropZone && browseButton && fileInput) {
// 1. Click to browse
browseButton.addEventListener('click', (e) => {
e.preventDefault(); // Impede o comportamento padrão do botão
e.stopPropagation(); // Impede que o clique se propague
fileInput.click();
});
// 2. Input change
fileInput.addEventListener('change', (e) => {
// Dispara evento para app.js com o FileList
window.dispatchEvent(new CustomEvent('trigger-file-upload', {
detail: { files: e.target.files }
}));
// Limpa o input para permitir selecionar os mesmos arquivos novamente
e.target.value = null;
});
// 3. Drag and Drop
dropZone.addEventListener('dragover', (e) => {
e.preventDefault();
e.stopPropagation();
dropZone.classList.add('drag-over');
});
dropZone.addEventListener('dragleave', (e) => {
e.preventDefault();
e.stopPropagation();
dropZone.classList.remove('drag-over');
});
dropZone.addEventListener('drop', (e) => {
e.preventDefault();
e.stopPropagation();
dropZone.classList.remove('drag-over');
// Dispara evento para app.js com o DataTransfer
window.dispatchEvent(new CustomEvent('trigger-file-upload', {
detail: { dataTransfer: e.dataTransfer }
}));
});
}
// --- FIM: LÓGICA DE UPLOAD (EVENT LISTENERS) ---
},
updateFiles(projectFiles) {
const iconMap = { 'html': 'text-orange-500', 'js': 'text-yellow-400', 'css': 'text-sky-500', 'json':
'text-green-500', 'md': 'text-zinc-400', 'png': 'text-purple-400', 'jpg': 'text-purple-400', 'jpeg':
'text-purple-400', 'gif': 'text-purple-400', 'svg': 'text-red-400' }; // Added image icons
this.allFiles = Array.from(projectFiles.keys()).map(path => {
const parts = path.split('/');
const name = parts.pop();
const folder = parts.join('/') || '.';
return {
path: path,
name: name,
folder: folder,
iconColor: iconMap[name.split('.').pop()] || 'text-zinc-400'
};
});
this.buildFileStructure(); // Rebuild structure on update
},
buildFileStructure() {
const filtered = this.searchTerm.trim() === ''
? this.allFiles
: this.allFiles.filter(file => file.path.toLowerCase().includes(this.searchTerm.toLowerCase()));
if (filtered.length === 0) {
this.fileStructure = null;
return;
}
// Sort files alphabetically within folders
filtered.sort((a, b) => a.name.localeCompare(b.name));
this.fileStructure = filtered.reduce((acc, file) => {
if (!acc[file.folder]) {
acc[file.folder] = [];
}
acc[file.folder].push(file);
return acc;
}, {});
this.$nextTick(() => lucide.createIcons());
},
get filteredStructure() {
// Structure is built when searchTerm changes or files update
return this.fileStructure;
},
editFile(filePath) {
console.log('Editing file via assets:', filePath);
// Dispara evento global para o Alpine ouvir
window.dispatchEvent(new CustomEvent('edit-asset-file', { detail: { fileName: filePath }}));
},
// --- INÍCIO DAS ADIÇÕES ---
renameFile(filePath) {
const newName = prompt("Enter the new file name (including path if moving):", filePath);
if (newName && newName !== filePath) {
// Validação simples (não pode estar vazio)
if (newName.trim() === '') {
alert("File name cannot be empty.");
return;
}
console.log(`Renaming file from: ${filePath} to: ${newName}`);
// Dispara evento para app.js tratar a lógica
window.dispatchEvent(new CustomEvent('trigger-file-rename', {
detail: { oldPath: filePath, newPath: newName }
}));
}
},
deleteFile(filePath) {
if (confirm(`Are you sure you want to delete "${filePath}"?\nThis action cannot be undone.`)) {
console.log('Deleting file via assets:', filePath);
// Dispara evento para app.js tratar a lógica
window.dispatchEvent(new CustomEvent('trigger-file-delete', {
detail: { path: filePath }
}));
}
}
// --- FIM DAS ADIÇÕES ---
}
}
document.addEventListener('alpine:init', () => {
// This makes isInspectorOpen true by default on large screens, and false on smaller ones.
Alpine.data('main', () => ({
// 'isOwner' e 'canEdit' serão definidos pelo evento 'set-permission-status'
isOwner: false,
canEdit: false,
isInspectorOpen: window.innerWidth >= 1024,
init() {
// Listener atualizado
window.addEventListener('set-permission-status', event => {
this.isOwner = event.detail.isOwner;
this.canEdit = event.detail.canEdit;
});
}
}))
})
window.addEventListener("load", () => {
setTimeout(() => {
const loader = document.querySelector("#loader");
if (loader) loader.remove();
}, 1500);
});