11import 'dart:async' ;
2+ import 'dart:convert' ;
23import 'dart:developer' ;
34
45import 'package:universal_web/js_interop.dart' ;
@@ -21,6 +22,51 @@ class ClientAppBinding extends AppBinding with ComponentsBinding {
2122 rootElement? .visitChildren ((element) => element.reassemble ());
2223 return ServiceExtensionResponse .result ('{}' );
2324 });
25+ registerExtension ('ext.jaspr.reload_stylesheets' , (method, parameters) async {
26+ final urls = (jsonDecode (parameters['urls' ]! ) as List ).cast <String >();
27+
28+ void reloadStylesheet (web.Element oldLink, String url, {int retries = 5 }) {
29+ final newLink = web.document.createElement ('link' ) as web.HTMLLinkElement ;
30+ newLink.rel = 'stylesheet' ;
31+ newLink.href = '$url ?v=${DateTime .now ().millisecondsSinceEpoch }' ;
32+
33+ StreamSubscription <void >? loadSub;
34+ StreamSubscription <void >? errorSub;
35+
36+ void cleanup () {
37+ loadSub? .cancel ();
38+ errorSub? .cancel ();
39+ }
40+
41+ loadSub = web.EventStreamProvider <web.Event >('load' ).forElement (newLink).listen ((_) {
42+ cleanup ();
43+ oldLink.remove ();
44+ });
45+
46+ errorSub = web.EventStreamProvider <web.Event >('error' ).forElement (newLink).listen ((_) {
47+ cleanup ();
48+ newLink.remove ();
49+ if (retries > 0 ) {
50+ Future .delayed (const Duration (milliseconds: 500 ), () {
51+ reloadStylesheet (oldLink, url, retries: retries - 1 );
52+ });
53+ } else {
54+ print ('Failed to reload stylesheet $url after 5 retries.' );
55+ }
56+ });
57+
58+ oldLink.parentNode? .insertBefore (newLink, oldLink.nextSibling);
59+ }
60+
61+ // Reload all stylesheet <link> tags.
62+ for (final url in urls) {
63+ final link = web.document.querySelector ('link[rel="stylesheet"][href^="$url "]' );
64+ if (link != null ) {
65+ reloadStylesheet (link, url);
66+ }
67+ }
68+ return ServiceExtensionResponse .result ('{}' );
69+ });
2470 return true ;
2571 }());
2672 }
0 commit comments