summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorewy <ewy0@protonmail.com>2026-04-09 21:01:59 +0200
committerewy <ewy0@protonmail.com>2026-04-09 21:01:59 +0200
commit6e896ae0e108eef385b46c26e770dc191ae936ba (patch)
tree3f34ba405833fd08b2b9396ca50d0cb454126b53
parent4b082851542cf8b546e3fbacaf0b27a7db5b80eb (diff)
add more css
-rw-r--r--go.mod2
-rw-r--r--go.sum10
-rw-r--r--main.go2
-rw-r--r--pages/create.go22
-rw-r--r--pages/create.gohtml31
-rw-r--r--pages/header.gohtml12
-rw-r--r--pages/landing.go7
-rw-r--r--pages/landing.gohtml46
-rw-r--r--pages/local.go58
-rw-r--r--pages/receive.go5
-rw-r--r--pages/style.gohtml84
-rw-r--r--storage/link.go1
12 files changed, 223 insertions, 57 deletions
diff --git a/go.mod b/go.mod
index e229c11..43e6991 100644
--- a/go.mod
+++ b/go.mod
@@ -6,4 +6,6 @@ require (
github.com/google/uuid v1.6.0 // indirect
github.com/mattn/go-sqlite3 v1.14.38 // indirect
github.com/spf13/pflag v1.0.10 // indirect
+ golang.org/x/sys v0.43.0 // indirect
+ gopkg.in/fsnotify/fsnotify.v1 v1.4.7 // indirect
)
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..ccbbde1
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,10 @@
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/mattn/go-sqlite3 v1.14.38 h1:tDUzL85kMvOrvpCt8P64SbGgVFtJB11GPi2AdmITgb4=
+github.com/mattn/go-sqlite3 v1.14.38/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
+github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
+github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
+golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
+gopkg.in/fsnotify/fsnotify.v1 v1.4.7 h1:XNNYLJHt73EyYiCZi6+xjupS9CpvmiDgjPTAjrBlQbo=
+gopkg.in/fsnotify/fsnotify.v1 v1.4.7/go.mod h1:Fyux9zXlo4rWoMSIzpn9fDAYjalPqJ/K1qJ27s+7ltE=
diff --git a/main.go b/main.go
index bf616cb..e06c63f 100644
--- a/main.go
+++ b/main.go
@@ -22,6 +22,8 @@ var (
func main() {
pflag.Parse()
+ pages.SetupLocal()
+
http.HandleFunc("GET /{$}", pages.Land)
http.HandleFunc("POST /{$}", pages.Create)
http.HandleFunc("GET /l/{id}", pages.Get)
diff --git a/pages/create.go b/pages/create.go
index 03f4159..5469ee8 100644
--- a/pages/create.go
+++ b/pages/create.go
@@ -58,6 +58,7 @@ func CreateLink(w http.ResponseWriter, r *http.Request) *storage.Link {
OpensFrom: time.Now().Add(time.Duration(minutesInFuture) * time.Minute),
OpensLeft: numberOfOpens,
}
+ l.OpensStr = l.OpensFrom.Format(time.UnixDate)
id, err := l.Save(storage.Current)
if err != nil {
@@ -69,17 +70,30 @@ func CreateLink(w http.ResponseWriter, r *http.Request) *storage.Link {
return &l
}
-//go:embed create.gohtml
-var recContent string
-var recTmpl = template.Must(template.New("delayed.link").Parse(recContent))
+var tmpl = template.New("delayed.link")
func Create(w http.ResponseWriter, r *http.Request) {
l := CreateLink(w, r)
if l == nil {
return
}
- err := recTmpl.Execute(w, l)
+ err := tmpl.ExecuteTemplate(w, "create", l)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
+
+//go:embed create.gohtml
+var recContent string
+
+//go:embed style.gohtml
+var style string
+
+//go:embed header.gohtml
+var header string
+
+func init() {
+ template.Must(tmpl.Parse(style))
+ template.Must(tmpl.Parse(header))
+ template.Must(tmpl.New("create").Parse(recContent))
+}
diff --git a/pages/create.gohtml b/pages/create.gohtml
index 5d402cb..d50582a 100644
--- a/pages/create.gohtml
+++ b/pages/create.gohtml
@@ -7,19 +7,26 @@
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="icon" href="data:,"/>
<title>delayed.link: created</title>
+ {{ template "style" . }}
</head>
<body>
-<p>
- <a href="/l/{{.Id}}">This link will unlock at {{.OpensFrom}}</a>
-</p>
-<p>
- This will occur in approximately {{ .MinutesLeft }} minute{{ if gt .MinutesLeft 1 }}s{{end}}.
-</p>
-<p>
- It will be able to be opened {{ .OpensLeft }} time{{ if gt .OpensLeft 1 }}s{{end}}.
-</p>
-<p>
- This page is completely ephemeral. Once you close it, you cannot access the link again.
-</p>
+{{ template "header" . }}
+<main>
+ <div>
+ <a href="/l/{{.Id}}">This link will unlock at {{.OpensStr}}</a>
+ </div>
+ <div>
+ It will occur in approximately {{ .MinutesLeft }} minute{{ if gt .MinutesLeft 1 }}s{{end}}.
+ </div>
+ <div>
+ It can be opened {{ .OpensLeft }} time{{ if gt .OpensLeft 1 }}s{{end}}.
+ </div>
+ <div>
+ Be mindful embedding services might take visits off the counter.
+ </div>
+ <div>
+ This page is completely ephemeral. Once you close it, you cannot access the link again.
+ </div>
+</main>
</body>
</html> \ No newline at end of file
diff --git a/pages/header.gohtml b/pages/header.gohtml
new file mode 100644
index 0000000..5af455e
--- /dev/null
+++ b/pages/header.gohtml
@@ -0,0 +1,12 @@
+{{ define "header" }}
+ <header>
+ <a href="/">
+ <h1>
+ delayed.link
+ </h1>
+ </a>
+ <span>
+ send something now, they unlock it later
+ </span>
+ </header>
+{{end}} \ No newline at end of file
diff --git a/pages/landing.go b/pages/landing.go
index d8c4f54..d2c2fc3 100644
--- a/pages/landing.go
+++ b/pages/landing.go
@@ -8,12 +8,15 @@ import (
//go:embed landing.gohtml
var landContent string
-var landTmpl = template.Must(template.New("delayed.link").Parse(landContent))
func Land(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
- err := landTmpl.Execute(w, nil)
+ err := tmpl.ExecuteTemplate(w, "land", nil)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
+
+func init() {
+ template.Must(tmpl.New("land").Parse(landContent))
+}
diff --git a/pages/landing.gohtml b/pages/landing.gohtml
index 40f5ae3..021cb95 100644
--- a/pages/landing.gohtml
+++ b/pages/landing.gohtml
@@ -4,55 +4,34 @@
<meta charset="UTF-8">
<link rel="icon" href="data:,"/>
<title>delayed.link</title>
- <style>
- main {
- min-height: 105vh;
- }
-
- label {
- display: flex;
- justify-content: space-between;
- max-width: 500px;
- }
-
- input[type="number"] {
- width: 64px;
- }
-
- form {
- display: flex;
- flex-direction: column;
- gap: 4px;
- }
- </style>
+ {{ template "style" . }}
</head>
<body>
+{{ template "header" . }}
<main>
<form method="POST" action="/">
- <div>
<label>
- Lock time in minutes
+ <span>
+ Lock time in minutes
+ </span>
<input type="number" name="minutes_in_future" value="10"/>
</label>
- </div>
- <div>
<label>
- Maximum times the link can be opened
+ <span>
+ Maximum times the link can be opened
+ </span>
<input type="number" name="number_of_opens" min="1" max="100" value="8"/>
</label>
- </div>
- <div>
<label>
- URL to save for later
+ <span>
+ URL to save for later
+ </span>
<input type="text" name="payload"/>
</label>
- </div>
- <div>
<label>
<span></span>
<input type="submit" value="Create"/>
</label>
- </div>
</form>
</main>
<footer>
@@ -60,8 +39,7 @@
WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH THE CUSTOMER. SHOULD
- THE SOFTWARE PROVE DEFECTIVE, THE CUSTOMER ASSUMES THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION EXCEPT
- TO THE EXTENT SET OUT UNDER THE HARDWARE WARRANTY IN THESE TERMS.
+ THE SOFTWARE PROVE DEFECTIVE, THE CUSTOMER ASSUMES THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.
</footer>
</body>
</html> \ No newline at end of file
diff --git a/pages/local.go b/pages/local.go
new file mode 100644
index 0000000..ccd0f41
--- /dev/null
+++ b/pages/local.go
@@ -0,0 +1,58 @@
+package pages
+
+import (
+ "fmt"
+ "github.com/spf13/pflag"
+ "gopkg.in/fsnotify/fsnotify.v1"
+ "html/template"
+ "os"
+)
+
+var Local = pflag.BoolP("local", "l", false, "use local files instead of embedded")
+
+var Templates = map[string]func(content string){
+ "pages/create.gohtml": func(content string) {
+ template.Must(tmpl.New("create").Parse(content))
+ },
+ "pages/landing.gohtml": func(content string) {
+ template.Must(tmpl.New("landing").Parse(content))
+ },
+ "pages/style.gohtml": func(content string) {
+ template.Must(tmpl.Parse(content))
+ },
+}
+
+func SetupLocal() {
+ if *Local {
+
+ watcher, err := fsnotify.NewWatcher()
+ if err != nil {
+ panic(err)
+ }
+ for page := range Templates {
+ watcher.Add(page)
+ }
+
+ go func() {
+ for {
+ select {
+ case ev := <-watcher.Events:
+ newContent, err := os.ReadFile(ev.Name)
+ if err != nil {
+ fmt.Printf("error: %vn", err)
+ continue
+ }
+ Templates[ev.Name](string(newContent))
+ if err != nil {
+ fmt.Printf("error: %vn", err)
+ } else {
+ fmt.Printf("updated: %vn", ev.Name)
+
+ }
+
+ }
+ }
+ }()
+
+ }
+}
diff --git a/pages/receive.go b/pages/receive.go
deleted file mode 100644
index 023a20b..0000000
--- a/pages/receive.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package pages
-
-import (
- _ "embed"
-)
diff --git a/pages/style.gohtml b/pages/style.gohtml
new file mode 100644
index 0000000..bb15fb9
--- /dev/null
+++ b/pages/style.gohtml
@@ -0,0 +1,84 @@
+{{ define "style"}}
+<style>
+ @media (prefers-color-scheme: dark) {
+ html {
+ background-color: #3e3b37;
+ color: rgb(222, 213, 200);
+ }
+ }
+
+ body {
+ max-width: 44em;
+ margin: auto;
+ display: flex;
+ flex-direction: column;
+ gap: 32px;
+
+ & p {
+ padding: 4px 0;
+ }
+ }
+ main {
+ min-height: 105vh;
+ display: flex;
+ gap: 16px;
+ flex-direction: column;
+ align-items: center;
+ }
+
+ label {
+ display: flex;
+ justify-content: end;
+ width: 100%;
+ gap: 8px;
+ }
+
+ form {
+ font-family: system-ui;
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+
+ width: 100%;
+
+ & input {
+ background-color: #fefcf8;
+ color: rgb(30, 27, 25);
+ border-color: #bad1f9;
+ border-style: double;
+ }
+
+ & input[type="number"] {
+ width: 48px;
+ }
+
+ & input[type="text"] {
+ width: 20em;
+ }
+
+ & input[type="submit"] {
+ background-color: #bef8d7;
+ border-color: #395143;
+ }
+ }
+
+ header {
+ display: flex;
+ align-items: baseline;
+ gap: 16px;
+ justify-content: space-between;
+
+ & a {
+ text-decoration: none;
+ }
+
+ & h1 {
+ font-family: monospace
+ }
+ }
+
+ a {
+ color: #f2cae2;
+ }
+</style>
+{{end}} \ No newline at end of file
diff --git a/storage/link.go b/storage/link.go
index 6f0a0c3..99542f8 100644
--- a/storage/link.go
+++ b/storage/link.go
@@ -12,6 +12,7 @@ type Link struct {
Target string
OpensFrom time.Time
OpensLeft int
+ OpensStr string
}
var Null = uuid.UUID{}