-
Notifications
You must be signed in to change notification settings - Fork 2
/
viewer.html
138 lines (129 loc) · 5.27 KB
/
viewer.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type"/>
</head>
<body>
<canvas style="position: absolute;top:0;bottom: 0;left: 0;right: 0;margin:auto;"></canvas>
<p id="status_text"></p>
<script>
var collected = 0;
var total_length = 0;
var recording_bytes = new Uint8Array();
var recording_available = false;
var download_done = true;
function get_recording_available() {
return recording_available;
}
function get_recording_bytes() {
return recording_bytes;
}
</script>
<!-- Note the usage of `type=module` here as this is an ES6 module -->
<script type="module">
// Use ES module import syntax to import functionality from the module
// that we have compiled.
//
// Note that the `default` import is an initialization function which
// will "boot" the module and make it ready to use. Currently browsers
// don't support natively imported WebAssembly as an ES module, but
// eventually the manual initialization won't be required!
import init from './pkg/web.js';
export async function run() {
// First up we need to actually load the wasm file, so we use the
// default export to inform it where the wasm file is located on the
// server, and then we wait on the returned promise to wait for the
// wasm to be loaded.
// It may look like this: `await init('./pkg/without_a_bundler_bg.wasm');`,
// but there is also a handy default inside `init` function, which uses
// `import.meta` to locate the wasm file relatively to js file
//
// Note that instead of a string here you can also pass in an instance
// of `WebAssembly.Module` which allows you to compile your own module.
// Also note that the promise, when resolved, yields the wasm module's
// exports which is the same as importing the `*_bg` module in other
// modes
await init('./pkg/web_bg.wasm');
}
// Expose run in the window for later launching.
window.run_start = run;
</script>
<script>
let launch_viewer = () => {
// If the module hasn't been processed yet, run_start doesn't exist, so here we defer to
// later if it is not present.
if (!download_done) {
setTimeout(launch_viewer, 100);
return;
}
if (window.run_start === undefined) {
setTimeout(launch_viewer, 100);
} else {
window.run_start();
}
};
const urlParams = new URLSearchParams(window.location.search);
const recording_url = urlParams.get('url');
if (recording_url) {
fetch(recording_url)
.then((response) => {
// Check if it was ok, else throw an error to let catch handle it.
if (!response.ok) {
throw new Error(`${response.status}: ${response.statusText} for ${response.url}`);
}
download_done = false;
const reader = response.body.getReader();
total_length = response.headers.get('Content-Length');
return new ReadableStream({
start(controller) {
return pump();
function pump() {
return reader.read().then(({ done, value }) => {
collected += value.length;
console.log(collected, total_length);
document.getElementById("status_text").innerHTML = `Downloading recording: ${collected}/${total_length} (${((collected / total_length) * 100.0).toFixed(2)} %)`;
// Couldn't really figure out how to elegantly collect bytes using streams, so we use this here.
// Odd way of concatenating, but seems to be the only way.
var combined = new Uint8Array(recording_bytes.length + value.length);
combined.set(recording_bytes);
combined.set(value, recording_bytes.length);
recording_bytes = combined;
if (combined.length == total_length) {
recording_available = true;
download_done = true;
controller.close();
return;
}
// When no more data needs to be consumed, close the stream
if (done) {
// never seem to get here? Possibly because the stream never completes?
console.log("done");
recording_available = true;
download_done = true;
controller.close();
return;
}
// Enqueue the next data chunk into our target stream
controller.enqueue(value);
return pump();
});
}
}
})
})
.then((foo) => {
console.log(foo);
// completed the download, launch the viewer.
launch_viewer();
})
.catch((err) => {
// something bad happened, show the error.
document.getElementById("status_text").innerHTML = `${err}`;
console.error(err)
});
} else {
// no recording url.
launch_viewer();
}
</script>
</body>
</html>