<?php
// file_explorer.php - umieść ten plik w katalogu głównym swojej aplikacji

// Konfiguracja
$baseDir = './'; // Katalog główny aplikacji
$excludeDirs = ['.git', 'node_modules', 'vendor']; // Katalogi do pominięcia
$allowedExtensions = ['js', 'php', 'css', 'html', 'htm']; // Obsługiwane rozszerzenia plików

// Funkcja do skanowania katalogów rekurencyjnie
function scanDirectory($dir, $basePath = '') {
    global $excludeDirs, $allowedExtensions;
    $result = [];
    
    $files = scandir($dir);
    foreach ($files as $file) {
        if ($file === '.' || $file === '..') continue;
        
        $path = $dir . '/' . $file;
        $relativePath = $basePath . '/' . $file;
        
        if (is_dir($path)) {
            // Pomijanie wykluczonych katalogów
            if (in_array($file, $excludeDirs)) continue;
            
            $result[$file] = [
                'type' => 'directory',
                'path' => $relativePath,
                'contents' => scanDirectory($path, $relativePath)
            ];
        } else {
            // Sprawdzanie rozszerzenia pliku
            $extension = pathinfo($file, PATHINFO_EXTENSION);
            if (!in_array($extension, $allowedExtensions)) continue;
            
            $result[$file] = [
                'type' => 'file',
                'path' => $relativePath,
                'extension' => $extension,
                'size' => filesize($path),
                'content' => htmlspecialchars(file_get_contents($path))
            ];
        }
    }
    
    return $result;
}

// Pobieranie danych w formacie JSON, jeśli żądanie jest wykonywane przez AJAX
if (isset($_GET['ajax'])) {
    header('Content-Type: application/json');
    echo json_encode(scanDirectory($baseDir));
    exit;
}

// Generowanie HTML
?>
<!DOCTYPE html>
<html lang="pl">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Eksplorator kodu aplikacji</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            padding: 0;
            background-color: #f5f5f5;
            color: #333;
        }
        .container {
            display: flex;
            height: 100vh;
        }
        .file-tree {
            width: 300px;
            background-color: #2c3e50;
            color: #ecf0f1;
            overflow-y: auto;
            padding: 15px;
            box-sizing: border-box;
        }
        .content-view {
            flex: 1;
            display: flex;
            flex-direction: column;
            overflow: hidden;
        }
        .file-header {
            background-color: #34495e;
            color: #ecf0f1;
            padding: 10px 15px;
            font-size: 1.2em;
            border-bottom: 1px solid #546e7a;
        }
        .file-content {
            flex: 1;
            overflow: auto;
            padding: 15px;
            background-color: #fff;
        }
        pre {
            margin: 0;
            white-space: pre-wrap;
            font-family: 'Courier New', Courier, monospace;
            font-size: 14px;
            line-height: 1.5;
        }
        .folder, .file {
            margin: 3px 0;
            cursor: pointer;
            padding: 5px;
            border-radius: 3px;
            transition: background-color 0.2s;
        }
        .folder:hover, .file:hover {
            background-color: #34495e;
        }
        .folder-content {
            margin-left: 15px;
            display: none;
        }
        .open > .folder-content {
            display: block;
        }
        .folder::before {
            content: "📁 ";
        }
        .open > .folder-name::before {
            content: "📂 ";
        }
        .file.js::before {
            content: "📄 ";
            color: #f1c40f;
        }
        .file.php::before {
            content: "📄 ";
            color: #9b59b6;
        }
        .file.css::before {
            content: "📄 ";
            color: #3498db;
        }
        .file.html::before, .file.htm::before {
            content: "📄 ";
            color: #e74c3c;
        }
        .selected {
            background-color: #3498db !important;
            color: white;
        }
        .file-tree-header {
            font-size: 1.2em;
            margin-bottom: 15px;
            padding-bottom: 10px;
            border-bottom: 1px solid #546e7a;
        }
        .code-content {
            tab-size: 4;
        }
        .copy-btn {
            position: absolute;
            top: 10px;
            right: 10px;
            background-color: #3498db;
            color: white;
            border: none;
            padding: 5px 10px;
            border-radius: 3px;
            cursor: pointer;
        }
        .copy-btn:hover {
            background-color: #2980b9;
        }
        .file-info {
            font-size: 0.85em;
            color: #7f8c8d;
            margin-top: 5px;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="file-tree">
            <div class="file-tree-header">Struktura plików</div>
            <div id="fileTree"></div>
        </div>
        <div class="content-view">
            <div class="file-header" id="fileHeader">Wybierz plik, aby zobaczyć jego zawartość</div>
            <div class="file-content">
                <button id="copyBtn" class="copy-btn" style="display: none;">Kopiuj</button>
                <div id="fileInfo" class="file-info"></div>
                <pre id="fileContent" class="code-content"></pre>
            </div>
        </div>
    </div>

    <script>
        // Funkcja do renderowania drzewa plików
        function renderFileTree(data, container) {
            for (const [name, info] of Object.entries(data)) {
                if (info.type === 'directory') {
                    const folderElement = document.createElement('div');
                    folderElement.className = 'folder';
                    
                    const folderNameElement = document.createElement('div');
                    folderNameElement.className = 'folder-name';
                    folderNameElement.textContent = name;
                    folderElement.appendChild(folderNameElement);
                    
                    folderNameElement.addEventListener('click', function() {
                        folderElement.classList.toggle('open');
                    });
                    
                    const folderContentElement = document.createElement('div');
                    folderContentElement.className = 'folder-content';
                    renderFileTree(info.contents, folderContentElement);
                    folderElement.appendChild(folderContentElement);
                    
                    container.appendChild(folderElement);
                } else {
                    const fileElement = document.createElement('div');
                    fileElement.className = `file ${info.extension}`;
                    fileElement.textContent = name;
                    fileElement.dataset.path = info.path;
                    fileElement.dataset.extension = info.extension;
                    fileElement.dataset.content = info.content;
                    fileElement.dataset.size = info.size;
                    
                    fileElement.addEventListener('click', function() {
                        // Usunięcie poprzedniego zaznaczenia
                        document.querySelectorAll('.file.selected').forEach(el => {
                            el.classList.remove('selected');
                        });
                        
                        // Dodanie nowego zaznaczenia
                        fileElement.classList.add('selected');
                        
                        // Aktualizacja nagłówka i zawartości
                        document.getElementById('fileHeader').textContent = info.path.substring(1); // Usuwamy początkowy '/'
                        document.getElementById('fileContent').textContent = info.content;
                        document.getElementById('fileInfo').textContent = `Typ: ${info.extension.toUpperCase()} | Rozmiar: ${formatFileSize(info.size)}`;
                        document.getElementById('copyBtn').style.display = 'block';
                    });
                    
                    container.appendChild(fileElement);
                }
            }
        }
        
        // Formatowanie rozmiaru pliku
        function formatFileSize(bytes) {
            if (bytes < 1024) return bytes + ' B';
            else if (bytes < 1048576) return (bytes / 1024).toFixed(2) + ' KB';
            else return (bytes / 1048576).toFixed(2) + ' MB';
        }
        
        // Kopiowanie zawartości pliku
        document.getElementById('copyBtn').addEventListener('click', function() {
            const content = document.getElementById('fileContent').textContent;
            navigator.clipboard.writeText(content)
                .then(() => {
                    const btn = document.getElementById('copyBtn');
                    const originalText = btn.textContent;
                    btn.textContent = 'Skopiowano!';
                    setTimeout(() => {
                        btn.textContent = originalText;
                    }, 2000);
                })
                .catch(err => {
                    console.error('Błąd podczas kopiowania:', err);
                });
        });
        
        // Pobieranie danych i renderowanie drzewa plików
        fetch('?ajax=1')
            .then(response => response.json())
            .then(data => {
                const fileTreeContainer = document.getElementById('fileTree');
                renderFileTree(data, fileTreeContainer);
            })
            .catch(error => {
                console.error('Błąd pobierania danych:', error);
                document.getElementById('fileTree').innerHTML = '<div style="color: red;">Błąd pobierania struktury plików</div>';
            });
    </script>
</body>
</html>

przerób ten plik tak aby można było cały kod aplikacji skopiować jednym przyciskiem. Opisany który to którego pliku kod. ale wszystko na raz i może być też zapis do jednego pliku txt Pomujaj jedynie plik file_explorer.php