diff --git a/src/hmnurl/hmnurl_test.go b/src/hmnurl/hmnurl_test.go
index 3a43c81..e71f657 100644
--- a/src/hmnurl/hmnurl_test.go
+++ b/src/hmnurl/hmnurl_test.go
@@ -415,6 +415,31 @@ func TestJamRecap2023_Visibility(t *testing.T) {
AssertSubdomain(t, BuildJamRecap2023_Visibility(), "")
}
+func TestTimeMachine(t *testing.T) {
+ AssertRegexMatch(t, BuildTimeMachine(), RegexTimeMachine, nil)
+ AssertSubdomain(t, BuildTimeMachine(), "")
+}
+
+func TestTimeMachineSubmissions(t *testing.T) {
+ AssertRegexMatch(t, BuildTimeMachineSubmissions(), RegexTimeMachineSubmissions, nil)
+ AssertSubdomain(t, BuildTimeMachineSubmissions(), "")
+}
+
+func TestTimeMachineForm(t *testing.T) {
+ AssertRegexMatch(t, BuildTimeMachineForm(), RegexTimeMachineForm, nil)
+ AssertSubdomain(t, BuildTimeMachineForm(), "")
+}
+
+func TestTimeMachineFormDone(t *testing.T) {
+ AssertRegexMatch(t, BuildTimeMachineFormDone(), RegexTimeMachineFormDone, nil)
+ AssertSubdomain(t, BuildTimeMachineFormDone(), "")
+}
+
+func TestNewsletterSignup(t *testing.T) {
+ AssertRegexMatch(t, BuildNewsletterSignup(), RegexNewsletterSignup, nil)
+ AssertSubdomain(t, BuildNewsletterSignup(), "")
+}
+
func TestProjectNewJam(t *testing.T) {
AssertRegexMatch(t, BuildProjectNewJam(), RegexProjectNew, nil)
AssertSubdomain(t, BuildProjectNewJam(), "")
diff --git a/src/hmnurl/urls.go b/src/hmnurl/urls.go
index 17071c6..6d0eab0 100644
--- a/src/hmnurl/urls.go
+++ b/src/hmnurl/urls.go
@@ -119,6 +119,13 @@ func BuildTimeMachine() string {
return Url("/timemachine", nil)
}
+var RegexTimeMachineSubmissions = regexp.MustCompile("^/timemachine/submissions$")
+
+func BuildTimeMachineSubmissions() string {
+ defer CatchPanic()
+ return Url("/timemachine/submissions", nil)
+}
+
var RegexTimeMachineForm = regexp.MustCompile("^/timemachine/submit$")
func BuildTimeMachineForm() string {
diff --git a/src/templates/src/include/timemachine_submission.html b/src/templates/src/include/timemachine_submission.html
new file mode 100644
index 0000000..9d81c50
--- /dev/null
+++ b/src/templates/src/include/timemachine_submission.html
@@ -0,0 +1,30 @@
+
+ {{ template "frame title" .Title }}
+
+
+
+
+
+ {{ range .Details }}
+
{{ .Name }}: {{ .Content }}
+ {{ end }}
+
+
+
+
+ {{ .Description }}
+
+
+
+
diff --git a/src/templates/src/layouts/timemachine_base.html b/src/templates/src/layouts/timemachine_base.html
index 54daaf6..97e2f2e 100644
--- a/src/templates/src/layouts/timemachine_base.html
+++ b/src/templates/src/layouts/timemachine_base.html
@@ -5,195 +5,213 @@
-
-
+
+
-
-
+
+
- {{ if .CanonicalLink }} {{ end }}
- {{ range .OpenGraphItems }}
- {{ if .Property }}
-
- {{ else }}
-
- {{ end }}
- {{ end }}
- {{ if .Title }}
- {{ .Title }} | Handmade Network
+ {{ if .CanonicalLink }} {{ end }}
+ {{ range .OpenGraphItems }}
+ {{ if .Property }}
+
{{ else }}
- Handmade Network
+
{{ end }}
-
+ {{ end }}
+ {{ if .Title }}
+ {{ .Title }} | Handmade Network
+ {{ else }}
+ Handmade Network
+ {{ end }}
+
-
+
-
-
-
-
+
+
+
+
-
+ .win95-input {
+ border-width: 2px;
+ border-style: solid;
+ border-image: url('{{ dataimg "timemachine/win95-border-input.gif" }}') 4;
+ outline: none;
+ background-color: white !important;
+ resize: vertical; /* only applies to textareas so whatever */
+ }
+ .less-spacing p {
+ margin: 0.2rem 0;
+ }
+
-
-
- {{ template "header.html" . }}
-
-
-
- {{ block "content" . }}{{ end }}
-
-
-
- {{ template "footer.html" . }}
-
+
+
+ {{ template "header.html" . }}
+
+
+
+ {{ with .Breadcrumbs }}
+
+ {{ range $i, $e := . -}}
+ {{- if gt $i 0 -}}
+
»
+ {{- end -}}
+
{{ .Name }}
+ {{- end }}
+
+ {{ end }}
+
+ {{ block "content" . }}{{ end }}
+
+
+ {{ template "footer.html" . }}
+
+
+
+
+{{ define "frame title" }}
+
+ {{ . }}
+
+
+{{ end }}
diff --git a/src/templates/src/timemachine.html b/src/templates/src/timemachine.html
index 34b8962..d128a1c 100644
--- a/src/templates/src/timemachine.html
+++ b/src/templates/src/timemachine.html
@@ -1,12 +1,5 @@
{{ template "timemachine_base.html" . }}
-{{ define "frame title" }}
-
- {{ . }}
-
-
-{{ end }}
-
{{ define "content" }}
@@ -77,7 +70,7 @@
@@ -92,66 +85,22 @@
- 1 video has been submitted! Would you like to see it?
+ {{ if eq .NumSubmissions 1 }}
+ {{ .NumSubmissions }} video has been submitted! Would you like to see it?
+ {{ else }}
+ {{ .NumSubmissions }} videos have been submitted! Would you like to see them?
+ {{ end }}
-
- {{ template "frame title" "2009 iPod Touch" }}
-
-
-
-
-
-
Device: iPod Touch 3rd gen, model MC008LL
-
Submitted by: Ben Visness
-
Release year: 2009
-
Processor: 600MHz Samsung S5L8922, single-core
-
Memory: 256MB LPDDR2 @ 200 MHz
-
Operating system: iOS 5
-
-
-
-
- This is the iPod Touch I got when I was 13. It was my first major
- tech purchase and an early device in the iOS lineup. When I
- purchased this I think it was running iOS 3; at this point it has
- iOS 5. I was pleased to see that the battery still holds a charge
- quite well, and it consistently runs at about 30 to 60 frames per
- second.
-
-
- In the video you can see several built-in apps. Media playback
- still works great, and scrubbing around in songs is instantaneous.
- App switching works well. The calculator launches instantly (as
- you would hope). I was shocked to see that the old Google Maps app
- still works - apparently they have kept their old tile-based map
- servers online. It even gave me public transit directions.
-
-
- Overall, I would say this device feels only a hair slower than my
- current iPhone.
-
-
-
-
+
+ {{ template "timemachine_submission.html" .FeaturedSubmission }}
diff --git a/src/templates/src/timemachine_submissions.html b/src/templates/src/timemachine_submissions.html
new file mode 100644
index 0000000..041ab62
--- /dev/null
+++ b/src/templates/src/timemachine_submissions.html
@@ -0,0 +1,36 @@
+{{ template "timemachine_base.html" . }}
+
+{{ define "content" }}
+
+
+
+
+ {{ template "frame title" "About This Page" }}
+
+
+
+
+
+
+ The community has submitted the following
+ {{ with len .Submissions }}
+ {{ if eq . 1 }}video{{ else }}{{ . }} videos{{ end }}
+ {{ end }}
+ to the Time Machine project. If you have access to any older devices, you can participate too!
+
+
+
+
+
+
+
+
+ {{ range .Submissions }}
+ {{ template "timemachine_submission.html" . }}
+ {{ end }}
+
+
+
+{{ end }}
diff --git a/src/website/routes.go b/src/website/routes.go
index ee00a4f..966d4f2 100644
--- a/src/website/routes.go
+++ b/src/website/routes.go
@@ -71,6 +71,7 @@ func NewWebsiteRoutes(conn *pgxpool.Pool) http.Handler {
hmnOnly.GET(hmnurl.RegexJamRecap2023_Visibility, JamRecap2023_Visibility)
hmnOnly.GET(hmnurl.RegexTimeMachine, TimeMachine)
+ hmnOnly.GET(hmnurl.RegexTimeMachineSubmissions, TimeMachineSubmissions)
hmnOnly.GET(hmnurl.RegexTimeMachineForm, needsAuth(TimeMachineForm))
hmnOnly.GET(hmnurl.RegexTimeMachineFormDone, needsAuth(TimeMachineFormDone))
hmnOnly.POST(hmnurl.RegexTimeMachineForm, needsAuth(csrfMiddleware(TimeMachineFormSubmit)))
diff --git a/src/website/time_machine.go b/src/website/time_machine.go
index f8031f0..74fa354 100644
--- a/src/website/time_machine.go
+++ b/src/website/time_machine.go
@@ -1,6 +1,7 @@
package website
import (
+ "html/template"
"net/http"
"strings"
@@ -11,7 +12,46 @@ import (
)
func TimeMachine(c *RequestContext) ResponseData {
- baseData := getBaseDataAutocrumb(c, "Time Machine")
+ baseData := getBaseData(c, "Time Machine", nil)
+ baseData.OpenGraphItems = []templates.OpenGraphItem{
+ {Property: "og:title", Value: "Time Machine"},
+ {Property: "og:site_name", Value: "Handmade Network"},
+ {Property: "og:type", Value: "website"},
+ {Property: "og:image", Value: hmnurl.BuildPublic("timemachine/opengraph.png", true)},
+ {Property: "og:description", Value: "This summer, dig out your old devices and see what they were actually like to use."},
+ {Property: "og:url", Value: hmnurl.BuildTimeMachine()},
+ {Name: "twitter:card", Value: "summary_large_image"},
+ {Name: "twitter:image", Value: hmnurl.BuildPublic("timemachine/twittercard.png", true)},
+ }
+
+ featured := tmSubmissions[0]
+ featured.Title = "Latest Submission"
+
+ type TemplateData struct {
+ templates.BaseData
+ SubmitUrl string
+ SubmissionsUrl string
+ NumSubmissions int
+ FeaturedSubmission TimeMachineSubmission
+ }
+ tmpl := TemplateData{
+ BaseData: baseData,
+ SubmitUrl: hmnurl.BuildTimeMachineForm(),
+ SubmissionsUrl: hmnurl.BuildTimeMachineSubmissions(),
+ NumSubmissions: len(tmSubmissions),
+ FeaturedSubmission: featured,
+ }
+
+ var res ResponseData
+ res.MustWriteTemplate("timemachine.html", tmpl, c.Perf)
+ return res
+}
+
+func TimeMachineSubmissions(c *RequestContext) ResponseData {
+ baseData := getBaseData(c, "Time Machine - Submissions", []templates.Breadcrumb{
+ {"Time Machine", hmnurl.BuildTimeMachine()},
+ {"Submissions", hmnurl.BuildTimeMachineSubmissions()},
+ })
baseData.OpenGraphItems = []templates.OpenGraphItem{
{Property: "og:title", Value: "Time Machine"},
{Property: "og:site_name", Value: "Handmade Network"},
@@ -25,15 +65,19 @@ func TimeMachine(c *RequestContext) ResponseData {
type TemplateData struct {
templates.BaseData
- SubmitUrl string
+ MainUrl string
+ SubmitUrl string
+ Submissions []TimeMachineSubmission
}
tmpl := TemplateData{
- BaseData: baseData,
- SubmitUrl: hmnurl.BuildTimeMachineForm(),
+ BaseData: baseData,
+ MainUrl: hmnurl.BuildTimeMachine(),
+ SubmitUrl: hmnurl.BuildTimeMachineForm(),
+ Submissions: tmSubmissions,
}
var res ResponseData
- res.MustWriteTemplate("timemachine.html", tmpl, c.Perf)
+ res.MustWriteTemplate("timemachine_submissions.html", tmpl, c.Perf)
return res
}
@@ -94,3 +138,53 @@ func TimeMachineFormDone(c *RequestContext) ResponseData {
)
return res
}
+
+type TimeMachineSubmission struct {
+ Title string
+ Url string
+ Thumbnail string
+ Details []TimeMachineSubmissionDetail
+ Description template.HTML
+}
+
+type TimeMachineSubmissionDetail struct {
+ Name string
+ Content template.HTML
+}
+
+var tmSubmissions = []TimeMachineSubmission{
+ {
+ Title: "2009 iPod Touch",
+ Url: "https://youtu.be/2eBFk1yV6mE",
+ Thumbnail: "timemachine/ipodtouch-dither.gif",
+ Details: []TimeMachineSubmissionDetail{
+ {"Device", "iPod Touch 3rd gen, model MC008LL"},
+ {"Submitted by", "Ben Visness"},
+ {"Release year", "2009"},
+ {"Processor", "600MHz Samsung S5L8922, single-core"},
+ {"Memory", "256MB LPDDR2 @ 200 MHz"},
+ {"Operating system", "iOS 5"},
+ },
+ Description: `
+
+ This is the iPod Touch I got when I was 13. It was my first major
+ tech purchase and an early device in the iOS lineup. When I
+ purchased this I think it was running iOS 3; at this point it has
+ iOS 5. I was pleased to see that the battery still holds a charge
+ quite well, and it consistently runs at about 30 to 60 frames per
+ second.
+
+
+ In the video you can see several built-in apps. Media playback
+ still works great, and scrubbing around in songs is instantaneous.
+ App switching works well. The calculator launches instantly (as
+ you would hope). I was shocked to see that the old Google Maps app
+ still works - apparently they have kept their old tile-based map
+ servers online. It even gave me public transit directions.
+
+
+ Overall, I would say this device feels only a hair slower than my
+ current iPhone.
+
`,
+ },
+}