Files
.gitea
apps
admin
api
apps
blog
db
follow
identity
intro
issues
journal
room
sneaker
ssb
app.js
commonmark-hashtag.js
commonmark.min.js
emojis.js
emojis.json
filesaver.min.js
filesaver.min.js.map
index.html
lit-all.min.js
lit-all.min.js.map
script.js
tf-app.js
tf-compose.js
tf-message.js
tf-news.js
tf-profile.js
tf-reactions-modal.js
tf-styles.js
tf-tab-connections.js
tf-tab-news-feed.js
tf-tab-news.js
tf-tab-query.js
tf-tab-search.js
tf-tag.js
tf-user.js
tf-utils.js
tribute.css
tribute.esm.js
storage
test
todo
web
welcome
wiki
admin.json
api.json
apps.json
blog.json
db.json
follow.json
identity.json
intro.json
issues.json
journal.json
room.json
sneaker.json
ssb.json
storage.json
test.json
todo.json
web.json
welcome.json
wiki.json
core
deps
docs
metadata
src
tools
.clang-format
.dockerignore
.git-blame-ignore-revs
.gitignore
.gitmodules
.prettierignore
.prettierrc.yaml
CONTRIBUTING.md
Dockerfile
Doxyfile
GNUmakefile
LICENSE
README.md
default.nix
flake.lock
flake.nix
package-lock.json
package.json
tildefriends/apps/ssb/tf-tab-connections.js

357 lines
9.5 KiB
JavaScript
Raw Normal View History

import {LitElement, html} from './lit-all.min.js';
import * as tfrpc from '/static/tfrpc.js';
import {styles} from './tf-styles.js';
class TfTabConnectionsElement extends LitElement {
static get properties() {
return {
broadcasts: {type: Array},
identities: {type: Array},
my_identities: {type: Array},
connections: {type: Array},
stored_connections: {type: Array},
users: {type: Object},
2024-05-11 09:33:38 -04:00
server_identity: {type: String},
connect_attempt: {type: Object},
connect_message: {type: String},
connect_success: {type: Boolean},
};
}
static styles = styles;
static k_broadcast_emojis = {
discovery: '🏓',
room: '🚪',
peer_exchange: '🕸',
};
constructor() {
super();
let self = this;
this.broadcasts = [];
this.identities = [];
this.my_identities = [];
this.connections = [];
this.stored_connections = [];
this.users = {};
tfrpc.rpc.getIdentities().then(function (identities) {
self.my_identities = identities || [];
});
2024-02-24 11:09:34 -05:00
tfrpc.rpc.getAllIdentities().then(function (identities) {
self.identities = identities || [];
});
2024-02-24 11:09:34 -05:00
tfrpc.rpc.getStoredConnections().then(function (connections) {
self.stored_connections = connections || [];
});
2024-05-11 09:33:38 -04:00
tfrpc.rpc.getServerIdentity().then(function (identity) {
self.server_identity = identity;
});
}
render_connection_summary(connection) {
if (connection.address && connection.port) {
2024-04-13 20:07:39 -04:00
return html`<div>
<small>${connection.address}:${connection.port}</small>
</div>`;
} else if (connection.tunnel) {
return html`<div>room peer</div>`;
} else {
return JSON.stringify(connection);
}
}
render_room_peers(connection) {
let self = this;
2024-02-24 11:09:34 -05:00
let peers = this.broadcasts.filter((x) => x.tunnel?.id == connection);
if (peers.length) {
2024-02-24 11:09:34 -05:00
let connections = this.connections.map((x) => x.id);
return html`${peers
.filter((x) => connections.indexOf(x.pubkey) == -1)
.map((x) => html`${self.render_room_peer(x)}`)}`;
}
}
async _tunnel(portal, target) {
return tfrpc.rpc.createTunnel(portal, target);
}
render_room_peer(connection) {
let self = this;
return html`
<li>
2024-02-24 11:09:34 -05:00
<button
2024-04-04 20:35:09 -04:00
class="w3-button w3-theme-d1"
2024-02-24 11:09:34 -05:00
@click=${() => self._tunnel(connection.tunnel.id, connection.pubkey)}
>
Connect
</button>
<tf-user id=${connection.pubkey} .users=${this.users}></tf-user> 📡
</li>
`;
}
render_message(connection) {
return html`<div
?hidden=${this.connect_message === undefined ||
this.connect_attempt != connection}
style="cursor: pointer"
class=${'w3-panel ' + (this.connect_success ? 'w3-green' : 'w3-red')}
2024-11-13 18:58:09 -05:00
@click=${() => (this.connect_attempt = undefined)}
>
<p>${this.connect_message}</p>
</div>`;
}
render_progress(name, value, max) {
if (max && value != max) {
return html`
<div class="w3-theme-d1 w3-small">
<div
class="w3-container w3-theme-l1"
style="width: ${Math.floor(
(100.0 * value) / max
)}%; text-wrap: nowrap"
>
${name} ${value} / ${max} (${Math.round((100.0 * value) / max)}%)
</div>
</div>
`;
}
}
render_broadcast(connection) {
let self = this;
return html`
<li>
<div class="w3-bar" style="overflow: hidden; overflow-wrap: nowrap">
<button
class="w3-bar-item w3-button w3-theme-d1"
@click=${() => self.connect(connection)}
>
Connect
</button>
<div class="w3-bar-item">
${TfTabConnectionsElement.k_broadcast_emojis[connection.origin]}
<tf-user id=${connection.pubkey} .users=${this.users}></tf-user>
${this.render_connection_summary(connection)}
</div>
</div>
${this.render_message(connection)}
</li>
`;
}
async forget_stored_connection(connection) {
await tfrpc.rpc.forgetStoredConnection(connection);
this.stored_connections = (await tfrpc.rpc.getStoredConnections()) || [];
}
render_connection(connection) {
2024-05-12 08:23:34 -04:00
let requests = Object.values(
connection.requests.reduce(function (accumulator, value) {
let key = `${value.name}:${Math.sign(value.request_number)}`;
if (!accumulator[key]) {
accumulator[key] = Object.assign({count: 0}, value);
}
accumulator[key].count++;
return accumulator;
}, {})
);
return html`
${connection.connected
? html`
<button
class="w3-button w3-theme-d1"
@click=${() => tfrpc.rpc.closeConnection(connection.id)}
>
Close
</button>
`
: undefined}
${connection.flags.one_shot ? '🔃' : undefined}
<tf-user id=${connection.id} .users=${this.users}></tf-user>
${this.render_progress(
'recv',
connection.progress.in.total - connection.progress.in.current,
connection.progress.in.total
)}
${this.render_progress(
'send',
connection.progress.out.total - connection.progress.out.current,
connection.progress.out.total
)}
2024-02-24 11:09:34 -05:00
${connection.tunnel !== undefined
? '🚇'
: html`(${connection.host}:${connection.port})`}
2024-05-12 08:23:34 -04:00
<div>
${requests.map(
(x) => html`
<span
class=${'w3-tag w3-small ' +
(x.active ? 'w3-theme-l3' : 'w3-theme-d3')}
2024-05-12 08:23:34 -04:00
>${x.request_number > 0 ? '🟩' : '🟥'} ${x.name}
<span
class="w3-badge w3-white"
style=${x.count > 1 ? undefined : 'display: none'}
>${x.count}</span
></span
>
`
)}
</div>
<ul>
2024-02-24 11:09:34 -05:00
${this.connections
.filter((x) => x.tunnel === this.connections.indexOf(connection))
.map((x) => html`<li>${this.render_connection(x)}</li>`)}
${this.render_room_peers(connection.id)}
</ul>
<div ?hidden=${!connection.destroy_reason} class="w3-panel w3-red">
<p>${connection.destroy_reason}</p>
</div>
`;
}
connect(address) {
let self = this;
self.connect_attempt = address;
self.connect_message = undefined;
self.connect_success = false;
tfrpc.rpc
.connect(address)
.then(function () {
if (self.connect_attempt == address) {
self.connect_message = 'Connected.';
self.connect_success = true;
}
})
.catch(function (error) {
if (self.connect_attempt == address) {
self.connect_message = 'Error: ' + error;
self.connect_success = false;
}
});
}
toggle_accordian(id) {
let element = this.renderRoot.getElementById(id);
element.classList.toggle('w3-hide');
}
valid_connections() {
return this.connections.filter((x) => x.tunnel === undefined);
}
valid_broadcasts() {
return this.broadcasts
.filter((x) => x.address)
2025-02-27 20:17:24 -05:00
.filter((x) => this.connections.map((c) => c.id).indexOf(x.pubkey) == -1);
}
render() {
let self = this;
return html`
<div class="w3-container" style="box-sizing: border-box">
<h2>New Connection</h2>
2024-04-04 20:35:09 -04:00
<textarea class="w3-input w3-theme-d1" id="code"></textarea>
${this.render_message(this.renderRoot.getElementById('code')?.value)}
2024-02-24 11:09:34 -05:00
<button
2024-04-04 20:35:09 -04:00
class="w3-button w3-theme-d1"
2024-02-24 11:09:34 -05:00
@click=${() =>
self.connect(self.renderRoot.getElementById('code')?.value)}
2024-02-24 11:09:34 -05:00
>
Connect
</button>
2025-02-27 20:17:24 -05:00
<h2
class="w3-button w3-block w3-theme-d1"
@click=${() => self.toggle_accordian('connections')}
>
Connections (${this.valid_connections().length})
</h2>
<ul class="w3-ul w3-border" id="connections">
2025-02-27 20:17:24 -05:00
${this.valid_connections().map(
(x) => html` <li class="w3-bar">${this.render_connection(x)}</li> `
)}
</ul>
2025-02-27 20:17:24 -05:00
<h2
class="w3-button w3-block w3-theme-d1"
@click=${() => self.toggle_accordian('broadcasts')}
>
Discovery (${this.valid_broadcasts().length})
2025-02-27 20:17:24 -05:00
</h2>
<ul class="w3-ul w3-border w3-hide" id="broadcasts">
${this.valid_broadcasts().map((x) => self.render_broadcast(x))}
</ul>
2025-02-27 20:17:24 -05:00
<h2
class="w3-button w3-block w3-theme-d1"
@click=${() => self.toggle_accordian('stored_connections')}
>
Stored Connections (${this.stored_connections.length})
</h2>
<ul class="w3-ul w3-border w3-hide" id="stored_connections">
2024-02-24 11:09:34 -05:00
${this.stored_connections.map(
(x) => html`
<li>
<div class="w3-bar">
<button
class="w3-bar-item w3-button w3-theme-d1"
@click=${() => self.forget_stored_connection(x)}
>
Forget
</button>
<button
class="w3-bar-item w3-button w3-theme-d1"
@click=${() => this.connect(x)}
>
Connect
</button>
<div class="w3-bar-item">
<tf-user id=${x.pubkey} .users=${self.users}></tf-user>
<div><small>${x.address}:${x.port}</small></div>
<div>
<small
>Last connection:
${new Date(x.last_success * 1000)}</small
>
</div>
</div>
</div>
${this.render_message(x)}
2024-02-24 11:09:34 -05:00
</li>
`
)}
</ul>
2025-02-27 20:17:24 -05:00
<h2
class="w3-button w3-block w3-theme-d1"
@click=${() => self.toggle_accordian('local_accounts')}
>
Local Accounts (${this.identities.length})
</h2>
<div class="w3-container w3-hide" id="local_accounts">
2024-02-24 11:09:34 -05:00
${this.identities.map(
(x) =>
html`<div
class="w3-tag w3-round w3-theme-l3"
style="padding: 4px; margin: 2px; max-width: 100%; text-wrap: nowrap; overflow: hidden"
>
2024-05-12 07:48:34 -04:00
${x == this.server_identity
? html`<div class="w3-tag w3-medium w3-round w3-theme-l1">
🖥 local server
</div>`
2024-05-12 07:48:34 -04:00
: undefined}
${this.my_identities.indexOf(x) != -1
? html`<div class="w3-tag w3-medium w3-round w3-theme-d1">
😎 you
</div>`
2024-05-12 07:48:34 -04:00
: undefined}
<tf-user id=${x} .users=${this.users}></tf-user>
</div>`
2024-02-24 11:09:34 -05:00
)}
</div>
</div>
`;
}
}
2024-02-24 11:09:34 -05:00
customElements.define('tf-tab-connections', TfTabConnectionsElement);