Skip to content

Commit

Permalink
templates: rework the loader to be a function
Browse files Browse the repository at this point in the history
this makes the loading threadsafe by nature of it not sharing any state
between calls, other parts of the template reloading isn't thread-safe yet.

website: start implementing theme-supported SSE API; instead of sending
plain-text we send html appropriate for each client.
  • Loading branch information
Wessie committed Jan 26, 2024
1 parent 4e91d93 commit ad9157e
Show file tree
Hide file tree
Showing 8 changed files with 247 additions and 127 deletions.
9 changes: 5 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ require (
github.com/lrstanley/girc v0.0.0-20230911164840-f47717952bf9
github.com/olivere/elastic/v7 v7.0.32
github.com/tcolgate/mp3 v0.0.0-20170426193717-e79c5a46d300
golang.org/x/crypto v0.17.0
golang.org/x/crypto v0.18.0
google.golang.org/grpc v1.60.1
)

require (
github.com/golang/protobuf v1.5.3 // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect
golang.org/x/net v0.20.0 // indirect
golang.org/x/sys v0.16.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect
)
Expand All @@ -36,6 +37,6 @@ require (
github.com/mailru/easyjson v0.7.7 // indirect
github.com/pkg/errors v0.9.1 // indirect
go.uber.org/atomic v1.11.0 // indirect
golang.org/x/tools v0.16.0 // indirect
golang.org/x/tools v0.17.0 // indirect
google.golang.org/protobuf v1.32.0
)
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,26 @@ go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM=
golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 h1:AB/lmRny7e2pLhFEYIbl5qkDAUt2h0ZRO4wGPhZf+ik=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE=
Expand Down
87 changes: 48 additions & 39 deletions templates/default/home.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,7 @@
<button class="button is-fullwidth">More Options<span class="caret"></span></button>
</div>
</div>
<h2 id="current-song">
<p sse-swap="metadata" class="title is-2 has-text-centered" style="cursor: pointer;">{{.Status.Song.Metadata}}</p>
<p class="subtitle is-4 has-text-centered" style="font-size: 14px;">{{if .Status.Song.DatabaseTrack}}{{.Status.Song.Tags}}{{end}}</p>
</h2>
<progress id="current-song-progress" class="progress is-large" value="0" max="{{.Status.Song.Length.Seconds}}"></progress>
<div class="columns">
<div class="column is-6">
<p class="has-text-centered">Listeners: <span id="listener-count">{{.Status.Listeners}}</span></p>
</div>
<div class="column is-6">
<p class="has-text-centered"><span id="progress-current">00:00</span> / <span id="progress-max">00:00<span></p>
</div>
</div>
{{template "nowplaying" .Status}}
</div>
<div class="column is-3">
<div id="dj-image">
Expand All @@ -43,32 +31,8 @@
</div>
</div>
<div class="columns">
<div class="column is-6">
<p class="title is-4 has-text-centered">Last Played</p>
<div class="notification">
<ul>
{{range $song := .LastPlayed}}
<li class="columns is-mobile">
<span class="column is-4 has-text-left">{{Until $song.LastPlayed | PrettyDuration}}</span>
<span class="column is-8 has-text-centered">{{$song.Metadata}}</span>
</li>
{{end}}
</ul>
</div>
</div>
<div class="column is-6">
<p class="title is-4 has-text-centered">Queue</p>
<div class="notification">
<ul>
{{range $song := .Queue}}
<li class="columns is-mobile">
<span class="column is-8 has-text-centered">{{$song.Metadata}}</span>
<span class="column is-4 has-text-right">{{Until $song.ExpectedStartTime | PrettyDuration}}</span>
</li>
{{end}}
</ul>
</div>
</div>
{{template "lastplayed" .LastPlayed}}
{{template "queue" .Queue}}
</div>
<div class="columns">
<article class="column message is-small m-3 p-0">
Expand Down Expand Up @@ -99,4 +63,49 @@
</div>
</section>
Home {{printjson .}}
{{end}}
{{define "nowplaying"}}
<h2 id="current-song">
<p sse-swap="metadata" class="title is-2 has-text-centered" style="cursor: pointer;">{{.Song.Metadata}}</p>
<p class="subtitle is-4 has-text-centered" style="font-size: 14px;">{{if .Song.DatabaseTrack}}{{.Song.Tags}}{{end}}</p>
</h2>
<progress id="current-song-progress" class="progress is-large" value="0" max="{{.Song.Length.Seconds}}"></progress>
<div class="columns">
<div class="column is-6">
<p class="has-text-centered">Listeners: <span id="listener-count">{{.Listeners}}</span></p>
</div>
<div class="column is-6">
<p class="has-text-centered"><span id="progress-current">00:00</span> / <span id="progress-max">00:00<span></p>
</div>
</div>
{{end}}
{{define "lastplayed"}}
<div class="column is-6">
<p class="title is-4 has-text-centered">Last Played</p>
<div class="notification">
<ul id="lastplayed">
{{range $song := .}}
<li class="lp-item columns is-mobile">
<time datetime="{{$song.LastPlayed.Unix}}" class="lp-time column is-4 has-text-left">{{Until $song.LastPlayed | PrettyDuration}}</time>
<span class="lp-meta column is-8 has-text-centered">{{$song.Metadata}}</span>
</li>
{{end}}
</ul>
</div>
</div>
{{end}}
{{define "queue"}}
<div class="column is-6">
<p class="title is-4 has-text-centered">Queue</p>
<div class="notification">
<ul>
{{range $song := .}}
<li class="columns is-mobile">
<span class="column is-8 has-text-centered">{{$song.Metadata}}</span>
<time datetime="{{$song.ExpectedStartTime.Unix}}" class="column is-4 has-text-right">{{Until $song.ExpectedStartTime | PrettyDuration}}</time>
</li>
{{end}}
</ul>
</div>
</div>
{{end}}
37 changes: 33 additions & 4 deletions templates/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,21 @@ package templates
import (
"bytes"
"io"
"slices"

"github.com/R-a-dio/valkyrie/errors"
"github.com/R-a-dio/valkyrie/util/pool"
)

var bufferPool = pool.NewResetPool(func() *bytes.Buffer { return new(bytes.Buffer) })

type Executor struct {
site *Site
pool *pool.ResetPool[*bytes.Buffer]
}

func NewExecutor(site *Site) *Executor {
return &Executor{
site: site,
pool: pool.NewResetPool(func() *bytes.Buffer { return new(bytes.Buffer) }),
}
}

Expand All @@ -40,6 +41,8 @@ func (e *Executor) ExecutePartial(theme, page string, output io.Writer, input an
return nil
}

// ExecuteTemplate selects a theme, page and template and feeds it the input given and writing the template output
// to the output writer. Output is buffered until template execution is done before writing to output.
func (e *Executor) ExecuteTemplate(theme, page string, template string, output io.Writer, input any) error {
const op errors.Op = "templates/Executor.ExecuteTemplate"

Expand All @@ -48,8 +51,8 @@ func (e *Executor) ExecuteTemplate(theme, page string, template string, output i
return errors.E(op, err)
}

b := e.pool.Get()
defer e.pool.Put(b)
b := bufferPool.Get()
defer bufferPool.Put(b)

err = tmpl.ExecuteTemplate(b, template, input)
if err != nil {
Expand All @@ -62,3 +65,29 @@ func (e *Executor) ExecuteTemplate(theme, page string, template string, output i
}
return nil
}

// ExecuteTemplateAll executes the template given feeding the input given for all known themes
func (e *Executor) ExecuteTemplateAll(template string, input any) (map[string][]byte, error) {
const op errors.Op = "templates/Executor.ExecuteTemplateAll"

var out = make(map[string][]byte)

b := bufferPool.Get()
defer bufferPool.Put(b)

for _, theme := range e.site.ThemeNames() {
tmpl, err := e.site.Template(theme, "home")
if err != nil {
return nil, errors.E(op, err)
}

err = tmpl.ExecuteTemplate(b, template, input)
if err != nil {
return nil, errors.E(op, err)
}

out[theme] = slices.Clone(b.Bytes())
b.Reset()
}
return out, nil
}
Loading

0 comments on commit ad9157e

Please sign in to comment.