Setup up a first desktop version

This commit is contained in:
Daniele Tonon
2023-05-22 15:46:39 +02:00
parent e8a2932e09
commit 2b10bc61b7
6 changed files with 267 additions and 31 deletions

2
.gitignore vendored
View File

@@ -1 +1,3 @@
njump
.air.toml
tmp/*

View File

@@ -47,32 +47,89 @@
{{end}}
<!----------->
<style>
body {
padding: 3%;
}
#event {
margin: 5% 0;
white-space: pre-wrap;
word-wrap: break-word;
word-break: break-all;
font-family: monospace;
font-size: 130%;
}
</style>
<link rel="stylesheet" href="/static/styles.css" />
</head>
<body>
<div>
open {{.type}} in {{range .clients}}<br />
&nbsp;&nbsp;<span style="color: #bbb"></span>
<a class="client" href="{{.url}}">{{.name}}</a> {{end}}
<div class="top">
<a href="https://nostr.com" class="nostr_link">What is nostr?</a>
</div>
<div id="event">{{.eventJSON}}</div>
<div style="display: flex; justify-content: flex-end">
<div class="container_wrapper">
<div class="container profile">
<div class="column column1">
<div class="pic-wrapper">
<img class="pic" src="{{ .metadata.Picture }}" />
<svg width="0" height="0" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<clipPath id="svg-shape" clipPathUnits="objectBoundingBox">
<path
transform="scale(0.005, 0.005)"
d="M100,200c43.8,0,68.2,0,84.1-15.9C200,168.2,200,143.8,200,100s0-68.2-15.9-84.1C168.2,0,143.8,0,100,0S31.8,0,15.9,15.9C0,31.8,0,56.2,0,100s0,68.2,15.9,84.1C31.8,200,56.2,200,100,200z"
/>
</clipPath>
</defs>
</svg>
</div>
<div class="last_update">
Last update:<br/>
{{.createdAt}}
</div>
</div>
<div class="column column2">
<div class="field name">
{{.content_json.name}} <span class="display">{{.content_json.display_name}}</span>
</div>
<div class="field separator"></div>
<div class="field">
<a href="{{.content_json.website}}">{{.content_json.website}}</a>
</div>
<div class="field">
{{.content_json.about}}
</div>
<div class="field separator"></div>
<div class="field">
<div class="label">Public key</div>
{{.npub}}
</div>
<div class="field">
<div class="label">NIP-05</div>
{{.content_json.nip05}}
</div>
<div class="field">
<div class="label">LN Address</div>
{{.content_json.lud16}}
</div>
<div class="field">
<div class="label">Metadata Event</div>
{{.nevent}}
</div>
<div class="field">
<div class="label">JSON</div>
{{.eventJSON}}
</div>
<div class="field separator"></div>
</div>
<div class="column column3">
<div class="title">Open {{.type}} in</div>
<div class="clients">
{{range .clients}}
<div class="btn">
<a class="client" href="{{.url}}">{{.name}}</a>
<span></span>
</div>
{{end}}
</div>
</div>
</div>
</div>
<!-- <div style="display: flex; justify-content: flex-end">
<span>
powered by <a href="https://git.fiatjaf.com/njump">njump</a>
</span>
</div>
</div> -->
<script>
const type = '{{.type}}'
let counts = []
@@ -82,7 +139,7 @@
let url = clients[i].href
let key = 'nj:' + type + ':' + name
let count = parseInt(localStorage.getItem(key) || 0)
clients[i].previousElementSibling.innerText = count
clients[i].nextElementSibling.innerText = count
clients[i].addEventListener('click', () => {
localStorage.setItem(key, count + 1)
})
@@ -97,5 +154,8 @@
}
}
</script>
<div class="background"></div>
</body>
</html>

View File

@@ -7,6 +7,9 @@ import (
)
func main() {
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
http.HandleFunc("/image/", generate)
http.HandleFunc("/proxy/", proxy)
http.HandleFunc("/", render)

View File

@@ -8,7 +8,7 @@ import (
"regexp"
"strings"
"text/template"
"time"
"github.com/nbd-wtf/go-nostr"
"github.com/nbd-wtf/go-nostr/nip19"
)
@@ -48,6 +48,7 @@ func render(w http.ResponseWriter, r *http.Request) {
npub, _ := nip19.EncodePublicKey(event.PubKey)
nevent, _ := nip19.EncodeEvent(event.ID, []string{}, event.PubKey)
naddr := ""
createdAt := time.Unix(int64(event.CreatedAt), 0).Format("2006-01-02 15:04:05")
author := event
if event.Kind != 0 {
@@ -142,21 +143,23 @@ func render(w http.ResponseWriter, r *http.Request) {
// : ''
textImageURL := ""
description := ""
content := ""
content_json := make(map[string]interface{})
if useTextImage {
textImageURL = fmt.Sprintf("https://%s/image/%s", hostname, code)
if subject != "" {
description = fmt.Sprintf("%s -- %s", subject, seenOnRelays)
content = fmt.Sprintf("%s -- %s", subject, seenOnRelays)
} else {
description = seenOnRelays
content = seenOnRelays
}
} else {
description = prettyJsonOrRaw(event.Content)
content_json, content = prettyJsonOrRaw(event.Content)
}
eventJSON, _ := json.MarshalIndent(event, "", " ")
params := map[string]any{
"createdAt": createdAt,
"clients": generateClientList(code, event),
"type": typ,
"title": title,
@@ -166,7 +169,8 @@ func render(w http.ResponseWriter, r *http.Request) {
"naddr": naddr,
"metadata": metadata,
"authorLong": authorLong,
"description": description,
"content": content,
"content_json": content_json,
"textImageURL": textImageURL,
"videoType": videoType,
"image": image,

167
static/styles.css Normal file
View File

@@ -0,0 +1,167 @@
html {
font-family: Helvetica, sans-serif;
font-size: 20px;
font-weight: 300;
}
body {
color: #373737;
}
a {
color: #373737;
}
.background {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: white;
overflow: hidden;
z-index: -1;
}
.background::after {
content: "";
position: absolute;
background-color: #FAFAFA;
width: 140%;
height: 100%;
transform: rotate(-20deg);
transform-origin: bottom;
bottom: -40%;
}
.top, .container_wrapper {
display: flex;
justify-content: center;
align-items: center;
}
.top {
margin: 1rem 0;
justify-content: left;
}
.nostr_link {
flex-basis: 15%;
text-align: right;
text-decoration: none;
}
.container {
display: flex;
width: 70%;
justify-content: space-between;
gap: 4.8vw;
}
.column {
}
.column1 {
flex-basis: 25%;
margin-top: 2rem;
}
.container.profile .column1 .pic-wrapper {
max-width: 100%;
overflow: hidden;
}
.container.profile .column1 img.pic {
max-width: 100%;
width: 100%;
height: auto;
-webkit-clip-path: url(#svg-shape);
-moz-clip-path: url(#svg-shape);
-o-clip-path: url(#svg-shape);
-ms-clip-path: url(#svg-shape);
clip-path: url(#svg-shape);
}
.last_update {
font-size: 0.8em;
text-align: center;
color: #C9C9C9;
}
.column2 {
flex-basis: 50%;
max-width: 50%;
flex-grow: 0;
flex-shrink: 0;
word-wrap: break-word;
margin-right: 1vw;
}
.column2 .name {
font-size: 1.6rem;
}
.column2 .name .display {
color: #C9C9C9;
}
.column2 .separator {
height: 6px;
width: 30%;
margin-left: -0.6rem;
background-color: #F3F3F3;
}
.column2 .field {
margin-bottom: 1.5rem;
}
.column2 .field .label {
font-size: 0.8rem;
color: #E32A6D;
}
.column3 {
flex-basis: 25%;
margin-top: 2rem;
}
.column3 .title {
font-size: 0.8rem;
margin-bottom: 1rem;
}
.column3 .btn {
display: flex;
align-items: center;
margin-bottom: 0.8rem;
}
.column3 .btn a {
flex-basis: 80%;
padding: 0.4rem;
text-align: center;
font-size: 0.9rem;
color: #FFFFFF;
background-color: #5A5A5A;
text-decoration: none;
border-radius: 8px;
}
.column3 .btn a:hover {
background-color: #373737;
}
.column3 .btn:first-child a {
background-color: #E32A6D;
}
.column3 .btn:first-child a:hover {
background-color: #bc1150;
}
.column3 .btn span {
flex-basis: 20%;
margin-left: 0.4rem;
color: #9a9a9a;
}

View File

@@ -81,14 +81,14 @@ func mergeMaps[K comparable, V any](m1 map[K]V, m2 map[K]V) map[K]V {
return m1
}
func prettyJsonOrRaw(j string) string {
var parsedContent any
func prettyJsonOrRaw(j string) (map[string]interface{}, string) {
var parsedContent map[string]interface{}
if err := json.Unmarshal([]byte(j), &parsedContent); err == nil {
if t, err := toml.Marshal(parsedContent); err == nil && len(t) > 0 {
return string(t)
return parsedContent, string(t)
}
}
return j
return nil, j
}
func getPreviewStyle(r *http.Request) string {