From ea0f0b647d01621e3dfa7f5068f5e02fc4e38927 Mon Sep 17 00:00:00 2001 From: Daniele Tonon Date: Thu, 1 Jun 2023 11:07:05 +0200 Subject: [PATCH] Add link to the parent note, flag note as reply in the profile's last notes --- go.mod | 6 ++++-- go.sum | 8 ++++---- render.go | 19 ++++++++++++------- static/styles.css | 43 ++++++++++++++++++++++++++++++------------ static/styles.scss | 37 ++++++++++++++++++++++++++---------- templates/head.html | 2 +- templates/note.html | 8 +++++++- templates/profile.html | 3 +++ utils.go | 17 +++++++++++++++++ 9 files changed, 106 insertions(+), 37 deletions(-) diff --git a/go.mod b/go.mod index 181c21b..34c1ddb 100644 --- a/go.mod +++ b/go.mod @@ -7,14 +7,15 @@ require ( github.com/die-net/lrucache v0.0.0-20220628165024-20a71bc65bf1 github.com/lukevers/freetype-go v0.0.0-20150513150840-77e276735410 github.com/mailru/easyjson v0.7.7 - github.com/nbd-wtf/go-nostr v0.18.4 + github.com/nbd-wtf/go-nostr v0.18.7 github.com/pelletier/go-toml v1.9.5 github.com/rs/zerolog v1.29.1 golang.org/x/image v0.0.0-20190802002840-cff245a6509b ) +replace github.com/nbd-wtf/go-nostr v0.18.7 => github.com/nbd-wtf/go-nostr v0.18.8-0.20230531153548-b7ec430166bb + require ( - github.com/SaveTheRbtz/generic-sync-map-go v0.0.0-20220414055132-a37292614db8 // indirect github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect github.com/btcsuite/btcd/btcutil v1.1.3 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect @@ -26,6 +27,7 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect + github.com/puzpuzpuz/xsync v1.5.2 // indirect github.com/tidwall/gjson v1.14.4 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect diff --git a/go.sum b/go.sum index 13730a5..bf6a445 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -github.com/SaveTheRbtz/generic-sync-map-go v0.0.0-20220414055132-a37292614db8 h1:Xa6tp8DPDhdV+k23uiTC/GrAYOe4IdyJVKtob4KW3GA= -github.com/SaveTheRbtz/generic-sync-map-go v0.0.0-20220414055132-a37292614db8/go.mod h1:ihkm1viTbO/LOsgdGoFPBSvzqvx7ibvkMzYp3CgtHik= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/apatters/go-wordwrap v1.0.0 h1:G6ni4Pt7/I4ED+A5ZvsK8e9XwETD04veDKxEL2QN830= github.com/apatters/go-wordwrap v1.0.0/go.mod h1:3sM7HcArQ+utXnjDQ4d1xjrd8b/wbKuDr/RmbiHgjwI= @@ -75,8 +73,8 @@ github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZb github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/nbd-wtf/go-nostr v0.18.4 h1:P5qHEvvwS6DMaDMD82fP66M3kFBJnNQATczGH93rC0s= -github.com/nbd-wtf/go-nostr v0.18.4/go.mod h1:GPJOOK8US38kz+bfb9nWe873Xu0e6bXlThejOs1LTkc= +github.com/nbd-wtf/go-nostr v0.18.8-0.20230531153548-b7ec430166bb h1:28eaYF27FKWf5aO4plC0z0b4ht9FntbKC9IkAaQwxAs= +github.com/nbd-wtf/go-nostr v0.18.8-0.20230531153548-b7ec430166bb/go.mod h1:F9y6+M8askJCjilLgMC3rD0moA6UtG1MCnyClNYXeys= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -91,6 +89,8 @@ github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/puzpuzpuz/xsync v1.5.2 h1:yRAP4wqSOZG+/4pxJ08fPTwrfL0IzE/LKQ/cw509qGY= +github.com/puzpuzpuz/xsync v1.5.2/go.mod h1:K98BYhX3k1dQ2M63t1YNVDanbwUPmBCAhNmVrrxfiGg= github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc= github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU= diff --git a/render.go b/render.go index d613832..00ae99a 100644 --- a/render.go +++ b/render.go @@ -24,10 +24,10 @@ var static embed.FS var templates embed.FS type Event struct { - Nevent string - Content string - CreatedAt string - // ... + Nevent string + Content string + CreatedAt string + ParentNevent string } func render(w http.ResponseWriter, r *http.Request) { @@ -65,6 +65,7 @@ func render(w http.ResponseWriter, r *http.Request) { typ := "" author := event lastNotes := make([]Event, 0) + parentNevent := "" if event.Kind == 0 { typ = "profile" @@ -74,9 +75,10 @@ func render(w http.ResponseWriter, r *http.Request) { this_nevent, _ := nip19.EncodeEvent(n.ID, []string{}, n.PubKey) this_date := time.Unix(int64(n.CreatedAt), 0).Format("2006-01-02 15:04:05") lastNotes[i] = Event{ - Nevent: this_nevent, - Content: n.Content, - CreatedAt: this_date, + Nevent: this_nevent, + Content: n.Content, + CreatedAt: this_date, + ParentNevent: findParentNevent(&n), } } if err != nil { @@ -89,6 +91,8 @@ func render(w http.ResponseWriter, r *http.Request) { typ = "note" note, _ = nip19.EncodeNote(event.ID) content = event.Content + parentNevent = findParentNevent(event) + } else if event.Kind == 6 { typ = "note" if reposted := event.Tags.GetFirst([]string{"e", ""}); reposted != nil { @@ -228,6 +232,7 @@ func render(w http.ResponseWriter, r *http.Request) { "kindDescription": kindDescription, "kindNIP": kindNIP, "lastNotes": lastNotes, + "parentNevent": parentNevent, } // Use a mapping to expressly link the templates and share them between more kinds/types diff --git a/static/styles.css b/static/styles.css index c5e8f42..5190e33 100644 --- a/static/styles.css +++ b/static/styles.css @@ -216,7 +216,7 @@ h1, h2 { color: #c9c9c9; } .theme--dark .container .columnA .info-wrapper .display { - color: #c9c9c9; + color: #969696; } } .container .columnA .last_update { @@ -228,7 +228,7 @@ h1, h2 { color: #c9c9c9; } .theme--dark .container .columnA .last_update { - color: #c9c9c9; + color: #969696; } @media (max-width: 580px) { .container .columnA .last_update { @@ -247,7 +247,7 @@ h1, h2 { color: #c9c9c9; } .theme--dark .container .column_content .info-wrapper .display { - color: #c9c9c9; + color: #969696; } .container .column_content .info-wrapper .npub { font-size: 1rem; @@ -256,7 +256,7 @@ h1, h2 { color: #c9c9c9; } .theme--dark .container .column_content .info-wrapper .npub { - color: #c9c9c9; + color: #969696; } @media (max-width: 580px) { .container .column_content .info-wrapper { @@ -345,6 +345,9 @@ h1, h2 { border-bottom: none; } .container .column_content .field.last_notes a.note { + display: flex; + flex-direction: row; + flex-wrap: wrap; margin-bottom: 1rem; } .container .column_content .field.last_notes a.note .published_at { @@ -356,7 +359,19 @@ h1, h2 { .theme--dark .container .column_content .field.last_notes a.note .published_at { color: #e32a6d; } +.container .column_content .field.last_notes a.note .is_reply { + margin-left: 0.5em; + font-size: 0.8rem; +} +.theme--default .container .column_content .field.last_notes a.note .is_reply { + color: #c9c9c9; +} +.theme--dark .container .column_content .field.last_notes a.note .is_reply { + color: #969696; +} .container .column_content .field.last_notes a.note .content { + flex-basis: 100%; + margin-top: 0.2rem; max-height: 160px; overflow: hidden; } @@ -525,7 +540,7 @@ h1, h2 { color: #c9c9c9; } .theme--dark .container .column_content .field.last_update { - color: #c9c9c9; + color: #969696; } } .container .column_clients { @@ -727,22 +742,26 @@ body.note .column_content .profile_intro .pic-wrapper, body.raw .column_content margin-right: 0.5rem; } } -body.note .column_content .profile_intro .published_at, body.raw .column_content .profile_intro .published_at { +body.note .column_content .published_at, body.note .column_content .reply_of, body.raw .column_content .published_at, body.raw .column_content .reply_of { width: 100%; text-align: right; align-self: end; font-size: 0.8rem; } -.theme--default body.note .column_content .profile_intro .published_at, .theme--default body.raw .column_content .profile_intro .published_at { +.theme--default body.note .column_content .published_at, .theme--default body.note .column_content .reply_of, .theme--default body.raw .column_content .published_at, .theme--default body.raw .column_content .reply_of { color: #9a9a9a; } -.theme--dark body.note .column_content .profile_intro .published_at, .theme--dark body.raw .column_content .profile_intro .published_at { +.theme--dark body.note .column_content .published_at, .theme--dark body.note .column_content .reply_of, .theme--dark body.raw .column_content .published_at, .theme--dark body.raw .column_content .reply_of { color: #f3f3f3; } -@media (max-width: 580px) { - body.note .column_content .profile_intro .published_at, body.raw .column_content .profile_intro .published_at { - padding-top: 0.5rem; - } +.theme--default body.note .column_content .published_at a, .theme--default body.note .column_content .reply_of a, .theme--default body.raw .column_content .published_at a, .theme--default body.raw .column_content .reply_of a { + color: #e32a6d; +} +.theme--dark body.note .column_content .published_at a, .theme--dark body.note .column_content .reply_of a, .theme--dark body.raw .column_content .published_at a, .theme--dark body.raw .column_content .reply_of a { + color: #e32a6d; +} +body.note .column_content .reply_of, body.raw .column_content .reply_of { + margin-top: 0.2rem; } .footer { diff --git a/static/styles.scss b/static/styles.scss index 2de7033..f8385a7 100644 --- a/static/styles.scss +++ b/static/styles.scss @@ -31,7 +31,7 @@ $themes: ( base1: $color-base7, base2: $color-base6, base3: $color-base5, - base4: $color-base4, + base4: darken($color-base4, 20%), base5: $color-base3, base6: $color-base2, base7: $color-base2, @@ -364,6 +364,9 @@ a { text-decoration: none; border-bottom: none; &.note { + display: flex; + flex-direction: row; + flex-wrap: wrap; margin-bottom: 1rem; .published_at { font-size: 0.8rem; @@ -371,7 +374,16 @@ a { color: t($accent1); } } + .is_reply { + margin-left: 0.5em; + font-size: 0.8rem; + @include themed() { + color: t($base4); + } + } .content { + flex-basis: 100%; + margin-top: 0.2rem; max-height: 160px; overflow: hidden; &.gradient { @@ -687,19 +699,24 @@ body.note, body.raw { margin-right: 0.5rem; } } - .published_at { - width: 100%; - text-align: right; - align-self: end; - font-size: 0.8rem; + } + .published_at, .reply_of { + width: 100%; + text-align: right; + align-self: end; + font-size: 0.8rem; + @include themed() { + color: t($base5); + } + a { @include themed() { - color: t($base5); - } - @media (max-width: 580px) { - padding-top: 0.5rem; + color: t($accent1); } } } + .reply_of { + margin-top: 0.2rem; + } } } diff --git a/templates/head.html b/templates/head.html index d86709f..7277742 100644 --- a/templates/head.html +++ b/templates/head.html @@ -63,5 +63,5 @@ {{end}} - + diff --git a/templates/note.html b/templates/note.html index 9bff0fb..0aa5edf 100644 --- a/templates/note.html +++ b/templates/note.html @@ -23,9 +23,15 @@
{{.npubShort | sanitizeString}}
-
{{.createdAt | sanitizeString}}
+
{{.createdAt | sanitizeString}}
+ + {{ if .parentNevent }} +
+ In reply to {{ printf "%s%s" "nostr:" .parentNevent | sanitizeString | basicFormatting }} +
+ {{ end }}
diff --git a/templates/profile.html b/templates/profile.html index 3046c71..b610d88 100644 --- a/templates/profile.html +++ b/templates/profile.html @@ -68,6 +68,9 @@
{{.CreatedAt}}
+ {{if not (eq .ParentNevent "")}} +
- reply
+ {{end}}
{{.Content}}
diff --git a/utils.go b/utils.go index 560a3eb..dc3e71d 100644 --- a/utils.go +++ b/utils.go @@ -8,6 +8,8 @@ import ( "strings" "github.com/nbd-wtf/go-nostr" + "github.com/nbd-wtf/go-nostr/nip10" + "github.com/nbd-wtf/go-nostr/nip19" "github.com/pelletier/go-toml" ) @@ -227,3 +229,18 @@ func replaceURLsWithTags(line string) string { line = hrefRegex.ReplaceAllString(line, `$1`) return line } + +func findParentNevent(event *nostr.Event) string { + parentNevent := "" + replyTag := nip10.GetImmediateReply(event.Tags) + if replyTag != nil { + relay := "" + if len(*replyTag) > 2 { + relay = (*replyTag)[2] + } else { + relay = "" + } + parentNevent, _ = nip19.EncodeEvent((*replyTag)[1], []string{relay}, "") + } + return parentNevent +}