| | <?php |
| | -require_once 'Page.php'; |
| | - |
| | abstract class BasePage implements Page { |
| | + protected $repositories; |
| | protected $title; |
| | |
| | - // Shared Layout Logic (Header/Nav) |
| | - protected function renderLayout($contentCallback, $repo = null) { |
| | + public function __construct(array $repositories) { |
| | + $this->repositories = $repositories; |
| | + } |
| | + |
| | + // Shared Layout Logic |
| | + protected function renderLayout($contentCallback, $currentRepo = null) { |
| | ?> |
| | <!DOCTYPE html> |
| | <html lang="en"> |
| | <head> |
| | <meta charset="UTF-8"> |
| | <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| | <title><?php echo Config::SITE_TITLE . ($this->title ? ' - ' . htmlspecialchars($this->title) : ''); ?></title> |
| | <link rel="stylesheet" href="kimi-style.css"> |
| | <style> |
| | - /* Inline styles preserved for portability */ |
| | .commit-list { margin-top: 20px; } |
| | .commit-row { display: flex; padding: 10px 0; border-bottom: 1px solid #eee; gap: 15px; align-items: baseline; } |
 |
| | <nav class="nav"> |
| | <a href="?">Home</a> |
| | - <?php if ($repo): |
| | - $safeName = urlencode($repo['safe_name']); ?> |
| | + <?php if ($currentRepo): |
| | + $safeName = urlencode($currentRepo['safe_name']); ?> |
| | <a href="?repo=<?php echo $safeName; ?>">Files</a> |
| | <a href="?action=commits&repo=<?php echo $safeName; ?>">Commits</a> |
| | <a href="?action=refs&repo=<?php echo $safeName; ?>">Branches</a> |
| | + <?php endif; ?> |
| | + |
| | + <?php if ($currentRepo): ?> |
| | + <div class="repo-selector"> |
| | + <label>Repository:</label> |
| | + <select onchange="window.location.href='?repo=' + encodeURIComponent(this.value)"> |
| | + <option value="">Select repository...</option> |
| | + <?php foreach ($this->repositories as $r): ?> |
| | + <option value="<?php echo htmlspecialchars($r['safe_name']); ?>" |
| | + <?php echo $r['safe_name'] === $currentRepo['safe_name'] ? 'selected' : ''; ?>> |
| | + <?php echo htmlspecialchars($r['name']); ?> |
| | + </option> |
| | + <?php endforeach; ?> |
| | + </select> |
| | + </div> |
| | <?php endif; ?> |
| | </nav> |
| | - <?php if ($repo): ?> |
| | + |
| | + <?php if ($currentRepo): ?> |
| | <div style="margin-top: 15px;"> |
| | - <span class="current-repo">Current: <strong><?php echo htmlspecialchars($repo['name']); ?></strong></span> |
| | + <span class="current-repo">Current: <strong><?php echo htmlspecialchars($currentRepo['name']); ?></strong></span> |
| | </div> |
| | <?php endif; ?> |
 |
| | |
| | class HomePage extends BasePage { |
| | - private $repositories; |
| | - |
| | - public function __construct(array $repositories) { |
| | - $this->repositories = $repositories; |
| | - } |
| | - |
| | public function render() { |
| | $this->renderLayout(function() { |
 |
| | |
| | class CommitsPage extends BasePage { |
| | - private $repo; |
| | + private $currentRepo; |
| | private $git; |
| | private $hash; |
| | |
| | - public function __construct($repo, $git, $hash) { |
| | - $this->repo = $repo; |
| | + public function __construct($allRepos, $currentRepo, $git, $hash) { |
| | + parent::__construct($allRepos); |
| | + $this->currentRepo = $currentRepo; |
| | $this->git = $git; |
| | $this->hash = $hash; |
| | - $this->title = $repo['name']; |
| | + $this->title = $currentRepo['name']; |
| | } |
| | |
 |
| | |
| | $start = $this->hash ?: $main['hash']; |
| | - $repoParam = '&repo=' . urlencode($this->repo['safe_name']); |
| | + $repoParam = '&repo=' . urlencode($this->currentRepo['safe_name']); |
| | |
| | $this->git->history($start, 100, function($commit) use ($repoParam) { |
 |
| | }); |
| | echo '</div>'; |
| | - }, $this->repo); |
| | + }, $this->currentRepo); |
| | } |
| | |
| | private function renderBreadcrumbs() { |
| | echo '<div class="breadcrumb">'; |
| | echo '<a href="?">Repositories</a><span>/</span>'; |
| | - echo '<a href="?repo=' . urlencode($this->repo['safe_name']) . '">' . htmlspecialchars($this->repo['name']) . '</a><span>/</span>'; |
| | + echo '<a href="?repo=' . urlencode($this->currentRepo['safe_name']) . '">' . htmlspecialchars($this->currentRepo['name']) . '</a><span>/</span>'; |
| | echo '<span>Commits</span></div>'; |
| | } |
| | } |
| | |
| | class FilePage extends BasePage { |
| | - private $repo; |
| | + private $currentRepo; |
| | private $git; |
| | private $hash; |
| | |
| | - public function __construct($repo, $git, $hash) { |
| | - $this->repo = $repo; |
| | + public function __construct($allRepos, $currentRepo, $git, $hash) { |
| | + parent::__construct($allRepos); |
| | + $this->currentRepo = $currentRepo; |
| | $this->git = $git; |
| | $this->hash = $hash; |
| | - $this->title = $repo['name']; |
| | + $this->title = $currentRepo['name']; |
| | } |
| | |
 |
| | $this->renderBlob($target); |
| | } |
| | - }, $this->repo); |
| | + }, $this->currentRepo); |
| | } |
| | |
| | private function renderTree($main, $targetHash, $entries) { |
| | $this->renderBreadcrumbs($targetHash, 'Tree'); |
| | - echo '<h2>' . htmlspecialchars($this->repo['name']) . ' <span class="branch-badge">' . htmlspecialchars($main['name']) . '</span></h2>'; |
| | + echo '<h2>' . htmlspecialchars($this->currentRepo['name']) . ' <span class="branch-badge">' . htmlspecialchars($main['name']) . '</span></h2>'; |
| | |
| | - // Sorting |
| | usort($entries, function($a, $b) { |
| | return ($b['isDir'] <=> $a['isDir']) ?: strcasecmp($a['name'], $b['name']); |
| | }); |
| | |
| | echo '<div class="file-list">'; |
| | foreach ($entries as $e) { |
| | $icon = $e['isDir'] ? '[dir]' : '[file]'; |
| | - $url = '?repo=' . urlencode($this->repo['safe_name']) . '&hash=' . $e['sha']; |
| | + $url = '?repo=' . urlencode($this->currentRepo['safe_name']) . '&hash=' . $e['sha']; |
| | echo '<a href="' . $url . '" class="file-item">'; |
| | echo '<span class="file-mode">' . $e['mode'] . '</span>'; |
 |
| | echo '<div class="breadcrumb">'; |
| | echo '<a href="?">Repositories</a><span>/</span>'; |
| | - echo '<a href="?repo=' . urlencode($this->repo['safe_name']) . '">' . htmlspecialchars($this->repo['name']) . '</a>'; |
| | + echo '<a href="?repo=' . urlencode($this->currentRepo['safe_name']) . '">' . htmlspecialchars($this->currentRepo['name']) . '</a>'; |
| | if ($this->hash) echo '<span>/</span><span>' . $type . ' ' . substr($hash, 0, 7) . '</span>'; |
| | echo '</div>'; |