1+ <!doctype html>
2+ < html lang ="en ">
3+
4+ < head >
5+ < meta charset ="UTF-8 " />
6+ < meta name ="viewport " content ="width=device-width, initial-scale=1.0, user-scalable=no " />
7+ < title > Ratzilla</ title >
8+ < style >
9+ body {
10+ margin : 0 ;
11+ width : 100% ;
12+ height : 100vh ;
13+ display : flex;
14+ flex-direction : column;
15+ justify-content : center;
16+ align-items : center;
17+ align-content : center;
18+ background-color : # 121212 ;
19+ }
20+
21+ pre {
22+ font-family : monospace;
23+ font-size : 16px ;
24+ margin : 0px ;
25+ }
26+ </ style >
27+ < link rel ="modulepreload " href ="/tui-shader-eaa84b4af6e0d95e.js " crossorigin ="anonymous " integrity ="sha384-woJ1NmbrahLQb5IOznIyTC74moEccIbmV7RJ/Yi7B5p1TTPhjInpY97jtyZM7E6z "> < link rel ="preload " href ="/tui-shader-eaa84b4af6e0d95e_bg.wasm " crossorigin ="anonymous " integrity ="sha384-jucaB8mJYf61S4rwtoT3YRl67yao4Q/QDJLoROKVgMbHOxR4wuLSYstF1m9wpk6P " as ="fetch " type ="application/wasm "> </ head >
28+
29+ < body >
30+ < script type ="module ">
31+ import init from "./pkg/ratzilla.js" ;
32+ init ( ) ;
33+ </ script >
34+
35+ < script type ="module ">
36+ import init , * as bindings from '/tui-shader-eaa84b4af6e0d95e.js' ;
37+ const wasm = await init ( { module_or_path : '/tui-shader-eaa84b4af6e0d95e_bg.wasm' } ) ;
38+
39+
40+ window . wasmBindings = bindings ;
41+
42+
43+ dispatchEvent ( new CustomEvent ( "TrunkApplicationStarted" , { detail : { wasm} } ) ) ;
44+
45+ </ script > < script > "use strict" ;
46+
47+ ( function ( ) {
48+
49+ const address = '{{__TRUNK_ADDRESS__}}' ;
50+ const base = '{{__TRUNK_WS_BASE__}}' ;
51+ let protocol = '' ;
52+ protocol =
53+ protocol
54+ ? protocol
55+ : window . location . protocol === 'https:'
56+ ? 'wss'
57+ : 'ws' ;
58+ const url = protocol + '://' + address + base + '.well-known/trunk/ws' ;
59+
60+ class Overlay {
61+ constructor ( ) {
62+ // create an overlay
63+ this . _overlay = document . createElement ( "div" ) ;
64+ const style = this . _overlay . style ;
65+ style . height = "100vh" ;
66+ style . width = "100vw" ;
67+ style . position = "fixed" ;
68+ style . top = "0" ;
69+ style . left = "0" ;
70+ style . backgroundColor = "rgba(222, 222, 222, 0.5)" ;
71+ style . fontFamily = "sans-serif" ;
72+ // not sure that's the right approach
73+ style . zIndex = "1000000" ;
74+ style . backdropFilter = "blur(1rem)" ;
75+
76+ const container = document . createElement ( "div" ) ;
77+ // center it
78+ container . style . position = "absolute" ;
79+ container . style . top = "30%" ;
80+ container . style . left = "15%" ;
81+ container . style . maxWidth = "85%" ;
82+
83+ this . _title = document . createElement ( "div" ) ;
84+ this . _title . innerText = "Build failure" ;
85+ this . _title . style . paddingBottom = "2rem" ;
86+ this . _title . style . fontSize = "2.5rem" ;
87+
88+ this . _message = document . createElement ( "div" ) ;
89+ this . _message . style . whiteSpace = "pre-wrap" ;
90+
91+ const icon = document . createElement ( "div" ) ;
92+ icon . innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" fill="#dc3545" viewBox="0 0 16 16"><path d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"/></svg>' ;
93+ this . _title . prepend ( icon ) ;
94+
95+ container . append ( this . _title , this . _message ) ;
96+ this . _overlay . append ( container ) ;
97+
98+ this . _inject ( ) ;
99+ window . setInterval ( ( ) => {
100+ this . _inject ( ) ;
101+ } , 250 ) ;
102+ }
103+
104+ set reason ( reason ) {
105+ this . _message . textContent = reason ;
106+ }
107+
108+ _inject ( ) {
109+ if ( ! this . _overlay . isConnected ) {
110+ // prepend it
111+ document . body ?. prepend ( this . _overlay ) ;
112+ }
113+ }
114+
115+ }
116+
117+ class Client {
118+ constructor ( url ) {
119+ this . url = url ;
120+ this . poll_interval = 5000 ;
121+ this . _overlay = null ;
122+ }
123+
124+ start ( ) {
125+ const ws = new WebSocket ( this . url ) ;
126+ ws . onmessage = ( ev ) => {
127+ const msg = JSON . parse ( ev . data ) ;
128+ switch ( msg . type ) {
129+ case "reload" :
130+ this . reload ( ) ;
131+ break ;
132+ case "buildFailure" :
133+ this . buildFailure ( msg . data )
134+ break ;
135+ }
136+ } ;
137+ ws . onclose = ( ) => this . onclose ( ) ;
138+ }
139+
140+ onclose ( ) {
141+ window . setTimeout (
142+ ( ) => {
143+ // when we successfully reconnect, we'll force a
144+ // reload (since we presumably lost connection to
145+ // trunk due to it being killed, so it will have
146+ // rebuilt on restart)
147+ const ws = new WebSocket ( this . url ) ;
148+ ws . onopen = ( ) => window . location . reload ( ) ;
149+ ws . onclose = ( ) => this . onclose ( ) ;
150+ } ,
151+ this . poll_interval ) ;
152+ }
153+
154+ reload ( ) {
155+ window . location . reload ( ) ;
156+ }
157+
158+ buildFailure ( { reason} ) {
159+ // also log the console
160+ console . error ( "Build failed:" , reason ) ;
161+
162+ console . debug ( "Overlay" , this . _overlay ) ;
163+
164+ if ( ! this . _overlay ) {
165+ this . _overlay = new Overlay ( ) ;
166+ }
167+ this . _overlay . reason = reason ;
168+ }
169+ }
170+
171+ new Client ( url ) . start ( ) ;
172+
173+ } ) ( )
174+ </ script > </ body >
175+
176+ </ html >
0 commit comments