1
0
mirror of git://f0xx.org/android_cast synced 2026-07-29 04:57:40 +03:00

Shared platform footer template for hub and all PHP consoles.

Centralize copyright in examples/platform/footer.config.php, render via
footer.php in crashes/builder/login layouts, and serve hub through index.php.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Anton Afanasyeu
2026-06-02 18:54:13 +02:00
parent f885d194dd
commit 4803caebce
18 changed files with 1313 additions and 1100 deletions

View File

@@ -16,9 +16,13 @@ Browser → apps.f0xx.org (Gentoo FE, TLS)
On FE, hub and (if you fix it) crashes should both target **`http://artc0.intra.raptor.org:80`**, same as `location /`.
## 1. `index.html` + hub assets
## 1. Hub entry (`index.php`) + assets
Landing uses **`index.php`** (shared footer from `examples/platform/footer.config.php`). Copy **`index.html`** only as a redirect fallback.
```bash
cp .../android_cast/examples/app_hub/index.php \
.../htdocs/apps/app/androidcast_project/index.php
cp .../android_cast/examples/app_hub/index.html \
.../htdocs/apps/app/androidcast_project/index.html
cp .../android_cast/examples/app_hub/hub.css \
@@ -68,7 +72,7 @@ Use prefix location for the hub (not `alias` to a single file):
```nginx
location /app/androidcast_project/ {
alias /var/www/localhost/htdocs/apps/app/androidcast_project/;
index index.html;
index index.php index.html;
}
```

File diff suppressed because it is too large Load Diff

1093
examples/app_hub/index.php Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,7 @@ declare(strict_types=1);
$examplesRoot = dirname(__DIR__, 3);
require_once $examplesRoot . '/platform/shared_session.php';
require_once $examplesRoot . '/platform/footer.php';
$crashSrc = $examplesRoot . '/crash_reporter/backend/src';
$configPath = __DIR__ . '/../config/config.php';

View File

@@ -53,6 +53,6 @@ $links = cfg('links', []);
<?php endif; ?>
</main>
</div>
<footer class="bottom-bar">(c) Anton Afanaasyeu, <?= (int) date('Y') ?></footer>
<?php platform_render_footer(); ?>
</body>
</html>

View File

@@ -21,5 +21,6 @@ $ab = assets_base();
<label><span>Password</span><input name="password" type="password" autocomplete="current-password" required></label>
<button type="submit">Sign in</button>
</form>
<?php platform_render_footer(); ?>
</body>
</html>

View File

@@ -9,9 +9,21 @@ server {
return 301 /app/androidcast_project/;
}
location = /app/androidcast_project/index.php {
include fastcgi_params;
fastcgi_pass unix:/run/php-fpm.socket;
fastcgi_param SCRIPT_FILENAME /var/www/localhost/htdocs/apps/app/androidcast_project/index.php;
fastcgi_param SCRIPT_NAME /app/androidcast_project/index.php;
}
location = /app/androidcast_project/ {
rewrite ^ /app/androidcast_project/index.php last;
}
location /app/androidcast_project/ {
alias /var/www/localhost/htdocs/apps/app/androidcast_project/;
index index.html;
index index.php index.html;
try_files $uri $uri/ =404;
}
location = /app/androidcast_project/crashes {

View File

@@ -13,10 +13,22 @@
return 301 /app/androidcast_project/;
}
# Hub — live vhost is listen 80 on BE (see nginx.apps-port80.fragment). Not :8089.
# Hub — see nginx.apps-port80.fragment (index.php + shared footer).
location = /app/androidcast_project/index.php {
include fastcgi_params;
fastcgi_pass unix:/run/php-fpm.socket;
fastcgi_param SCRIPT_FILENAME /var/www/localhost/htdocs/apps/app/androidcast_project/index.php;
fastcgi_param SCRIPT_NAME /app/androidcast_project/index.php;
}
location = /app/androidcast_project/ {
rewrite ^ /app/androidcast_project/index.php last;
}
location /app/androidcast_project/ {
alias /var/www/localhost/htdocs/apps/app/androidcast_project/;
index index.html;
index index.php index.html;
try_files $uri $uri/ =404;
}
location ^~ /app/androidcast_project/crashes/assets/ {

View File

@@ -30,9 +30,21 @@ server {
return 301 /app/androidcast_project/;
}
location = /app/androidcast_project/index.php {
include fastcgi_params;
fastcgi_pass unix:/run/php-fpm.socket;
fastcgi_param SCRIPT_FILENAME /var/www/localhost/htdocs/apps/app/androidcast_project/index.php;
fastcgi_param SCRIPT_NAME /app/androidcast_project/index.php;
}
location = /app/androidcast_project/ {
rewrite ^ /app/androidcast_project/index.php last;
}
location /app/androidcast_project/ {
alias /var/www/localhost/htdocs/apps/app/androidcast_project/;
index index.html;
index index.php index.html;
try_files $uri $uri/ =404;
}
location ^~ /app/androidcast_project/crashes/assets/ {

View File

@@ -13,6 +13,7 @@
declare(strict_types=1);
require_once dirname(__DIR__, 3) . '/platform/shared_session.php';
require_once dirname(__DIR__, 3) . '/platform/footer.php';
if (!function_exists('session_start')) {
http_response_code(500);

View File

@@ -340,6 +340,6 @@
</div>
</div>
<?php endif; ?>
<footer class="bottom-bar" data-i18n="footer.copyright" data-year="<?= (int) date('Y') ?>">(c) Anton Afanaasyeu, <?= (int) date('Y') ?></footer>
<?php platform_render_footer(); ?>
</body>
</html>

View File

@@ -51,5 +51,6 @@ $bp = Auth::basePath();
<p class="hint" data-i18n="login.hint_default">Default: admin / admin</p>
<p class="hint"><span data-i18n="login.register">Register</span> <span data-i18n="login.register_soon">(coming soon)</span></p>
</form>
<?php platform_render_footer(); ?>
</body>
</html>

View File

@@ -0,0 +1,27 @@
# Shared platform pieces
## Footer (`footer.php`)
Single copyright footer for hub, crashes, tickets, graphs, and builder consoles.
**Configure:** edit `footer.config.php` (copy from `footer.config.example.php`).
| Key | Purpose |
|-----|---------|
| `holder` | Copyright name |
| `copyright_symbol` | `(c)` or `©` |
| `show_year` | Append year |
| `year` | Fixed year, or `null` for current |
| `use_i18n` | `data-i18n` for consoles with `i18n.js` |
**In PHP views:** `<?php platform_render_footer(); ?>` (loaded via each app `bootstrap.php`).
**Hub:** `examples/app_hub/index.php` (landing nginx runs it through PHP-FPM).
**Static HTML export:**
```bash
php examples/platform/scripts/render-footer-html.php
```
**Gitea** (`/git/`) uses the upstream Gitea UI; this footer does not apply there unless you customize Gitea templates separately.

View File

@@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
/**
* Site-wide footer (hub, crashes, tickets, graphs, builder).
* Copy to footer.config.php and edit; footer.config.php is optional (defaults apply).
*/
return [
// Visible copyright holder (also used in i18n {holder} if you customize strings).
'holder' => 'Anton Afanaasyeu',
// Prefix before the name: "(c)", "©", or "".
'copyright_symbol' => '(c)',
// Append current calendar year (or fixed year below).
'show_year' => true,
// null = (int) date('Y') at render time.
'year' => null,
// CSS class on <footer>.
'footer_class' => 'bottom-bar',
// When true, consoles with i18n.js replace text via data-i18n / data-year.
'use_i18n' => true,
'i18n_key' => 'footer.copyright',
];

View File

@@ -0,0 +1,4 @@
<?php
declare(strict_types=1);
return require __DIR__ . '/footer.config.example.php';

View File

@@ -0,0 +1,85 @@
<?php
declare(strict_types=1);
/**
* Shared footer fragment for Android Cast web consoles and hub.
*
* Configure: examples/platform/footer.config.php (see footer.config.example.php).
* Usage: <?php platform_render_footer(); ?> or platform_render_footer(['use_i18n' => false]);
*/
function platform_footer_h(mixed $value): string
{
return htmlspecialchars((string) $value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
/** @return array<string, mixed> */
function platform_footer_config(): array
{
static $loaded = null;
if ($loaded !== null) {
return $loaded;
}
$path = __DIR__ . '/footer.config.php';
if (!is_file($path)) {
$path = __DIR__ . '/footer.config.example.php';
}
$loaded = require $path;
return is_array($loaded) ? $loaded : [];
}
function platform_footer_year(array $cfg): int
{
if (array_key_exists('year', $cfg) && $cfg['year'] !== null) {
return (int) $cfg['year'];
}
return (int) date('Y');
}
function platform_footer_plain_text(array $cfg, int $year): string
{
$symbol = trim((string) ($cfg['copyright_symbol'] ?? '(c)'));
$holder = trim((string) ($cfg['holder'] ?? ''));
$showYear = (bool) ($cfg['show_year'] ?? true);
$parts = [];
if ($symbol !== '') {
$parts[] = $symbol;
}
if ($holder !== '') {
$parts[] = $holder;
}
$line = implode(' ', $parts);
if ($showYear && $line !== '') {
return $line . ', ' . $year;
}
if ($showYear && $line === '') {
return (string) $year;
}
return $line;
}
/**
* @param array{use_i18n?: bool, extra_class?: string} $opts
*/
function platform_render_footer(array $opts = []): void
{
$cfg = platform_footer_config();
$year = platform_footer_year($cfg);
$text = platform_footer_plain_text($cfg, $year);
$class = (string) ($opts['extra_class'] ?? ($cfg['footer_class'] ?? 'bottom-bar'));
$useI18n = $opts['use_i18n'] ?? (bool) ($cfg['use_i18n'] ?? true);
$i18nKey = (string) ($cfg['i18n_key'] ?? 'footer.copyright');
if ($useI18n && $i18nKey !== '') {
echo '<footer class="' . platform_footer_h($class) . '"'
. ' data-i18n="' . platform_footer_h($i18nKey) . '"'
. ' data-year="' . $year . '">'
. platform_footer_h($text)
. '</footer>';
return;
}
echo '<footer class="' . platform_footer_h($class) . '">' . platform_footer_h($text) . '</footer>';
}

View File

@@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
/**
* Emit a static footer.html from footer.config.php (for docs or static-only hosts).
*
* php examples/platform/scripts/render-footer-html.php > /path/to/footer.html
*/
require_once dirname(__DIR__) . '/footer.php';
ob_start();
platform_render_footer(['use_i18n' => false]);
$footer = ob_get_clean();
echo $footer . "\n";

View File

@@ -44,9 +44,20 @@ server {
add_header Cache-Control "public, max-age=60";
}
location = /app/androidcast_project/index.php {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /workspace/examples/app_hub/index.php;
fastcgi_param SCRIPT_NAME /app/androidcast_project/index.php;
fastcgi_pass crash-php:9000;
}
location = /app/androidcast_project/ {
rewrite ^ /app/androidcast_project/index.php last;
}
location /app/androidcast_project/ {
alias /workspace/examples/app_hub/;
index index.html;
try_files $uri $uri/ /app/androidcast_project/index.html;
index index.php index.html;
try_files $uri $uri/ =404;
}
}