2022-09-06 19:26:43 -04:00
|
|
|
import {LitElement, html, unsafeHTML} from './lit-all.min.js';
|
|
|
|
import * as tfrpc from '/static/tfrpc.js';
|
|
|
|
import * as tfutils from './tf-utils.js';
|
|
|
|
import {styles} from './tf-styles.js';
|
|
|
|
|
|
|
|
class TfProfileElement extends LitElement {
|
|
|
|
static get properties() {
|
|
|
|
return {
|
2022-09-09 22:56:15 -04:00
|
|
|
editing: {type: Object},
|
|
|
|
whoami: {type: String},
|
2022-09-06 19:26:43 -04:00
|
|
|
id: {type: String},
|
|
|
|
users: {type: Object},
|
2022-09-09 22:56:15 -04:00
|
|
|
size: {type: Number},
|
2023-10-20 10:37:24 -04:00
|
|
|
server_follows_me: {type: Boolean},
|
2023-11-02 20:45:30 -04:00
|
|
|
following: {type: Boolean},
|
|
|
|
blocking: {type: Boolean},
|
2023-03-29 18:02:12 -04:00
|
|
|
};
|
2022-09-06 19:26:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static styles = styles;
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
let self = this;
|
2022-09-09 22:56:15 -04:00
|
|
|
this.editing = null;
|
|
|
|
this.whoami = null;
|
2022-09-06 19:26:43 -04:00
|
|
|
this.id = null;
|
|
|
|
this.users = {};
|
2022-09-09 22:56:15 -04:00
|
|
|
this.size = 0;
|
2023-10-20 10:37:24 -04:00
|
|
|
this.server_follows_me = undefined;
|
|
|
|
}
|
|
|
|
|
2023-11-02 20:45:30 -04:00
|
|
|
async load() {
|
|
|
|
if (this.whoami !== this._follow_whoami) {
|
|
|
|
this._follow_whoami = this.whoami;
|
|
|
|
this.following = undefined;
|
|
|
|
this.blocking = undefined;
|
|
|
|
|
2024-02-23 04:35:39 -05:00
|
|
|
let result = await tfrpc.rpc.query(`
|
2023-11-02 20:45:30 -04:00
|
|
|
SELECT json_extract(content, '$.following') AS following
|
|
|
|
FROM messages WHERE author = ? AND
|
|
|
|
json_extract(content, '$.type') = 'contact' AND
|
2023-11-02 20:49:17 -04:00
|
|
|
json_extract(content, '$.contact') = ? AND
|
|
|
|
following IS NOT NULL
|
2023-11-02 20:45:30 -04:00
|
|
|
ORDER BY sequence DESC LIMIT 1
|
2024-02-23 04:35:39 -05:00
|
|
|
`, [this.whoami, this.id]);
|
2023-11-02 20:45:30 -04:00
|
|
|
this.following = result?.[0]?.following ?? false;
|
2024-02-23 04:35:39 -05:00
|
|
|
result = await tfrpc.rpc.query(`
|
2023-11-02 20:49:17 -04:00
|
|
|
SELECT json_extract(content, '$.blocking') AS blocking
|
|
|
|
FROM messages WHERE author = ? AND
|
|
|
|
json_extract(content, '$.type') = 'contact' AND
|
|
|
|
json_extract(content, '$.contact') = ? AND
|
|
|
|
blocking IS NOT NULL
|
|
|
|
ORDER BY sequence DESC LIMIT 1
|
2024-02-23 04:35:39 -05:00
|
|
|
`, [this.whoami, this.id]);
|
2023-11-02 20:49:17 -04:00
|
|
|
this.blocking = result?.[0]?.blocking ?? false;
|
2023-11-02 20:45:30 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-20 10:37:24 -04:00
|
|
|
async initial_load() {
|
|
|
|
this.server_follows_me = undefined;
|
|
|
|
let server_id = await tfrpc.rpc.getServerIdentity();
|
2024-02-23 04:35:39 -05:00
|
|
|
let followed = await tfrpc.rpc.query(`
|
2023-11-02 20:45:30 -04:00
|
|
|
SELECT json_extract(content, '$.following') AS following
|
|
|
|
FROM messages
|
2023-10-20 10:37:24 -04:00
|
|
|
WHERE author = ? AND
|
|
|
|
json_extract(content, '$.type') = 'contact' AND
|
|
|
|
json_extract(content, '$.contact') = ? ORDER BY sequence DESC LIMIT 1
|
2024-02-23 04:35:39 -05:00
|
|
|
`, [server_id, this.whoami]);
|
2023-10-20 10:37:24 -04:00
|
|
|
let is_followed = false;
|
|
|
|
for (let row of followed) {
|
|
|
|
is_followed = row.following != 0;
|
|
|
|
}
|
|
|
|
this.server_follows_me = is_followed;
|
2022-09-06 19:26:43 -04:00
|
|
|
}
|
|
|
|
|
2022-09-09 22:56:15 -04:00
|
|
|
modify(change) {
|
2024-02-23 04:35:39 -05:00
|
|
|
tfrpc.rpc.appendMessage(this.whoami,
|
|
|
|
Object.assign({
|
|
|
|
type: 'contact',
|
|
|
|
contact: this.id,
|
|
|
|
}, change)).catch(function(error) {
|
2022-09-09 22:56:15 -04:00
|
|
|
alert(error?.message);
|
2023-03-29 18:02:12 -04:00
|
|
|
});
|
2022-09-09 22:56:15 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
follow() {
|
|
|
|
this.modify({following: true});
|
|
|
|
}
|
|
|
|
|
|
|
|
unfollow() {
|
|
|
|
this.modify({following: false});
|
|
|
|
}
|
|
|
|
|
|
|
|
block() {
|
|
|
|
this.modify({blocking: true});
|
|
|
|
}
|
|
|
|
|
|
|
|
unblock() {
|
|
|
|
this.modify({blocking: false});
|
|
|
|
}
|
|
|
|
|
|
|
|
edit() {
|
|
|
|
let original = this.users[this.id];
|
|
|
|
this.editing = {
|
|
|
|
name: original.name,
|
|
|
|
description: original.description,
|
|
|
|
image: original.image,
|
2023-12-09 14:26:33 -05:00
|
|
|
publicWebHosting: original.publicWebHosting,
|
2022-09-09 22:56:15 -04:00
|
|
|
};
|
|
|
|
console.log(this.editing);
|
|
|
|
}
|
|
|
|
|
|
|
|
save_edits() {
|
|
|
|
let self = this;
|
|
|
|
let message = {
|
|
|
|
type: 'about',
|
|
|
|
about: this.whoami,
|
|
|
|
};
|
|
|
|
for (let key of Object.keys(this.editing)) {
|
|
|
|
if (this.editing[key] !== this.users[this.id][key]) {
|
|
|
|
message[key] = this.editing[key];
|
|
|
|
}
|
|
|
|
}
|
2024-02-23 04:35:39 -05:00
|
|
|
tfrpc.rpc.appendMessage(this.whoami, message).then(function() {
|
|
|
|
self.editing = null;
|
|
|
|
}).catch(function(error) {
|
|
|
|
alert(error?.message);
|
|
|
|
});
|
2022-09-09 22:56:15 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
discard_edits() {
|
|
|
|
this.editing = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
attach_image() {
|
|
|
|
let self = this;
|
|
|
|
let input = document.createElement('input');
|
|
|
|
input.type = 'file';
|
2024-02-23 04:35:39 -05:00
|
|
|
input.onchange = function(event) {
|
2022-09-09 22:56:15 -04:00
|
|
|
let file = event.target.files[0];
|
2024-02-23 04:35:39 -05:00
|
|
|
file.arrayBuffer().then(function(buffer) {
|
|
|
|
let bin = Array.from(new Uint8Array(buffer));
|
|
|
|
return tfrpc.rpc.store_blob(bin);
|
|
|
|
}).then(function(id) {
|
|
|
|
self.editing = Object.assign({}, self.editing, {image: id});
|
|
|
|
console.log(self.editing);
|
|
|
|
}).catch(function(e) {
|
|
|
|
alert(e.message);
|
|
|
|
});
|
2022-09-09 22:56:15 -04:00
|
|
|
};
|
|
|
|
input.click();
|
2022-09-06 19:26:43 -04:00
|
|
|
}
|
|
|
|
|
2023-10-20 10:37:24 -04:00
|
|
|
async server_follow_me(follow) {
|
|
|
|
try {
|
|
|
|
await tfrpc.rpc.setServerFollowingMe(this.whoami, follow);
|
|
|
|
} catch (e) {
|
|
|
|
console.log(e);
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
await this.initial_load();
|
|
|
|
} catch (e) {
|
|
|
|
console.log(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-06 19:26:43 -04:00
|
|
|
render() {
|
2024-02-23 04:35:39 -05:00
|
|
|
if (this.id == this.whoami && this.editing && this.server_follows_me === undefined) {
|
2023-10-20 10:37:24 -04:00
|
|
|
this.initial_load();
|
|
|
|
}
|
2023-11-02 20:45:30 -04:00
|
|
|
this.load();
|
2022-09-09 22:56:15 -04:00
|
|
|
let self = this;
|
2022-09-06 19:26:43 -04:00
|
|
|
let profile = this.users[this.id] || {};
|
2024-02-23 04:35:39 -05:00
|
|
|
tfrpc.rpc.query(
|
|
|
|
`SELECT SUM(LENGTH(content)) AS size FROM messages WHERE author = ?`,
|
|
|
|
[this.id]).then(function(result) {
|
2022-09-09 22:56:15 -04:00
|
|
|
self.size = result[0].size;
|
|
|
|
});
|
|
|
|
let edit;
|
|
|
|
let follow;
|
|
|
|
let block;
|
|
|
|
if (this.id === this.whoami) {
|
|
|
|
if (this.editing) {
|
2023-10-20 10:37:24 -04:00
|
|
|
let server_follow;
|
|
|
|
if (this.server_follows_me === true) {
|
2024-02-23 04:35:39 -05:00
|
|
|
server_follow = html`<button class="w3-button w3-dark-grey" @click=${() => this.server_follow_me(false)}>Server, Stop Following Me</button>`;
|
2023-10-20 10:37:24 -04:00
|
|
|
} else if (this.server_follows_me === false) {
|
2024-02-23 04:35:39 -05:00
|
|
|
server_follow = html`<button class="w3-button w3-dark-grey" @click=${() => this.server_follow_me(true)}>Server, Follow Me</button>`;
|
2023-10-20 10:37:24 -04:00
|
|
|
}
|
2022-09-09 22:56:15 -04:00
|
|
|
edit = html`
|
2024-02-23 04:35:39 -05:00
|
|
|
<button class="w3-button w3-dark-grey" @click=${this.save_edits}>Save Profile</button>
|
|
|
|
<button class="w3-button w3-dark-grey" @click=${this.discard_edits}>Discard</button>
|
2023-10-20 10:37:24 -04:00
|
|
|
${server_follow}
|
2022-09-09 22:56:15 -04:00
|
|
|
`;
|
|
|
|
} else {
|
2024-02-23 04:35:39 -05:00
|
|
|
edit = html`<button class="w3-button w3-dark-grey" @click=${this.edit}>Edit Profile</button>`;
|
2022-09-09 22:56:15 -04:00
|
|
|
}
|
|
|
|
}
|
2024-02-23 04:35:39 -05:00
|
|
|
if (this.id !== this.whoami &&
|
|
|
|
this.following !== undefined) {
|
|
|
|
follow =
|
|
|
|
this.following ?
|
|
|
|
html`<button class="w3-button w3-dark-grey" @click=${this.unfollow}>Unfollow</button>` :
|
|
|
|
html`<button class="w3-button w3-dark-grey" @click=${this.follow}>Follow</button>`;
|
2022-09-09 22:56:15 -04:00
|
|
|
}
|
2024-02-23 04:35:39 -05:00
|
|
|
if (this.id !== this.whoami &&
|
|
|
|
this.blocking !== undefined) {
|
|
|
|
block =
|
|
|
|
this.blocking ?
|
|
|
|
html`<button class="w3-button w3-dark-grey" @click=${this.unblock}>Unblock</button>` :
|
|
|
|
html`<button class="w3-button w3-dark-grey" @click=${this.block}>Block</button>`;
|
2022-09-09 22:56:15 -04:00
|
|
|
}
|
2024-02-23 04:35:39 -05:00
|
|
|
let edit_profile = this.editing ? html`
|
2024-01-12 21:55:52 -05:00
|
|
|
<div style="flex: 1 0 50%; display: flex; flex-direction: column; gap: 8px">
|
|
|
|
<div class="w3-container">
|
|
|
|
<div>
|
|
|
|
<label for="name">Name:</label>
|
2024-02-23 04:35:39 -05:00
|
|
|
<input class="w3-input w3-dark-grey" type="text" id="name" value=${this.editing.name} @input=${event => this.editing = Object.assign({}, this.editing, {name: event.srcElement.value})}></input>
|
2024-01-12 21:55:52 -05:00
|
|
|
</div>
|
|
|
|
<div><label for="description">Description:</label></div>
|
2024-02-23 04:35:39 -05:00
|
|
|
<textarea class="w3-input w3-dark-grey" style="resize: vertical" rows="8" id="description" @input=${event => this.editing = Object.assign({}, this.editing, {description: event.srcElement.value})}>${this.editing.description}</textarea>
|
2024-01-12 21:55:52 -05:00
|
|
|
<div>
|
|
|
|
<label for="public_web_hosting">Public Web Hosting:</label>
|
2024-02-23 04:35:39 -05:00
|
|
|
<input class="w3-check w3-dark-grey" type="checkbox" id="public_web_hosting" ?checked=${this.editing.publicWebHosting} @input=${event => self.editing = Object.assign({}, self.editing, {publicWebHosting: event.srcElement.checked})}></input>
|
2024-01-12 21:55:52 -05:00
|
|
|
</div>
|
|
|
|
<div>
|
|
|
|
<button class="w3-button w3-dark-grey" @click=${this.attach_image}>Attach Image</button>
|
|
|
|
</div>
|
2023-10-21 17:31:46 -04:00
|
|
|
</div>
|
2024-02-23 04:35:39 -05:00
|
|
|
</div>` : null;
|
|
|
|
let image = typeof(profile.image) == 'string' ? profile.image : profile.image?.link;
|
2022-09-09 22:56:15 -04:00
|
|
|
image = this.editing?.image ?? image;
|
|
|
|
let description = this.editing?.description ?? profile.description;
|
2022-09-06 19:26:43 -04:00
|
|
|
return html`<div style="border: 2px solid black; background-color: rgba(255, 255, 255, 0.2); padding: 16px">
|
2022-09-09 22:56:15 -04:00
|
|
|
<tf-user id=${this.id} .users=${this.users}></tf-user> (${tfutils.human_readable_size(this.size)})
|
2023-10-21 17:31:46 -04:00
|
|
|
<div style="display: flex; flex-direction: row; gap: 1em">
|
2022-09-09 22:56:15 -04:00
|
|
|
${edit_profile}
|
|
|
|
<div style="flex: 1 0 50%">
|
|
|
|
<div><img src=${'/' + image + '/view'} style="width: 256px; height: auto"></img></div>
|
|
|
|
<div>${unsafeHTML(tfutils.markdown(description))}</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div>
|
2023-11-02 20:45:30 -04:00
|
|
|
Following ${profile.following} identities.
|
|
|
|
Followed by ${profile.followed} identities.
|
|
|
|
Blocking ${profile.blocking} identities.
|
|
|
|
Blocked by ${profile.blocked} identities.
|
2022-09-09 22:56:15 -04:00
|
|
|
</div>
|
|
|
|
<div>
|
|
|
|
${edit}
|
|
|
|
${follow}
|
|
|
|
${block}
|
|
|
|
</div>
|
2022-09-06 19:26:43 -04:00
|
|
|
</div>`;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-23 04:35:39 -05:00
|
|
|
customElements.define('tf-profile', TfProfileElement);
|