@mothepro/fancy-p2p
Version:
A quick and efficient way to form p2p groups in the browser
118 lines (117 loc) • 4.91 kB
JavaScript
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
const lit_element_1 = require("lit-element");
let default_1 = class default_1 extends lit_element_1.LitElement {
constructor() {
super(...arguments);
/** Others connected to the lobby. */
this.clients = [];
/** List of incoming proposals */
this.proposals = [];
this.log = (...detail) => this.dispatchEvent(new CustomEvent('log', { detail, bubbles: true, composed: true }))
&& this.requestUpdate();
/** Chilling in the lobby. */
this.render = () => lit_element_1.html `${this.clients.length
? lit_element_1.html `
Clients connected to this lobby
<form
=${(event) => // Propose group of all the ack'd clients
this.dispatchEvent(new CustomEvent('proposeGroup', {
detail: this.clients
.filter(({ ack }) => ack)
.map(({ client }) => client)
})) && event.preventDefault()}}
>
<ul id="others">
${[...this.clients].map(({ client: { name, isYou }, ack }, index) => lit_element_1.html `
<li>
<label>
<input
type="checkbox"
?checked=${ack}
?disabled=${isYou}
=${() => this.clients = this.clients.map(({ client, ack: currentAck }, i) => ({
client,
ack: index == i ? !currentAck : currentAck,
}))}
/>
${name}
</label>
</li>`)}
</ul>
<input
type="submit"
value="Propose Group"
?disabled=${!this.clients.some(({ ack }) => ack)}
/>
</form>
${this.proposals.map(({ groupName, action }, index) => lit_element_1.html `
Join group with ${groupName}?
<button
=${() => {
this.proposals = this.proposals.filter((_, i) => index != i);
action(true);
}}>Accept</button>
<button
=${() => {
this.proposals = this.proposals.filter((_, i) => index != i);
action(false);
}}>Reject</button>
<br/>`)}`
: 'No one else has joined this lobby... yet.'}`;
}
async firstUpdated() {
for await (const client of this.connection) {
this.clients = [...this.clients, { client, ack: false }];
this.log(`${client.name} has joined the lobby`);
this.bindProposals(client);
}
}
async bindProposals(client) {
for await (const { members, ack, action } of client.proposals) {
const names = members.map(({ name }) => name).join(', ');
this.log(`${client.isYou ? 'You' : client.name} proposed a group for ${names} & you`);
this.bindAck(names, ack, action);
}
this.clients = this.clients.filter(({ client: currentClient }) => currentClient != client);
this.log(`${client.name} has left the lobby`);
}
async bindAck(groupName, ack, action) {
const current = this.proposals.length; // the index of the proposal we may add
if (action) // proposal that we can accept or reject
this.proposals = [...this.proposals, { groupName, action }];
try {
for await (const { name } of ack)
this.log(`${name} accepted invitation with ${groupName} & you`);
}
catch (err) {
this.log(err.client
? `${err.client.name} rejected invitation to group with ${groupName} & you`
: `Group with ${groupName} & you was shut down`, err);
}
finally { // Remove the proposal once it is completed.
if (action)
this.proposals = this.proposals.filter((_, i) => current != i);
}
}
};
__decorate([
lit_element_1.property({ attribute: false })
], default_1.prototype, "connection", void 0);
__decorate([
lit_element_1.internalProperty()
], default_1.prototype, "clients", void 0);
__decorate([
lit_element_1.internalProperty()
], default_1.prototype, "proposals", void 0);
default_1 = __decorate([
lit_element_1.customElement('lit-lobby')
], default_1);
exports.default = default_1;
//# sourceMappingURL=lobby.js.map