From e7483dfc24815073c78d6b7d76f6c34f17ef80b9 Mon Sep 17 00:00:00 2001 From: Fabian Mendoza Date: Thu, 23 Jul 2026 11:25:00 -0400 Subject: [PATCH] feat(ui): show server URL in Add Display modal + GitHub Releases link on /download/apk (#210) - Add Device modal now shows the server URL and full Smart TV player URL - Smart TV note changed from bare /player to full URL (dynamic via JS) - /download/apk error page now includes a download link to GitHub Releases - i18n keys added in en + es, old smart_tv_note removed --- frontend/index.html | 11 ++++++++--- frontend/js/i18n/en.js | 4 +++- frontend/js/i18n/es.js | 4 +++- frontend/js/views/dashboard.js | 6 ++++++ server/server.js | 2 +- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/frontend/index.html b/frontend/index.html index 44c36d0..ec49af1 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -184,8 +184,13 @@ -
-

Need a player app? Install one to get a pairing code:

+
+ Server URL + + Use this URL when configuring the Android app +
+
+

Need a player app? Install one to get a pairing code:

🤖 Android APK @@ -200,7 +205,7 @@ 💻 Windows
-

Smart TVs (LG/Samsung): open the built-in browser and navigate to /player

+

Smart TVs (LG/Samsung): open the built-in browser and navigate to /player

Provisioning a fresh / factory-reset Android panel? Enroll it as device owner for silent updates, reboot & kiosk:

diff --git a/frontend/js/i18n/en.js b/frontend/js/i18n/en.js index 4a7704b..15ccb2e 100644 --- a/frontend/js/i18n/en.js +++ b/frontend/js/i18n/en.js @@ -1530,10 +1530,12 @@ export default { 'add_display.web_player': 'Web Player', 'add_display.raspberry_pi': 'Raspberry Pi', 'add_display.windows': 'Windows', - 'add_display.smart_tv_note': 'Smart TVs (LG/Samsung): open the built-in browser and navigate to /player', 'add_display.owner_prompt': 'Provisioning a fresh / factory-reset Android panel? Enroll it as device owner for silent updates, reboot & kiosk:', 'add_display.owner_qr_btn': 'Show device-owner QR', 'add_display.pair_btn': 'Pair Display', + 'add_display.server_url_label': 'Server URL', + 'add_display.server_url_hint': 'Use this URL when configuring the Android app', + 'add_display.smart_tv_prefix': 'Smart TVs (LG/Samsung): open the built-in browser and navigate to', // Workspace switcher (Phase 3 MVP). devices_count is the only count exposed // today; matching pattern for users/playlists/etc. when those land later. diff --git a/frontend/js/i18n/es.js b/frontend/js/i18n/es.js index 7e5e3f6..2b610c8 100644 --- a/frontend/js/i18n/es.js +++ b/frontend/js/i18n/es.js @@ -1176,6 +1176,8 @@ export default { 'add_display.web_player': 'Reproductor web', 'add_display.raspberry_pi': 'Raspberry Pi', 'add_display.windows': 'Windows', - 'add_display.smart_tv_note': 'Smart TVs (LG/Samsung): abre el navegador integrado y ve a /player', 'add_display.pair_btn': 'Vincular pantalla', + 'add_display.server_url_label': 'URL del servidor', + 'add_display.server_url_hint': 'Usa esta URL al configurar la app de Android', + 'add_display.smart_tv_prefix': 'Smart TVs (LG/Samsung): abre el navegador integrado y ve a', }; diff --git a/frontend/js/views/dashboard.js b/frontend/js/views/dashboard.js index 6ddb747..2eb42e1 100644 --- a/frontend/js/views/dashboard.js +++ b/frontend/js/views/dashboard.js @@ -297,6 +297,12 @@ export function render(container) { document.getElementById('pairingCodeInput').value = ''; document.getElementById('deviceNameInput').value = ''; document.getElementById('pairingCodeInput').focus(); + + const serverUrl = `${window.location.protocol}//${window.location.host}`; + const el = document.getElementById('addDeviceServerUrl'); + if (el) el.textContent = serverUrl; + const tvEl = document.getElementById('addDeviceSmartTvUrl'); + if (tvEl) tvEl.textContent = `${serverUrl}/player`; }); // #device-owner: provision a fresh/factory-reset Android panel straight from Add Display. diff --git a/server/server.js b/server/server.js index f0c1ac5..4133ba9 100644 --- a/server/server.js +++ b/server/server.js @@ -943,7 +943,7 @@ const otaDownloadState = otaDownloadGuard.prodState(); // #146 P3.8: shared si app.get('/download/apk', (req, res) => { const apk = apkCache.get(); if (!apk.exists) { - return res.status(404).send(`APK Not Found

APK Not Available

The Android APK has not been compiled yet. In Docker, mount a built APK at /data/ScreenTinker.apk, or use the web player.

`); + return res.status(404).send(`APK Not Available — ScreenTinker

APK Not Available

The Android APK has not been compiled yet.

📦 Download from GitHub Releases

Self-hosting? Mount a built APK at /data/ScreenTinker.apk to serve it from this instance. Or use the web player instead.

`); } const verdict = otaDownloadGuard.admit(otaDownloadState, getBand());