From dbe0a83636e7749e8ade785078f740449d798898 Mon Sep 17 00:00:00 2001 From: Anton Afanasyeu Date: Sun, 12 Jul 2026 13:53:14 +0200 Subject: [PATCH] feat(platform): shared nav shell and common footer config Signed-off-by: Anton Afanasyeu --- platform/footer.config.example.php | 6 +- platform/footer.php | 2 + platform/nav_shell.php | 126 +++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 platform/nav_shell.php diff --git a/platform/footer.config.example.php b/platform/footer.config.example.php index 0d3209f..2851375 100644 --- a/platform/footer.config.example.php +++ b/platform/footer.config.example.php @@ -21,11 +21,11 @@ return [ // --- Default left column when `left` is null --- // Use holder_name + holder_url for a safe link (holder HTML is escaped if used alone). - 'holder_name' => 'Anton Afanaasyeu', + 'holder_name' => 'Anton Afanasyeu', 'holder_url' => 'https://f0xx.org', 'holder' => null, - 'copyright_symbol' => "\u{00A9}", - 'show_year' => false, + 'copyright_symbol' => '', + 'show_year' => true, // null = current calendar year at render time (end of range). 'year' => null, // Integer start year. With year_through_current: "2026 - current" (literal suffix). diff --git a/platform/footer.php b/platform/footer.php index d7dee69..4401c63 100644 --- a/platform/footer.php +++ b/platform/footer.php @@ -1,6 +1,8 @@ '/app/androidcast_project', 'active' => 'builder', ...]); + */ + +function platform_nav_h(string $s): string +{ + return htmlspecialchars($s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); +} + +/** @param array $opts */ +function platform_render_nav_shell(array $opts = []): void +{ + $projectBase = rtrim((string) ($opts['project_base'] ?? '/app/androidcast_project'), '/'); + $issuesBase = rtrim((string) ($opts['issues_base'] ?? $projectBase . '/issues'), '/'); + $active = (string) ($opts['active'] ?? ''); + $username = trim((string) ($opts['username'] ?? '')); + $paneId = (string) ($opts['pane_id'] ?? 'nav-pane'); + $handleId = (string) ($opts['handle_id'] ?? 'nav-handle'); + $extraClass = trim((string) ($opts['extra_class'] ?? 'landing-left')); + + $navClass = 'nav-pane' . ($extraClass !== '' ? ' ' . platform_nav_h($extraClass) : ''); + + $isActive = static fn(string $id): string => $active === $id ? ' active' : ''; + + $items = [ + ['id' => 'console', 'href' => $issuesBase . '/?view=home', 'icon' => 'home', 'label' => 'Console', 'desc' => 'Crash triage home and workspace cards.', 'i18n' => 'nav.console', 'i18n_desc' => 'nav.console_desc'], + ['id' => 'git', 'href' => $projectBase . '/git/', 'icon' => 'git', 'label' => 'Git', 'desc' => 'Browse repos, branches, and tags.', 'i18n' => 'nav.git', 'i18n_desc' => 'nav.git_desc'], + ['id' => 'issues', 'href' => $issuesBase . '/?view=reports', 'icon' => 'reports', 'label' => 'Issues', 'desc' => 'Browse and triage crash reports.', 'i18n' => 'nav.issues', 'i18n_desc' => 'nav.issues_desc'], + ['id' => 'tickets', 'href' => $issuesBase . '/?view=tickets', 'icon' => 'tickets', 'label' => 'Tickets', 'desc' => 'Roadmap tasks, QA items, and tags.', 'i18n' => 'nav.tickets', 'i18n_desc' => 'nav.tickets_desc'], + ['id' => 'graphs', 'href' => $projectBase . '/graphs/', 'icon' => 'graphs', 'label' => 'Analytics', 'desc' => 'Sessions, live cast stats, and device activity.', 'i18n' => 'nav.graphs', 'i18n_desc' => 'nav.graphs_desc'], + ['id' => 'monitor', 'href' => $projectBase . '/monitor/', 'icon' => 'monitor', 'label' => 'Monitoring', 'desc' => 'Grafana dashboards — cluster health, alerts, exporters.', 'i18n' => 'nav.monitor', 'i18n_desc' => 'nav.monitor_desc'], + ['id' => 'live_sessions', 'href' => $issuesBase . '/?view=live_sessions', 'icon' => 'live', 'label' => 'Live sessions', 'desc' => 'Cast intents, join stats, session history.', 'i18n' => 'nav.live_sessions', 'i18n_desc' => 'nav.live_sessions_desc'], + ['id' => 'education', 'href' => $issuesBase . '/live/education', 'icon' => 'education', 'label' => 'Education (demo)', 'desc' => 'Browser screen-share trial (5 min).', 'i18n' => 'nav.education', 'i18n_desc' => 'nav.education_desc'], + ['id' => 'remote', 'href' => $issuesBase . '/?view=remote_access', 'icon' => 'remote', 'label' => 'Remote access', 'desc' => 'WireGuard sessions and device reachability.', 'i18n' => 'nav.remote', 'i18n_desc' => 'nav.remote_desc'], + ['id' => 'short_links', 'href' => $issuesBase . '/?view=short_links', 'icon' => 'link', 'label' => 'Short links', 'desc' => 'Mint bearer tokens and shorten URLs for s.f0xx.org.', 'i18n' => 'nav.short_links', 'i18n_desc' => 'nav.short_links_desc'], + ['id' => 'builder', 'href' => $projectBase . '/build/', 'icon' => 'builder', 'label' => 'Builder', 'desc' => 'Docker CI for APK baking and OTA artifacts.', 'i18n' => 'nav.builder', 'i18n_desc' => 'nav.builder_desc'], + ]; + ?> + + 'console', + 'reports', 'report' => 'issues', + 'tickets', 'ticket' => 'tickets', + 'graphs' => 'graphs', + 'live_sessions' => 'live_sessions', + 'live_education' => 'education', + 'remote_access' => 'remote', + 'short_links' => 'short_links', + 'media_pipelines' => 'console', + 'rbac' => 'console', + default => '', + }; +}