1// Copyright (C) 2021 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15let lastReloadDialogTime = 0; 16const kMinTimeBetweenDialogsMs = 10000; 17const changedPaths = new Set<string>(); 18 19export function initLiveReloadIfLocalhost() { 20 if (!location.origin.startsWith('http://localhost:')) return; 21 22 const monitor = new EventSource('/live_reload'); 23 monitor.onmessage = msg => { 24 const change = msg.data; 25 console.log('Live reload:', change); 26 changedPaths.add(change); 27 if (change.endsWith('.css')) { 28 reloadCSS(); 29 } else if (change.endsWith('.html') || change.endsWith('.js')) { 30 reloadDelayed(); 31 } 32 }; 33 monitor.onerror = (err) => { 34 // In most cases the error is fired on reload, when the socket disconnects. 35 // Delay the error and the reconnection, so in the case of a reload we don't 36 // see any midleading message. 37 setTimeout(() => console.error('LiveReload SSE error', err), 1000); 38 }; 39} 40 41function reloadCSS() { 42 const css = document.querySelector('link[rel=stylesheet]') as HTMLLinkElement; 43 if (!css) return; 44 const parent = css.parentElement!; 45 parent.removeChild(css); 46 parent.appendChild(css); 47} 48 49function reloadDelayed() { 50 setTimeout(() => { 51 let pathsStr = ''; 52 for (const path of changedPaths) { 53 pathsStr += path + '\n'; 54 } 55 changedPaths.clear(); 56 if (Date.now() - lastReloadDialogTime < kMinTimeBetweenDialogsMs) return; 57 const reload = confirm(`${pathsStr}changed, click to reload`); 58 lastReloadDialogTime = Date.now(); 59 if (reload) { 60 window.location.reload(); 61 } 62 }, 1000); 63} 64