diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 574afe4..e55d843 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -41,13 +41,20 @@ jobs: aws s3 sync dist/reqsai-web/browser/ s3://${{ env.S3_BUCKET }}/ \ --delete \ --exclude "index.html" \ + --exclude "i18n/*" \ --cache-control "public,max-age=31536000,immutable" - - name: Upload index.html to S3 (no cache — shell must always be fresh) + - name: Upload index.html and i18n to S3 (no cache — must always be fresh) run: | + # index.html and the i18n JSON have STABLE, non-fingerprinted names, so they must + # never be served "immutable" — otherwise a browser caches them for a year and never + # picks up new translations after a deploy. Serve them revalidatable instead. aws s3 cp dist/reqsai-web/browser/index.html \ s3://${{ env.S3_BUCKET }}/index.html \ --cache-control "no-cache,no-store,must-revalidate" + aws s3 cp dist/reqsai-web/browser/i18n/ \ + s3://${{ env.S3_BUCKET }}/i18n/ --recursive \ + --cache-control "no-cache,must-revalidate" - name: Invalidate CloudFront cache run: | diff --git a/src/app/features/discovery/data/session-recording.service.ts b/src/app/features/discovery/data/session-recording.service.ts index 986c66d..2e73aab 100644 --- a/src/app/features/discovery/data/session-recording.service.ts +++ b/src/app/features/discovery/data/session-recording.service.ts @@ -45,7 +45,12 @@ export class SessionRecordingService { private readonly nowMs = signal(Date.now()); /** Recorded time in ms, frozen while paused. */ readonly elapsedMs = computed(() => { - const running = this.resumedAtEpochMs === null ? 0 : this.nowMs() - this.resumedAtEpochMs; + // Read nowMs() UNCONDITIONALLY so this computed always keeps its dependency on the tick signal. + // If nowMs() were only read in the "running" branch, then while paused (resumedAtEpochMs === null) + // the ternary short-circuits, the computed records ZERO signal dependencies, and it never re-runs + // on resume — freezing the timer at the paused value until a full page reload. + const now = this.nowMs(); + const running = this.resumedAtEpochMs === null ? 0 : now - this.resumedAtEpochMs; return this.accumulatedMs + Math.max(0, running); });