2022-09-06 23:26:43 +00: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-10 02:56:15 +00:00
editing : { type : Object } ,
whoami : { type : String } ,
2022-09-06 23:26:43 +00:00
id : { type : String } ,
users : { type : Object } ,
2022-09-10 02:56:15 +00:00
size : { type : Number } ,
2023-11-03 00:45:30 +00:00
following : { type : Boolean } ,
blocking : { type : Boolean } ,
2023-03-29 22:02:12 +00:00
} ;
2022-09-06 23:26:43 +00:00
}
static styles = styles ;
constructor ( ) {
super ( ) ;
let self = this ;
2022-09-10 02:56:15 +00:00
this . editing = null ;
this . whoami = null ;
2022-09-06 23:26:43 +00:00
this . id = null ;
this . users = { } ;
2022-09-10 02:56:15 +00:00
this . size = 0 ;
2023-10-20 14:37:24 +00:00
}
2023-11-03 00:45:30 +00:00
async load ( ) {
if ( this . whoami !== this . _follow _whoami ) {
this . _follow _whoami = this . whoami ;
this . following = undefined ;
this . blocking = undefined ;
2024-02-24 11:09:34 -05:00
let result = await tfrpc . rpc . query (
`
2023-11-03 00:45:30 +00:00
SELECT json _extract ( content , '$.following' ) AS following
FROM messages WHERE author = ? AND
json _extract ( content , '$.type' ) = 'contact' AND
2023-11-03 00:49:17 +00:00
json _extract ( content , '$.contact' ) = ? AND
following IS NOT NULL
2023-11-03 00:45:30 +00:00
ORDER BY sequence DESC LIMIT 1
2024-02-24 11:09:34 -05:00
` ,
[ this . whoami , this . id ]
) ;
2023-11-03 00:45:30 +00:00
this . following = result ? . [ 0 ] ? . following ? ? false ;
2024-02-24 11:09:34 -05:00
result = await tfrpc . rpc . query (
`
2023-11-03 00:49:17 +00: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-24 11:09:34 -05:00
` ,
[ this . whoami , this . id ]
) ;
2023-11-03 00:49:17 +00:00
this . blocking = result ? . [ 0 ] ? . blocking ? ? false ;
2023-11-03 00:45:30 +00:00
}
}
2022-09-10 02:56:15 +00:00
modify ( change ) {
2024-02-24 11:09:34 -05:00
tfrpc . rpc
. appendMessage (
this . whoami ,
Object . assign (
{
type : 'contact' ,
contact : this . id ,
} ,
change
)
)
. catch ( function ( error ) {
2022-09-10 02:56:15 +00:00
alert ( error ? . message ) ;
2023-03-29 22:02:12 +00:00
} ) ;
2022-09-10 02:56:15 +00: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 19:26:33 +00:00
publicWebHosting : original . publicWebHosting ,
2022-09-10 02:56:15 +00: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-24 11:09:34 -05:00
tfrpc . rpc
. appendMessage ( this . whoami , message )
. then ( function ( ) {
self . editing = null ;
} )
. catch ( function ( error ) {
alert ( error ? . message ) ;
} ) ;
2022-09-10 02:56:15 +00:00
}
discard _edits ( ) {
this . editing = null ;
}
attach _image ( ) {
let self = this ;
let input = document . createElement ( 'input' ) ;
input . type = 'file' ;
2024-02-24 11:09:34 -05:00
input . onchange = function ( event ) {
2022-09-10 02:56:15 +00:00
let file = event . target . files [ 0 ] ;
2024-02-24 11:09:34 -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-10 02:56:15 +00:00
} ;
input . click ( ) ;
2022-09-06 23:26:43 +00:00
}
2024-08-11 16:26:24 -04:00
copy _id ( ) {
navigator . clipboard . writeText ( this . id ) ;
}
2022-09-06 23:26:43 +00:00
render ( ) {
2023-11-03 00:45:30 +00:00
this . load ( ) ;
2022-09-10 02:56:15 +00:00
let self = this ;
2022-09-06 23:26:43 +00:00
let profile = this . users [ this . id ] || { } ;
2024-02-24 11:09:34 -05:00
tfrpc . rpc
. query (
` SELECT SUM(LENGTH(content)) AS size FROM messages WHERE author = ? ` ,
[ this . id ]
)
. then ( function ( result ) {
2022-09-10 02:56:15 +00:00
self . size = result [ 0 ] . size ;
} ) ;
let edit ;
let follow ;
let block ;
if ( this . id === this . whoami ) {
if ( this . editing ) {
edit = html `
2024-11-25 20:05:40 -05:00
< button
id = "save_profile"
class = "w3-button w3-theme-d1"
@ click = $ { this . save _edits }
>
2024-02-24 11:09:34 -05:00
Save Profile
< / b u t t o n >
2024-04-04 20:35:09 -04:00
< button class = "w3-button w3-theme-d1" @ click = $ { this . discard _edits } >
2024-02-24 11:09:34 -05:00
Discard
< / b u t t o n >
2022-09-10 02:56:15 +00:00
` ;
} else {
2024-11-25 20:05:40 -05:00
edit = html ` <button
id = "edit_profile"
class = "w3-button w3-theme-d1"
@ click = $ { this . edit }
>
2024-02-24 11:09:34 -05:00
Edit Profile
< / b u t t o n > ` ;
2022-09-10 02:56:15 +00:00
}
}
2024-02-24 11:09:34 -05:00
if ( this . id !== this . whoami && this . following !== undefined ) {
follow = this . following
2024-04-04 20:35:09 -04:00
? html ` <button class="w3-button w3-theme-d1" @click= ${ this . unfollow } >
2024-02-24 11:09:34 -05:00
Unfollow
< / b u t t o n > `
2024-04-04 20:35:09 -04:00
: html ` <button class="w3-button w3-theme-d1" @click= ${ this . follow } >
2024-02-24 11:09:34 -05:00
Follow
< / b u t t o n > ` ;
2022-09-10 02:56:15 +00:00
}
2024-02-24 11:09:34 -05:00
if ( this . id !== this . whoami && this . blocking !== undefined ) {
block = this . blocking
2024-04-04 20:35:09 -04:00
? html ` <button class="w3-button w3-theme-d1" @click= ${ this . unblock } >
2024-02-24 11:09:34 -05:00
Unblock
< / b u t t o n > `
2024-04-04 20:35:09 -04:00
: html ` <button class="w3-button w3-theme-d1" @click= ${ this . block } >
2024-02-24 11:09:34 -05:00
Block
< / b u t t o n > ` ;
2022-09-10 02:56:15 +00:00
}
2024-02-24 11:09:34 -05:00
let edit _profile = this . editing
? html `
2024-01-13 02:55:52 +00:00
< div style = "flex: 1 0 50%; display: flex; flex-direction: column; gap: 8px" >
2025-01-05 15:49:57 -05:00
< div >
< label for = "name" > Name : < / l a b e l >
< input class = "w3-input w3-theme-d1" type = "text" id = "name" value = $ { this . editing . name } @ input = $ { ( event ) => ( this . editing = Object . assign ( { } , this . editing , { name : event . srcElement . value } ) ) } placeholder = "Choose a name" > < / i n p u t >
< / d i v >
< div > < label for = "description" > Description : < / l a b e l > < / d i v >
< textarea class = "w3-input w3-theme-d1" style = "resize: vertical" rows = "8" id = "description" @ input = $ { ( event ) => ( this . editing = Object . assign ( { } , this . editing , { description : event . srcElement . value } ) ) } placeholder = "Tell people a little bit about yourself here, if you like." > $ { this . editing . description } < / t e x t a r e a >
< div >
< label for = "public_web_hosting" > Public Web Hosting : < / l a b e l >
< input class = "w3-check w3-theme-d1" type = "checkbox" id = "public_web_hosting" ? checked = $ { this . editing . publicWebHosting } @ input = $ { ( event ) => ( self . editing = Object . assign ( { } , self . editing , { publicWebHosting : event . srcElement . checked } ) ) } > < / i n p u t >
< / d i v >
< div >
< button class = "w3-button w3-theme-d1" @ click = $ { this . attach _image } > Attach Image < / b u t t o n >
2023-10-21 21:31:46 +00:00
< / d i v >
2024-02-24 11:09:34 -05:00
< / d i v > `
: null ;
let image =
typeof profile . image == 'string' ? profile . image : profile . image ? . link ;
2022-09-10 02:56:15 +00:00
image = this . editing ? . image ? ? image ;
let description = this . editing ? . description ? ? profile . description ;
2024-12-29 15:51:51 -05:00
return html ` <div class="w3-card-4 w3-container w3-theme-d3" style="box-sizing: border-box">
< header class = "w3-container" >
< p > < tf - user id = $ { this . id } . users = $ { this . users } > < / t f - u s e r > ( $ { t f u t i l s . h u m a n _ r e a d a b l e _ s i z e ( t h i s . s i z e ) } ) < / p >
< / h e a d e r >
< div class = "w3-container" >
2025-01-05 15:49:57 -05:00
< div class = "w3-margin-bottom" style = "display: flex; flex-direction: row" >
2025-01-05 15:41:56 -05:00
< input type = "text" class = "w3-input w3-border w3-theme-d1" style = "display: flex 1 1" readonly value = $ { this . id } > < / i n p u t >
< button class = "w3-button w3-theme-d1 w3-ripple" style = "flex: 0 0 auto" @ click = $ { this . copy _id } > Copy < / b u t t o n >
< / d i v >
2024-12-29 15:51:51 -05:00
< div style = "display: flex; flex-direction: row; gap: 1em" >
$ { edit _profile }
< div style = "flex: 1 0 50%" >
< div > < img src = $ { '/' + image + '/view' } style = "width: 256px; height: auto" > < / i m g > < / d i v >
< div > $ { unsafeHTML ( tfutils . markdown ( description ) ) } < / d i v >
< / d i v >
< / d i v >
< div >
Following $ { profile . following } identities .
Followed by $ { profile . followed } identities .
Blocking $ { profile . blocking } identities .
Blocked by $ { profile . blocked } identities .
2022-09-10 02:56:15 +00:00
< / d i v >
< / d i v >
2024-12-29 15:51:51 -05:00
< footer class = "w3-container" >
< p >
$ { edit }
$ { follow }
$ { block }
< / p >
< / f o o t e r >
2022-09-06 23:26:43 +00:00
< / d i v > ` ;
}
}
2024-02-24 11:09:34 -05:00
customElements . define ( 'tf-profile' , TfProfileElement ) ;