diff options
Diffstat (limited to 'client-web/source')
-rw-r--r-- | client-web/source/resource/file.ts | 69 | ||||
-rw-r--r-- | client-web/source/resource/mod.ts | 2 | ||||
-rw-r--r-- | client-web/source/user/remote.ts | 13 |
3 files changed, 67 insertions, 17 deletions
diff --git a/client-web/source/resource/file.ts b/client-web/source/resource/file.ts index b6629bc..c54abc8 100644 --- a/client-web/source/resource/file.ts +++ b/client-web/source/resource/file.ts @@ -1,18 +1,31 @@ -import { ediv } from "../helper.ts"; +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) { + new_remote(info, user, enable) { return { info, - el: ediv(), - on_statechange(_s) { }, - on_enable(_track, _disable) { - return { - on_disable() { - + 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`); } } } @@ -28,12 +41,40 @@ export function create_file_res(): Promise<LocalResource> { if (!picker.files) return reject() const f = picker.files.item(0) if (!f) return reject() - resolve({ - info: { kind: "file", id: Math.random().toString(), label: f.name, size: f.size }, - destroy() { /* TODO */ }, - el: ediv(), - on_request(_user, _create_channel) { return _create_channel("TODO") } - }) + 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 + } + } }
\ No newline at end of file diff --git a/client-web/source/resource/mod.ts b/client-web/source/resource/mod.ts index f99a252..a213d87 100644 --- a/client-web/source/resource/mod.ts +++ b/client-web/source/resource/mod.ts @@ -101,7 +101,7 @@ export interface LocalResource { el: HTMLElement info: ProvideInfo, destroy(): void - on_request(user: RemoteUser, create_channel: (label: string) => RTCDataChannel): TrackHandle | RTCDataChannel + on_request(user: RemoteUser, create_channel: () => RTCDataChannel): TrackHandle | RTCDataChannel } const RESOURCE_HANDLERS: ResourceHandlerDecl[] = [resource_file, resource_track] diff --git a/client-web/source/user/remote.ts b/client-web/source/user/remote.ts index 677d362..e143625 100644 --- a/client-web/source/user/remote.ts +++ b/client-web/source/user/remote.ts @@ -45,10 +45,19 @@ export class RemoteUser extends User { r.on_enable(new TrackHandle(t), () => { this.request_resource_stop(r) }) - // else { ev.transceiver.stop(); return log({ scope: "media", warn: true }, "got a track for a resource that should use data channel") } log("media", `remote track: ${this.display_name}`, t) this.update_stats() } + this.pc.ondatachannel = ({ channel }) => { + const id = channel.label + const r = this.resources.get(id) + if (!r) { channel.close(); return log({ scope: "media", warn: true }, "got an unassociated channel") } + r.on_enable(channel, () => { + this.request_resource_stop(r) + }) + log("media", `remote channel: ${this.display_name}`, channel) + this.update_stats() + } this.pc.onnegotiationneeded = () => { log("webrtc", `negotiation needed: ${this.display_name}`) if (this.negotiation_busy && this.pc.signalingState == "stable") return @@ -97,7 +106,7 @@ export class RemoteUser extends User { if (message.request) { const r = this.room.local_user.resources.get(message.request.id) if (!r) return log({ scope: "*", warn: true }, "somebody requested an unknown resource") - const channel = r.on_request(this, label => this.pc.createDataChannel(label)) + const channel = r.on_request(this, () => this.pc.createDataChannel(r.info.id)) if (channel instanceof TrackHandle) { const sender = this.pc.addTrack(channel.track, channel.stream) this.senders.set(channel.id, sender) |