diff --git a/fasthtml/live_reload.py b/fasthtml/live_reload.py index a9d0d073..84cfbd30 100644 --- a/fasthtml/live_reload.py +++ b/fasthtml/live_reload.py @@ -4,24 +4,25 @@ __all__ = ["FastHTMLWithLiveReload"] -LIVE_RELOAD_SCRIPT = """ - (function() {{ - var socket = new WebSocket(`ws://${{window.location.host}}/live-reload`); - var maxReloadAttempts = {reload_attempts}; - var reloadInterval = {reload_interval}; // time between reload attempts in ms - socket.onclose = function() {{ +def LiveReloadJs(reload_attempts:int=1, reload_interval:float=1000., **kwargs): + src = """ + (function() { + var socket = new WebSocket(`ws://${window.location.host}/live-reload`); + var maxReloadAttempts = %s; + var reloadInterval = %s; // time between reload attempts in ms + socket.onclose = function() { let reloadAttempts = 0; - const intervalFn = setInterval(function(){{ + const intervalFn = setInterval(function(){ window.location.reload(); reloadAttempts++; if (reloadAttempts === maxReloadAttempts) clearInterval(intervalFn); - }}, reloadInterval); - }} - }})(); + }, reloadInterval); + } + })(); """ + return Script(src % (reload_attempts, reload_interval)) - -async def live_reload_websocket(websocket): await websocket.accept() +async def live_reload_ws(websocket): await websocket.accept() class FastHTMLWithLiveReload(FastHTML): """ @@ -47,19 +48,8 @@ class FastHTMLWithLiveReload(FastHTML): Run: serve() """ - LIVE_RELOAD_ROUTE = WebSocketRoute("/live-reload", endpoint=live_reload_websocket) - def __init__(self, *args, **kwargs): - # Create the live reload script to be injected into the webpage - self.LIVE_RELOAD_HEADER = Script( - LIVE_RELOAD_SCRIPT.format( - reload_attempts=kwargs.get("reload_attempts", 1), - reload_interval=kwargs.get("reload_interval", 1000), - ) - ) - # "hdrs" and "routes" can be missing, None, a list or a tuple. - kwargs["hdrs"] = [*(kwargs.get("hdrs") or []), self.LIVE_RELOAD_HEADER] - kwargs["routes"] = [*(kwargs.get("routes") or []), self.LIVE_RELOAD_ROUTE] + kwargs["hdrs"] = [*(kwargs.get("hdrs") or []), LiveReloadJs(**kwargs)] + kwargs["routes"] = [*(kwargs.get("routes") or []), WebSocketRoute("/live-reload", endpoint=live_reload_ws)] super().__init__(*args, **kwargs) - diff --git a/fasthtml/toaster.py b/fasthtml/toaster.py index 5856643b..2991798b 100644 --- a/fasthtml/toaster.py +++ b/fasthtml/toaster.py @@ -31,27 +31,31 @@ .fh-toast-error { background-color: #F44336; } """ -toast_js = """ -export function proc_htmx(sel, func) {{ - htmx.onLoad(elt => {{ +def ToastJs(duration:float): + duration = int(1000*duration) + src = """ +export function proc_htmx(sel, func) { + htmx.onLoad(elt => { const elements = any(sel, elt, false); if (elt.matches && elt.matches(sel)) elements.unshift(elt); elements.forEach(func); - }}); -}} -proc_htmx('.fh-toast-container', async function(toast) {{ + }); +} +proc_htmx('.fh-toast-container', async function(toast) { await sleep(100); toast.style.opacity = '0.8'; - await sleep({duration}); + await sleep(%s); toast.style.opacity = '0'; await sleep(300); toast.remove(); -}}); +}); -proc_htmx('.fh-toast-dismiss', function(elem) {{ - elem.addEventListener('click', (e) => {{ e.target.parentElement.remove() }}); -}}); +proc_htmx('.fh-toast-dismiss', function(elem) { + elem.addEventListener('click', (e) => { e.target.parentElement.remove() }); +}); """ + return Script(src % (duration,), type="module") + def add_toast(sess, message, typ="info"): assert typ in ("info", "success", "warning", "error"), '`typ` not in ("info", "success", "warning", "error")' @@ -65,5 +69,5 @@ def toast_after(resp, req, sess): if sk in sess and (not resp or isinstance(resp, (tuple,FT,FtResponse))): req.injects.append(render_toasts(sess)) def setup_toasts(app, duration:float=10.): - app.hdrs += (Style(toast_css), Script(toast_js.format(duration=1000*duration), type="module")) + app.hdrs += (Style(toast_css), ToastJs(duration)) app.after.append(toast_after)