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
|
import { ebutton, ediv, espan } from "../helper.ts";
import { LocalResource, ResourceHandlerDecl } from "./mod.ts";
export const resource_file: ResourceHandlerDecl = {
kind: "file",
new_remote(info, user, enable) {
return {
info,
el: ediv({},
espan(`File: ${JSON.stringify(info.label)}`),
ebutton("Download", {
onclick: self => {
enable()
self.disabled = true
}
})
),
on_statechange(_s) { },
on_enable(channel, _disable) {
if (!(channel instanceof RTCDataChannel)) throw new Error("not a data channel");
channel.onopen = _ev => {
console.log(`${user.display_name}: channel open`);
}
channel.onerror = _ev => {
console.log(`${user.display_name}: channel error`);
}
channel.onclose = _ev => {
console.log(`${user.display_name}: channel closed`);
}
}
}
}
}
export function create_file_res(): Promise<LocalResource> {
const picker = document.createElement("input")
picker.type = "file"
picker.click()
return new Promise((resolve, reject) => {
picker.addEventListener("change", () => {
if (!picker.files) return reject()
const f = picker.files.item(0)
if (!f) return reject()
resolve(file_res_inner(f))
})
})
}
function file_res_inner(file: File): LocalResource {
const transfers_el = ediv({})
return {
info: { kind: "file", id: Math.random().toString(), label: file.name, size: file.size },
destroy() { },
el: ediv({ class: "file" },
espan(`Sharing file: ${JSON.stringify(file.name)}`),
transfers_el
),
on_request(user, create_channel) {
const channel = create_channel()
const reader = file.stream().getReader()
console.log(`${user.display_name} started requested file`);
channel.onbufferedamountlow = async () => {
const { value: chunk, done } = await reader.read()
console.log(chunk, done);
channel.send(chunk)
if (!done) console.log("transfer done");
}
channel.onopen = _ev => {
console.log(`${user.display_name}: channel open`);
}
channel.onerror = _ev => {
console.log(`${user.display_name}: channel error`);
}
channel.onclose = _ev => {
console.log(`${user.display_name}: channel closed`);
}
return channel
}
}
}
|