From 0741f46acabe9a594045799833781dddc57417cb Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 3 May 2026 16:50:03 +0000 Subject: [PATCH] feat: add self-contained legacy timer viewer for old browsers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds timer-legacy.html — a zero-dependency static page that connects to the Ontime WebSocket and displays the live countdown for browsers that cannot parse the Vite-built React bundle (Safari < 14, Chrome < 85). Also adds a synchronous pre-React guard in index.html that redirects /timer visitors to the legacy page when Promise.any is unavailable, matching the Vite build target floor of Safari 14 / Chrome 85. https://claude.ai/code/session_013MfdwdjdDUnr3akpGSGXa4 --- apps/client/index.html | 7 + apps/server/src/app.ts | 7 +- apps/server/src/html/timer-legacy.html | 218 +++++++++++++++++++++++++ apps/server/src/setup/index.ts | 2 + 4 files changed, 233 insertions(+), 1 deletion(-) create mode 100644 apps/server/src/html/timer-legacy.html diff --git a/apps/client/index.html b/apps/client/index.html index 478f5f38d..7ecb28091 100644 --- a/apps/client/index.html +++ b/apps/client/index.html @@ -18,6 +18,13 @@
+ diff --git a/apps/server/src/app.ts b/apps/server/src/app.ts index 290e3bcc7..45e442738 100644 --- a/apps/server/src/app.ts +++ b/apps/server/src/app.ts @@ -32,7 +32,7 @@ import { runtimeService } from './services/runtime-service/runtime.service.js'; import { timerConfig } from './setup/config.js'; import { environment, isProduction } from './setup/environment.js'; // import utils -import { publicDir, srcDir } from './setup/index.js'; +import { publicDir, srcDir, srcFiles } from './setup/index.js'; import { populateDemo } from './setup/loadDemo.js'; import { populateStyles } from './setup/loadStyles.js'; import { populateTranslation } from './setup/loadTranslations.js'; @@ -113,6 +113,11 @@ app.use(`${prefix}/external`, (req, res) => { }); app.use(`${prefix}/user`, express.static(publicDir.userDir, { etag: false, lastModified: true })); +// Serve legacy timer for old browsers that don't support modern JS +app.get(`${prefix}/timer-legacy`, authenticateAndRedirect, (_req, res) => { + res.sendFile(srcFiles.timerLegacy); +}); + // Base route for static files app.use(`${prefix}`, authenticateAndRedirect, compressedStatic); app.use(`${prefix}/*splat`, authenticateAndRedirect, compressedStatic); diff --git a/apps/server/src/html/timer-legacy.html b/apps/server/src/html/timer-legacy.html new file mode 100644 index 000000000..726b37747 --- /dev/null +++ b/apps/server/src/html/timer-legacy.html @@ -0,0 +1,218 @@ + + + + + + + Ontime Timer + + + +
+
--:--
+
+
+
+
+
+ + + diff --git a/apps/server/src/setup/index.ts b/apps/server/src/setup/index.ts index 5043769a3..b5e44cda3 100644 --- a/apps/server/src/setup/index.ts +++ b/apps/server/src/setup/index.ts @@ -95,6 +95,8 @@ export const srcFiles = { translationReadme: join(srcDir.root, config.user, config.translations.directory, 'README.md'), /** Path to login */ login: join(srcDir.root, 'html/login.html'), + /** Path to legacy timer for old browsers */ + timerLegacy: join(srcDir.root, 'html/timer-legacy.html'), /** Path to ontime-logo */ logo: join(srcDir.root, config.user, config.logo, 'ontime-logo.png'), };