mirror of
https://github.com/aljazceru/njump.git
synced 2026-02-10 00:24:24 +01:00
Add link to the parent note, flag note as reply in the profile's last notes
This commit is contained in:
6
go.mod
6
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
|
||||
|
||||
8
go.sum
8
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=
|
||||
|
||||
19
render.go
19
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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,5 +63,5 @@
|
||||
{{end}}
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="/njump/static/styles.css?v=20230530b" />
|
||||
<link rel="stylesheet" href="/njump/static/styles.css?v=20230601" />
|
||||
</head>
|
||||
|
||||
@@ -23,9 +23,15 @@
|
||||
</div>
|
||||
<div class="npub">{{.npubShort | sanitizeString}}</div>
|
||||
</div>
|
||||
<div class="published_at">{{.createdAt | sanitizeString}}</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="published_at">{{.createdAt | sanitizeString}}</div>
|
||||
|
||||
{{ if .parentNevent }}
|
||||
<div class="reply_of">
|
||||
In reply to {{ printf "%s%s" "nostr:" .parentNevent | sanitizeString | basicFormatting }}
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
<div class="field separator"></div>
|
||||
|
||||
|
||||
@@ -68,6 +68,9 @@
|
||||
<div class="published_at">
|
||||
{{.CreatedAt}}
|
||||
</div>
|
||||
{{if not (eq .ParentNevent "")}}
|
||||
<div class="is_reply">- reply</div>
|
||||
{{end}}
|
||||
<div class="content">
|
||||
{{.Content}}
|
||||
</div>
|
||||
|
||||
17
utils.go
17
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, `<a href="$1">$1</a>`)
|
||||
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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user