@ -257,7 +257,10 @@ document.body.addEventListener('click', (e) => {
const textNoteList = [ ] ; // could use indexDB
const textNoteList = [ ] ; // could use indexDB
const eventRelayMap = { } ; // eventId: [relay1, relay2]
const eventRelayMap = { } ; // eventId: [relay1, relay2]
const hasEventTag = tag => tag [ 0 ] === 'e' ;
const hasEventTag = tag => tag [ 0 ] === 'e' ;
const isReply = ( [ tag , , , marker ] ) => tag === 'e' && marker !== 'mention' ;
const isMention = ( [ tag , , , marker ] ) => tag === 'e' && marker === 'mention' ;
function handleTextNote ( evt , relay ) {
function handleTextNote ( evt , relay ) {
if ( eventRelayMap [ evt . id ] ) {
if ( eventRelayMap [ evt . id ] ) {
@ -273,7 +276,27 @@ function handleTextNote(evt, relay) {
}
}
}
}
const replyList = [ ] ; // could use textNoteList with isReply field
const replyList = [ ] ;
const replyDomMap = { } ;
const replyToMap = { } ;
function handleReply ( evt , relay ) {
if (
replyDomMap [ evt . id ] // already rendered probably received from another relay
|| evt . tags . some ( isMention ) // ignore mentions for now
) {
return ;
}
if ( ! replyToMap [ evt . id ] ) {
replyToMap [ evt . id ] = getReplyTo ( evt ) ;
}
replyList . push ( {
replyTo : replyToMap [ evt . id ] ,
... evt ,
} ) ;
renderReply ( evt , relay ) ;
}
const reactionMap = { } ;
const reactionMap = { } ;
const getReactionList = ( id ) => {
const getReactionList = ( id ) => {
@ -313,7 +336,6 @@ function handleReaction(evt, relay) {
// feed
// feed
const feedContainer = document . querySelector ( '#homefeed' ) ;
const feedContainer = document . querySelector ( '#homefeed' ) ;
const feedDomMap = { } ;
const feedDomMap = { } ;
const replyDomMap = { } ;
const restoredReplyTo = localStorage . getItem ( 'reply_to' ) ;
const restoredReplyTo = localStorage . getItem ( 'reply_to' ) ;
const sortByCreatedAt = ( evt1 , evt2 ) => {
const sortByCreatedAt = ( evt1 , evt2 ) => {
@ -434,7 +456,8 @@ function linkPreview(href, id, relay) {
}
}
function createTextNote ( evt , relay ) {
function createTextNote ( evt , relay ) {
const { host , img , isReply , name , replies , time , userName } = getMetadata ( evt , relay ) ;
const { host , img , name , time , userName } = getMetadata ( evt , relay ) ;
const replies = replyList . filter ( ( { replyTo } ) => replyTo === evt . id ) ;
// const isLongContent = evt.content.trimRight().length > 280;
// const isLongContent = evt.content.trimRight().length > 280;
// const content = isLongContent ? evt.content.slice(0, 280) : evt.content;
// const content = isLongContent ? evt.content.slice(0, 280) : evt.content;
const hasReactions = reactionMap [ evt . id ] ? . length > 0 ;
const hasReactions = reactionMap [ evt . id ] ? . length > 0 ;
@ -446,7 +469,6 @@ function createTextNote(evt, relay) {
className : 'mbox-header' ,
className : 'mbox-header' ,
title : ` User: ${ userName } \n ${ time } \n \n User pubkey: ${ evt . pubkey } \n \n Relay: ${ host } \n \n Event-id: ${ evt . id }
title : ` User: ${ userName } \n ${ time } \n \n User pubkey: ${ evt . pubkey } \n \n Relay: ${ host } \n \n Event-id: ${ evt . id }
$ { evt . tags . length ? ` \n Tags ${ JSON . stringify ( evt . tags ) } \n ` : '' }
$ { evt . tags . length ? ` \n Tags ${ JSON . stringify ( evt . tags ) } \n ` : '' }
$ { isReply ? ` \n Reply to ${ evt . tags [ 0 ] [ 1 ] } \n ` : '' }
$ { evt . content } `
$ { evt . content } `
} , [
} , [
elem ( 'small' , { } , [
elem ( 'small' , { } , [
@ -473,7 +495,6 @@ function createTextNote(evt, relay) {
elem ( 'small' , { data : { reactions : '' } } , hasReactions ? reactionMap [ evt . id ] . length : '' ) ,
elem ( 'small' , { data : { reactions : '' } } , hasReactions ? reactionMap [ evt . id ] . length : '' ) ,
] ) ,
] ) ,
] ) ,
] ) ,
// replies[0] ? elem('div', {className: 'mobx-replies'}, replyFeed.reverse()) : '',
] ) ;
] ) ;
if ( restoredReplyTo === evt . id ) {
if ( restoredReplyTo === evt . id ) {
appendReplyForm ( body . querySelector ( '.buttons' ) ) ;
appendReplyForm ( body . querySelector ( '.buttons' ) ) ;
@ -481,22 +502,13 @@ function createTextNote(evt, relay) {
}
}
return renderArticle ( [
return renderArticle ( [
elem ( 'div' , { className : 'mbox-img' } , [ img ] ) , body ,
elem ( 'div' , { className : 'mbox-img' } , [ img ] ) , body ,
replies [ 0 ] ? elem ( 'div' , { className : 'mobx-replies' } , replyFeed . reverse( ) ) : '' ,
replies [ 0 ] ? elem ( 'div' , { className : 'mobx-replies' } , replyFeed . sort( sortByCreatedAt ) . reverse( ) ) : '' ,
] , { data : { id : evt . id , pubkey : evt . pubkey , relay } } ) ;
] , { data : { id : evt . id , pubkey : evt . pubkey , relay } } ) ;
}
}
function handleReply ( evt , relay ) {
if ( replyDomMap [ evt . id ] ) {
console . log ( 'CALL ME already have reply in replyDomMap' , evt , relay ) ;
return ;
}
replyList . push ( evt ) ;
renderReply ( evt , relay ) ;
}
function renderReply ( evt , relay ) {
function renderReply ( evt , relay ) {
const eventId = evt . tags . filter ( hasEventTag ) [ 0 ] [ 1 ] ; // TODO: should check for 'reply' marker with fallback to 'root' marker or last 'e' tag, see nip-10
const replyToId = replyToMap [ evt . id ] ;
const article = feedDomMap [ eventId] || replyDomMap [ event Id] ;
const article = feedDomMap [ replyToId ] || replyDomMap [ replyToId ] ;
if ( ! article ) { // root article has not been rendered
if ( ! article ) { // root article has not been rendered
return ;
return ;
}
}
@ -707,10 +719,29 @@ function getMetadata(evt, relay) {
src : userImg ,
src : userImg ,
title : ` ${ userName } on ${ host } ${ userAbout } ` ,
title : ` ${ userName } on ${ host } ${ userAbout } ` ,
} ) : elemCanvas ( evt . pubkey ) ;
} ) : elemCanvas ( evt . pubkey ) ;
const isReply = evt . tags . some ( hasEventTag ) ;
const isReply = ! ! replyToMap [ evt . id ] ;
const replies = replyList . filter ( ( { tags } ) => tags . filter ( hasEventTag ) . some ( reply => reply [ 1 ] === evt . id ) ) ; // TODO: nip-10
const time = new Date ( evt . created _at * 1000 ) ;
const time = new Date ( evt . created _at * 1000 ) ;
return { host , img , isReply , name , replies , time , userName } ;
return { host , img , isReply , name , time , userName } ;
}
/ * *
* find reply - to ID according to nip - 10 , find marked reply or root tag or
* fallback to positional ( last ) e tag or return null
* @ param { event } evt
* @ returns replyToID | null
* /
function getReplyTo ( evt ) {
const eventTags = evt . tags . filter ( isReply ) ;
const withReplyMarker = eventTags . filter ( ( [ , , , marker ] ) => marker === 'reply' ) ;
if ( withReplyMarker . length === 1 ) {
return withReplyMarker [ 0 ] [ 1 ] ;
}
const withRootMarker = eventTags . filter ( ( [ , , , marker ] ) => marker === 'root' ) ;
if ( withReplyMarker . length === 0 && withRootMarker . length === 1 ) {
return withRootMarker [ 0 ] [ 1 ] ;
}
// fallback to deprecated positional 'e' tags (nip-10)
return eventTags . length ? eventTags . at ( - 1 ) [ 1 ] : null ;
}
}
const writeForm = document . querySelector ( '#writeForm' ) ;
const writeForm = document . querySelector ( '#writeForm' ) ;