Skip to content

Commit 3e12235

Browse files
Rich-HarrisRich Harris
andauthored
reinstate ping mechanism (sveltejs#345)
* reinstate ping mechanism * tidy up __client.js a bit * fix 298 --------- Co-authored-by: Rich Harris <[email protected]>
1 parent 0486052 commit 3e12235

File tree

2 files changed

+68
-96
lines changed

2 files changed

+68
-96
lines changed
Lines changed: 48 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,36 @@
1-
window.addEventListener('message', async (e) => {
2-
if (e.data.type === 'fetch') {
3-
const names = e.data.names;
4-
5-
const transformed = await Promise.all(
6-
names.map(async (name) => {
7-
const res = await fetch(name);
8-
return {
9-
name,
10-
code: await res.text()
11-
};
12-
})
13-
);
14-
15-
const css_files = [];
16-
17-
for (const { name, code } of transformed) {
18-
if (
19-
name.endsWith('.svelte') &&
20-
code.includes('svelte&type=style&lang.css')
21-
) {
22-
css_files.push(name + '?svelte&type=style&lang.css');
23-
}
24-
}
25-
26-
if (css_files.length > 0) {
27-
const css_transformed = await Promise.all(
28-
css_files.map(async (name) => {
29-
const res = await fetch(name);
30-
return {
31-
name,
32-
code: await res.text()
33-
};
34-
})
35-
);
36-
37-
transformed.push(...css_transformed);
38-
}
1+
function post(data) {
2+
parent.postMessage(data, '*');
3+
}
394

40-
parent.postMessage(
41-
{
42-
type: 'fetch-result',
43-
data: transformed
44-
},
45-
'*'
46-
);
47-
}
48-
});
5+
function ping() {
6+
post({
7+
type: 'ping',
8+
path: location.pathname + location.search + location.hash
9+
});
10+
}
4911

50-
let can_focus = false;
12+
function pause() {
13+
post({ type: 'ping-pause' });
14+
}
5115

52-
window.addEventListener('pointerdown', (e) => {
53-
can_focus = true;
54-
});
16+
// Hack into the alert that's used in some tutorials and send a message prior to the alert,
17+
// else the parent thinks we lost contact and wrongfully reloads the page.
18+
// The drawback is that alert is no longer blocking, but no tutorial relies on this.
19+
const alert = window.alert;
20+
window.alert = (message) => {
21+
pause();
5522

56-
window.addEventListener('pointerup', (e) => {
57-
can_focus = false;
58-
});
23+
setTimeout(() => {
24+
alert(message);
25+
});
26+
};
5927

60-
window.addEventListener('keydown', (e) => {
61-
can_focus = true;
62-
});
28+
let can_focus = false;
6329

64-
window.addEventListener('keyup', (e) => {
65-
can_focus = false;
66-
});
30+
window.addEventListener('pointerdown', (e) => can_focus = true);
31+
window.addEventListener('pointerup', (e) => can_focus = false);
32+
window.addEventListener('keydown', (e) => can_focus = true);
33+
window.addEventListener('keyup', (e) => can_focus = false);
6734

6835
/**
6936
* The iframe sometimes takes focus control in ways we can't prevent
@@ -78,12 +45,7 @@ window.addEventListener('focusin', (e) => {
7845
if (e.target.tagName === 'BODY' && e.relatedTarget) return;
7946

8047
// otherwise, broadcast an event that causes the editor to reclaim focus
81-
parent.postMessage(
82-
{
83-
type: 'iframe_took_focus'
84-
},
85-
'*'
86-
);
48+
post({ type: 'iframe_took_focus' });
8749
});
8850

8951
window.addEventListener('click', (e) => {
@@ -102,47 +64,38 @@ window.addEventListener('click', (e) => {
10264
}
10365
});
10466

105-
function ping() {
106-
parent.postMessage(
107-
{
108-
type: 'ping',
109-
data: {
110-
path: location.pathname + location.search + location.hash
111-
}
112-
},
113-
'*'
114-
);
115-
}
67+
window.addEventListener('visibilitychange', () => {
68+
if (document.visibilityState === 'visible') {
69+
ping();
70+
} else {
71+
pause();
72+
}
73+
});
74+
75+
let previous_href = location.href;
11676

117-
let pre_url = location.href;
11877
const url_observer = new MutationObserver(() => {
119-
if (location.href !== pre_url) {
120-
pre_url = location.href;
78+
if (location.href !== previous_href) {
79+
previous_href = location.href;
12180
ping();
12281
}
12382
});
124-
url_observer.observe(document, { subtree: true, childList: true, attributes: true });
12583

84+
url_observer.observe(document, {
85+
subtree: true,
86+
childList: true,
87+
attributes: true
88+
});
89+
90+
setInterval(ping, 100);
12691
ping();
12792

12893
if (import.meta.hot) {
12994
import.meta.hot.on('vite:beforeUpdate', (event) => {
130-
parent.postMessage(
131-
{
132-
type: 'hmr',
133-
data: event.updates
134-
},
135-
'*'
136-
);
95+
post({ type: 'hmr', data: event.updates });
13796
});
13897

13998
import.meta.hot.on('svelte:warnings', (data) => {
140-
parent.postMessage(
141-
{
142-
type: 'warnings',
143-
data
144-
},
145-
'*'
146-
);
99+
post({ type: 'warnings', data });
147100
});
148101
}

src/routes/tutorial/[slug]/Output.svelte

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,34 @@
3434
};
3535
});
3636
37+
afterNavigate(() => {
38+
clearTimeout(timeout);
39+
});
40+
41+
/** @type {any} */
42+
let timeout;
43+
3744
/** @param {MessageEvent} e */
3845
async function handle_message(e) {
3946
if (e.origin !== $base) return;
4047
4148
if (paused) return;
4249
4350
if (e.data.type === 'ping') {
44-
path = e.data.data.path ?? path;
51+
path = e.data.path;
4552
loading = false;
53+
54+
clearTimeout(timeout);
55+
timeout = setTimeout(() => {
56+
if (dev && !iframe) return;
57+
58+
// we lost contact, refresh the page
59+
loading = true;
60+
set_iframe_src($base + path);
61+
loading = false;
62+
}, 1000);
63+
} else if (e.data.type === 'ping-pause') {
64+
clearTimeout(timeout);
4665
} else if (e.data.type === 'warnings') {
4766
warnings.update(($warnings) => ({
4867
...$warnings,

0 commit comments

Comments
 (0)