aboutsummaryrefslogtreecommitdiff
path: root/renderer
diff options
context:
space:
mode:
authorr <r@freesoftwareextremist.com>2019-12-13 18:08:26 +0000
committerr <r@freesoftwareextremist.com>2019-12-13 18:26:24 +0000
commit5e4da01c3ae3ae2e870faba9085d9d9213c01c29 (patch)
tree39d6f1e76b901549f194ddbac3c6cb82e0abd019 /renderer
downloadbloat-5e4da01c3ae3ae2e870faba9085d9d9213c01c29.tar.gz
bloat-5e4da01c3ae3ae2e870faba9085d9d9213c01c29.zip
Initial commit
Diffstat (limited to 'renderer')
-rw-r--r--renderer/model.go40
-rw-r--r--renderer/renderer.go112
2 files changed, 152 insertions, 0 deletions
diff --git a/renderer/model.go b/renderer/model.go
new file mode 100644
index 0000000..ddc9e2d
--- /dev/null
+++ b/renderer/model.go
@@ -0,0 +1,40 @@
+package renderer
+
+import (
+ "mastodon"
+)
+
+type TimelinePageTemplateData struct {
+ Statuses []*mastodon.Status
+ HasNext bool
+ NextLink string
+ HasPrev bool
+ PrevLink string
+}
+
+func NewTimelinePageTemplateData(statuses []*mastodon.Status, hasNext bool, nextLink string, hasPrev bool,
+ prevLink string) *TimelinePageTemplateData {
+ return &TimelinePageTemplateData{
+ Statuses: statuses,
+ HasNext: hasNext,
+ NextLink: nextLink,
+ HasPrev: hasPrev,
+ PrevLink: prevLink,
+ }
+}
+
+type ThreadPageTemplateData struct {
+ Status *mastodon.Status
+ Context *mastodon.Context
+ PostReply bool
+ ReplyToID string
+}
+
+func NewThreadPageTemplateData(status *mastodon.Status, context *mastodon.Context, postReply bool, replyToID string) *ThreadPageTemplateData {
+ return &ThreadPageTemplateData{
+ Status: status,
+ Context: context,
+ PostReply: postReply,
+ ReplyToID: replyToID,
+ }
+}
diff --git a/renderer/renderer.go b/renderer/renderer.go
new file mode 100644
index 0000000..c3d3526
--- /dev/null
+++ b/renderer/renderer.go
@@ -0,0 +1,112 @@
+package renderer
+
+import (
+ "context"
+ "io"
+ "strconv"
+ "strings"
+ "text/template"
+ "time"
+
+ "mastodon"
+)
+
+type Renderer interface {
+ RenderErrorPage(ctx context.Context, writer io.Writer, err error)
+ RenderHomePage(ctx context.Context, writer io.Writer) (err error)
+ RenderSigninPage(ctx context.Context, writer io.Writer) (err error)
+ RenderTimelinePage(ctx context.Context, writer io.Writer, data *TimelinePageTemplateData) (err error)
+ RenderThreadPage(ctx context.Context, writer io.Writer, data *ThreadPageTemplateData) (err error)
+}
+
+type renderer struct {
+ template *template.Template
+}
+
+func NewRenderer(templateGlobPattern string) (r *renderer, err error) {
+ t := template.New("default")
+ t, err = t.Funcs(template.FuncMap{
+ "WithEmojis": WithEmojis,
+ "DisplayInteractionCount": DisplayInteractionCount,
+ "TimeSince": TimeSince,
+ "FormatTimeRFC3339": FormatTimeRFC3339,
+ }).ParseGlob(templateGlobPattern)
+ if err != nil {
+ return
+ }
+ return &renderer{
+ template: t,
+ }, nil
+}
+
+func (r *renderer) RenderErrorPage(ctx context.Context, writer io.Writer, err error) {
+ r.template.ExecuteTemplate(writer, "error.tmpl", err)
+ return
+}
+
+func (r *renderer) RenderHomePage(ctx context.Context, writer io.Writer) (err error) {
+ return r.template.ExecuteTemplate(writer, "homepage.tmpl", nil)
+}
+
+func (r *renderer) RenderSigninPage(ctx context.Context, writer io.Writer) (err error) {
+ return r.template.ExecuteTemplate(writer, "signin.tmpl", nil)
+}
+
+func (r *renderer) RenderTimelinePage(ctx context.Context, writer io.Writer, data *TimelinePageTemplateData) (err error) {
+ return r.template.ExecuteTemplate(writer, "timeline.tmpl", data)
+}
+
+func (r *renderer) RenderThreadPage(ctx context.Context, writer io.Writer, data *ThreadPageTemplateData) (err error) {
+ return r.template.ExecuteTemplate(writer, "thread.tmpl", data)
+}
+
+func WithEmojis(content string, emojis []mastodon.Emoji) string {
+ var emojiNameContentPair []string
+ for _, e := range emojis {
+ emojiNameContentPair = append(emojiNameContentPair, ":"+e.ShortCode+":", "<img class=\"status-emoji\" src=\""+e.URL+"\" alt=\""+e.ShortCode+"\" />")
+ }
+ return strings.NewReplacer(emojiNameContentPair...).Replace(content)
+}
+
+func DisplayInteractionCount(c int64) string {
+ if c > 0 {
+ return strconv.Itoa(int(c))
+ }
+ return ""
+}
+
+func TimeSince(t time.Time) string {
+ dur := time.Since(t)
+
+ s := dur.Seconds()
+ if s < 60 {
+ return strconv.Itoa(int(s)) + "s"
+ }
+
+ m := dur.Minutes()
+ if m < 60 {
+ return strconv.Itoa(int(m)) + "m"
+ }
+
+ h := dur.Hours()
+ if h < 24 {
+ return strconv.Itoa(int(h)) + "h"
+ }
+
+ d := h / 24
+ if d < 30 {
+ return strconv.Itoa(int(d)) + "d"
+ }
+
+ mo := d / 30
+ if mo < 12 {
+ return strconv.Itoa(int(mo)) + "mo"
+ }
+
+ y := m / 12
+ return strconv.Itoa(int(y)) + "y"
+}
+
+func FormatTimeRFC3339(t time.Time) string {
+ return t.Format(time.RFC3339)
+}