1import { Controller } from "@hotwired/stimulus" 2 3// Connects to data-controller="auto-refresh" 4// Works in background tabs by using fetch polling + visibilitychange. 5export default class extends Controller { 6 static values = { 7 interval: { type: Number, default: 5000 }, 8 active: { type: Boolean, default: true } 9 } 10 11 connect() { 12 if (this.activeValue) { 13 this.startRefreshing() 14 } 15 } 16 17 disconnect() { 18 this.stopRefreshing() 19 } 20 21 startRefreshing() { 22 // Use a Web Worker for reliable background-tab timers 23 this._setupWorker() 24 25 // Fallback: also refresh immediately when tab becomes visible again 26 this._onVisibilityChange = () => { 27 if (document.visibilityState === "visible") { 28 this.refresh() 29 } 30 } 31 document.addEventListener("visibilitychange", this._onVisibilityChange) 32 } 33 34 stopRefreshing() { 35 if (this._worker) { 36 this._worker.terminate() 37 this._worker = null 38 } 39 if (this._onVisibilityChange) { 40 document.removeEventListener("visibilitychange", this._onVisibilityChange) 41 } 42 } 43 44 refresh() { 45 // Use Turbo to reload the page 46 window.location.reload() 47 } 48 49 // Web Workers are not throttled in background tabs 50 _setupWorker() { 51 const blob = new Blob([ 52 `setInterval(() => postMessage("tick"), ${this.intervalValue})` 53 ], { type: "application/javascript" }) 54 this._worker = new Worker(URL.createObjectURL(blob)) 55 this._worker.onmessage = () => this.refresh() 56 } 57}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.