diff --git a/examples/chat/components/peers.js b/examples/chat/components/peers.js index 651ac7c..2ce7e35 100644 --- a/examples/chat/components/peers.js +++ b/examples/chat/components/peers.js @@ -8,32 +8,40 @@ export default class ChatPeers extends HTMLElement { } connectedCallback() { - this.shadow = this.attachShadow({mode: "open"}); - this.shadow.innerHTML = ` - -
- `; - this.peers = this.shadow.getElementById('peers'); this.cleanup = [ watch([peers, announcements], () => this.updatePeers()), watch([selected_announcement], () => this.updateSelected()), - delegate(this.peers, "click", "#peers li", function () { + delegate(this, "click", "li", function () { selected_announcement.value = JSON.parse(this.dataset.announcement); }), + delegate(this, "click", "button", ev => { + ev.preventDefault(); + this.dial(); + }), ]; this.updatePeers(); } + async dial() { + const address = prompt("Dial address (e.g. /ip4/127.0.0.1/tcp/33985):"); + if (address) { + await fetch("/_api/v1/dial", { + method: 'POST', + body: JSON.stringify({address}), + }); + } + } + disconnectedCallback() { for (const destroy of this.cleanup) destroy(); } updatePeers() { - this.peers.innerHTML = ''; + this.innerHTML = ''; if (announcements.value.length === 0) { const span = document.createElement('span'); span.textContent = "No peers discovered yet"; - this.peers.appendChild(span); + this.appendChild(span); } else { const ul = document.createElement('ul'); for (const announcement of announcements.value) { @@ -45,14 +53,17 @@ export default class ChatPeers extends HTMLElement { ul.appendChild(li); } } - this.peers.appendChild(ul); + this.appendChild(ul); } + const btn = document.createElement('button'); + btn.textContent = 'Add peer'; + this.appendChild(btn); this.updateSelected(); } updateSelected() { const json = JSON.stringify(selected_announcement.value); - for (const li of this.peers.querySelectorAll("li")) { + for (const li of this.querySelectorAll("li")) { if (li.dataset.announcement === json) { li.classList.add("active"); } else { diff --git a/examples/chat/main.js b/examples/chat/main.js index c182a16..a7ab7b1 100644 --- a/examples/chat/main.js +++ b/examples/chat/main.js @@ -1,7 +1,7 @@ // @ts-check import * as state from "./state.js"; import {watch} from "./lib/signaller.js"; -import {askNick} from "../nick.js"; +import {askNick} from "./nick.js"; // Custom elements import "./components/header.js"; diff --git a/examples/chat/style.css b/examples/chat/style.css index d2e946a..445c12e 100644 --- a/examples/chat/style.css +++ b/examples/chat/style.css @@ -41,13 +41,13 @@ chat-peers { min-width: 200px; } -#peers ul { +chat-peers ul { list-style: none; margin: 0; padding: 0; } -#peers li { +chat-peers li { overflow: hidden; text-overflow: ellipsis; margin: 0; @@ -56,7 +56,7 @@ chat-peers { white-space: nowrap; } -#peers .active { +chat-peers .active { background: #ccf; } @@ -94,7 +94,7 @@ chat-message-history { flex-shrink: 0; } -#peers li::before { +chat-peers li::before { content: '👤 '; } diff --git a/mutiny/src/server.ts b/mutiny/src/server.ts index 1e1fb6d..7525e48 100644 --- a/mutiny/src/server.ts +++ b/mutiny/src/server.ts @@ -31,6 +31,10 @@ export class Server { return eventStream(this.client.peerEvents(), event => { return [event.type, event.peer_id]; }); + } else if (request.method === 'POST' && pathname === '/_api/v1/dial') { + const body = await request.json(); + await this.client.dialAddress(body.address); + return new Response(JSON.stringify({success: true})); } else if (request.method === 'POST' && pathname === '/_api/v1/announcements/outbox') { const body = await request.json(); await this.client.announce(