Remove light/dark theme settings entirely

There is simply no need any more; system light/dark preferences handle this fine.
This commit is contained in:
Ben Visness 2024-06-17 21:30:37 -05:00
parent d9073db5d0
commit 04bc4e5035
29 changed files with 220 additions and 174 deletions

View File

@ -0,0 +1,47 @@
package migrations
import (
"context"
"time"
"git.handmade.network/hmn/hmn/src/migration/types"
"github.com/jackc/pgx/v5"
)
func init() {
registerMigration(RemoveDarkTheme{})
}
type RemoveDarkTheme struct{}
func (m RemoveDarkTheme) Version() types.MigrationVersion {
return types.MigrationVersion(time.Date(2024, 6, 18, 2, 25, 36, 0, time.UTC))
}
func (m RemoveDarkTheme) Name() string {
return "RemoveDarkTheme"
}
func (m RemoveDarkTheme) Description() string {
return "Remove the darktheme field from users"
}
func (m RemoveDarkTheme) Up(ctx context.Context, tx pgx.Tx) error {
_, err := tx.Exec(ctx,
`
ALTER TABLE hmn_user
DROP COLUMN darktheme;
`,
)
return err
}
func (m RemoveDarkTheme) Down(ctx context.Context, tx pgx.Tx) error {
_, err := tx.Exec(ctx,
`
ALTER TABLE hmn_user
ADD COLUMN darktheme BOOLEAN NOT NULL DEFAULT FALSE;
`,
)
return err
}

View File

@ -38,7 +38,6 @@ type User struct {
Signature string `db:"signature"` Signature string `db:"signature"`
AvatarAssetID *uuid.UUID `db:"avatar_asset_id"` AvatarAssetID *uuid.UUID `db:"avatar_asset_id"`
DarkTheme bool `db:"darktheme"`
Timezone string `db:"timezone"` Timezone string `db:"timezone"`
ShowEmail bool `db:"showemail"` ShowEmail bool `db:"showemail"`

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -14,7 +14,7 @@ import (
"git.handmade.network/hmn/hmn/src/models" "git.handmade.network/hmn/hmn/src/models"
) )
func PostToTemplate(p *models.Post, author *models.User, currentTheme string) Post { func PostToTemplate(p *models.Post, author *models.User) Post {
return Post{ return Post{
ID: p.ID, ID: p.ID,
@ -23,7 +23,7 @@ func PostToTemplate(p *models.Post, author *models.User, currentTheme string) Po
Preview: p.Preview, Preview: p.Preview,
ReadOnly: p.ReadOnly, ReadOnly: p.ReadOnly,
Author: UserToTemplate(author, currentTheme), Author: UserToTemplate(author),
// No content. A lot of the time we don't have this handy and don't need it. See AddContentVersion. // No content. A lot of the time we don't have this handy and don't need it. See AddContentVersion.
PostDate: p.PostDate, PostDate: p.PostDate,
} }
@ -34,7 +34,7 @@ func (p *Post) AddContentVersion(ver models.PostVersion, editor *models.User) {
p.IP = maybeIp(ver.IP) p.IP = maybeIp(ver.IP)
if editor != nil { if editor != nil {
editorTmpl := UserToTemplate(editor, "theme not required here") editorTmpl := UserToTemplate(editor)
p.Editor = &editorTmpl p.Editor = &editorTmpl
p.EditDate = ver.Date p.EditDate = ver.Date
p.EditReason = ver.EditReason p.EditReason = ver.EditReason
@ -61,15 +61,13 @@ var LifecycleBadgeStrings = map[models.ProjectLifecycle]string{
models.ProjectLifecycleLTS: "Complete", models.ProjectLifecycleLTS: "Complete",
} }
func ProjectLogoUrl(p *models.Project, lightAsset *models.Asset, darkAsset *models.Asset, theme string) string { // TODO(redesign): Remove one or the other of these from the database entirely.
if theme == "dark" { func ProjectLogoUrl(p *models.Project, lightAsset *models.Asset, darkAsset *models.Asset) string {
if darkAsset != nil {
return hmnurl.BuildS3Asset(darkAsset.S3Key)
}
} else {
if lightAsset != nil { if lightAsset != nil {
return hmnurl.BuildS3Asset(lightAsset.S3Key) return hmnurl.BuildS3Asset(lightAsset.S3Key)
} }
if darkAsset != nil {
return hmnurl.BuildS3Asset(darkAsset.S3Key)
} }
return "" return ""
} }
@ -100,11 +98,11 @@ func ProjectToTemplate(
} }
} }
func ProjectAndStuffToTemplate(p *hmndata.ProjectAndStuff, url string, theme string) Project { func ProjectAndStuffToTemplate(p *hmndata.ProjectAndStuff, url string) Project {
res := ProjectToTemplate(&p.Project, url) res := ProjectToTemplate(&p.Project, url)
res.Logo = ProjectLogoUrl(&p.Project, p.LogoLightAsset, p.LogoDarkAsset, theme) res.Logo = ProjectLogoUrl(&p.Project, p.LogoLightAsset, p.LogoDarkAsset)
for _, o := range p.Owners { for _, o := range p.Owners {
res.Owners = append(res.Owners, UserToTemplate(o, theme)) res.Owners = append(res.Owners, UserToTemplate(o))
} }
if p.HeaderImage != nil { if p.HeaderImage != nil {
res.HeaderImage = hmnurl.BuildS3Asset(p.HeaderImage.S3Key) res.HeaderImage = hmnurl.BuildS3Asset(p.HeaderImage.S3Key)
@ -133,11 +131,10 @@ func ProjectToProjectSettings(
owners []*models.User, owners []*models.User,
tag string, tag string,
lightLogo, darkLogo, headerImage *models.Asset, lightLogo, darkLogo, headerImage *models.Asset,
currentTheme string,
) ProjectSettings { ) ProjectSettings {
ownerUsers := make([]User, 0, len(owners)) ownerUsers := make([]User, 0, len(owners))
for _, owner := range owners { for _, owner := range owners {
ownerUsers = append(ownerUsers, UserToTemplate(owner, currentTheme)) ownerUsers = append(ownerUsers, UserToTemplate(owner))
} }
return ProjectSettings{ return ProjectSettings{
Name: p.Name, Name: p.Name,
@ -187,28 +184,23 @@ func ThreadToTemplate(t *models.Thread) Thread {
} }
} }
func UserAvatarDefaultUrl(currentTheme string) string { func UserAvatarDefaultUrl(theme string) string {
return hmnurl.BuildTheme("empty-avatar.svg", currentTheme, true) return hmnurl.BuildTheme("empty-avatar.svg", theme, true)
} }
func UserAvatarUrl(u *models.User, currentTheme string) string { func UserAvatarUrl(u *models.User) string {
if currentTheme == "" {
currentTheme = "light"
}
avatar := "" avatar := ""
if u != nil && u.AvatarAsset != nil { if u != nil && u.AvatarAsset != nil {
avatar = hmnurl.BuildS3Asset(u.AvatarAsset.S3Key) avatar = hmnurl.BuildS3Asset(u.AvatarAsset.S3Key)
} else {
avatar = UserAvatarDefaultUrl(currentTheme)
} }
return avatar return avatar
} }
func UserToTemplate(u *models.User, currentTheme string) User { func UserToTemplate(u *models.User) User {
if u == nil { if u == nil {
return User{ return User{
Name: "Deleted user", Name: "Deleted user",
AvatarUrl: UserAvatarUrl(nil, currentTheme), AvatarUrl: UserAvatarUrl(nil),
} }
} }
@ -231,9 +223,8 @@ func UserToTemplate(u *models.User, currentTheme string) User {
Signature: u.Signature, Signature: u.Signature,
DateJoined: u.DateJoined, DateJoined: u.DateJoined,
ProfileUrl: hmnurl.BuildUserProfile(u.Username), ProfileUrl: hmnurl.BuildUserProfile(u.Username),
AvatarUrl: UserAvatarUrl(u, currentTheme), AvatarUrl: UserAvatarUrl(u),
DarkTheme: u.DarkTheme,
Timezone: u.Timezone, Timezone: u.Timezone,
DiscordSaveShowcase: u.DiscordSaveShowcase, DiscordSaveShowcase: u.DiscordSaveShowcase,
@ -246,7 +237,7 @@ func UserToTemplate(u *models.User, currentTheme string) User {
var UnknownUser = User{ var UnknownUser = User{
Name: "Unknown User", Name: "Unknown User",
AvatarUrl: UserAvatarUrl(nil, ""), AvatarUrl: UserAvatarUrl(nil),
} }
// An online site/service for which we recognize the link // An online site/service for which we recognize the link

View File

@ -1,7 +1,9 @@
{{ template "base.html" . }} {{ template "base.html" . }}
{{ define "extrahead" }} {{ define "extrahead" }}
<link rel="stylesheet" href="{{ static (eq .Theme "dark" | ternary "fishbowl-dark.css" "fishbowl-light.css") }}"> <!-- TODO(redesign): Adapt these stylesheets to use media queries and variables -->
<link rel="stylesheet" href="fishbowl-dark.css">
<!-- <link rel="stylesheet" href="fishbowl-light.css"> -->
<script> <script>
function scrollToMessage(event, id) { function scrollToMessage(event, id) {
@ -40,15 +42,20 @@
<style> <style>
.fishbowl-banner { .fishbowl-banner {
background-color: {{ eq .Theme "dark" | ternary "#254464" "#a0c8f2" }}; /* TODO(redesign) */
background-image: url({{ static (eq .Theme "dark" | ternary "waterline-dark.svg" "waterline-light.svg") }}); background-color: #254464;
/* background-color: #a0c8f2; */
background-image: url({{ static "waterline-dark.svg" }});
/* background-image: url({{ static "waterline-light.svg" }}); */
background-size: 734px 30px; background-size: 734px 30px;
background-repeat: repeat-x; background-repeat: repeat-x;
padding-top: 30px; padding-top: 30px;
} }
.fishbowl-banner a { .fishbowl-banner a {
color: {{ eq .Theme "dark" | ternary "#9ad0ff" "#1f4f99" }}; /* TODO(redesign) */
color: #9ad0ff;
/* color: #1f4f99; */
} }
.fishbowl .chatlog__author a { .fishbowl .chatlog__author a {

View File

@ -0,0 +1,48 @@
<script src="{{ static "js/showcase.js" }}"></script>
<template id="showcase_item">
<div data-tmpl="container" class="showcase-item ba b--theme flex-shrink-0 bg-dark-gray hide-child relative overflow-hidden pointer">
<div data-tmpl="thumbnail" class="absolute absolute--fill z-0 flex justify-start items-center bg-left cover"></div>
<div class="overlay absolute absolute--fill z-1 child">
<div class="gradient relative">
<div class="user-info flex pa2 white f7 lh-title items-center">
<div data-tmpl="avatar" class="br-100 w2 h2 cover flex-shrink-0"></div>
<div class="flex-grow-1 flex flex-column pl1">
<div data-tmpl="username">Unknown User</div>
<div data-tmpl="when" class="i f8">Unknown Time</div>
</div>
</div>
</div>
</div>
</div>
</template>
<template id="timeline_modal">
<div data-tmpl="overlay" class="timeline-modal fixed absolute--fill bg-black-80 z-999 flex flex-column justify-center items-center">
<div data-tmpl="container" class="container timeline-item relative flex-shrink-0 shadow-1 flex flex-column items-stretch w-100 mh0 mh3-ns br2-ns overflow-hidden">
<div data-tmpl="asset_container" class="bg-dark-gray flex justify-center"></div>
<div class="bg--content pa3 overflow-y-auto">
<div class="timeline-user-info mb2 flex items-center">
<img class="avatar lite mr2" data-tmpl="avatar"/>
<a class="user" data-tmpl="userLink"></a>
<a data-tmpl="date" class="datetime tr" style="flex: 1 1 auto;"></a>
</div>
<div class="overflow-auto" data-tmpl="description">
Unknown description
</div>
<div data-tmpl="projects" class="pt2 flex g2"></div>
<div class="i f7 pt2">
<a data-tmpl="discord_link" target="_blank">View original message on Discord</a>
</div>
</div>
<div data-tmpl="close" class="absolute right-0 top-0 w2 h2 flex justify-center items-center bg-black-80 white br-100 ma1 pointer svgicon svgicon-nofix">{{ svg "close" }}</div>
</div>
</div>
</template>
<template id="project_link">
<a data-tmpl="root" class="snippet-project flex flex-row items-center bg-theme-dimmer ph2 pv1 br2">
<img data-tmpl="logo" class="db mr1 br1 h1-5" />
<div data-tmpl="name"></div>
</a>
</template>

View File

@ -22,26 +22,6 @@
<link href='https://fonts.googleapis.com/css?family=Fira+Mono:300,400,500,700' rel='stylesheet' type='text/css'> <link href='https://fonts.googleapis.com/css?family=Fira+Mono:300,400,500,700' rel='stylesheet' type='text/css'>
<link rel="stylesheet" type="text/css" href="{{ static "style.css" }}" /> <link rel="stylesheet" type="text/css" href="{{ static "style.css" }}" />
{{/* TODO: These are the base64 encodings of bglight.png and bgdark.png. Rather than manually putting the encoding here, it would be nice to automatically calculate it when the server starts up and pass it in. */}}
{{ $bglight := "iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAEGGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iCiAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIKICAgZXhpZjpQaXhlbFhEaW1lbnNpb249IjcyIgogICBleGlmOlBpeGVsWURpbWVuc2lvbj0iNzIiCiAgIHRpZmY6SW1hZ2VXaWR0aD0iNzIiCiAgIHRpZmY6SW1hZ2VMZW5ndGg9IjcyIgogICB0aWZmOlJlc29sdXRpb25Vbml0PSIyIgogICB0aWZmOlhSZXNvbHV0aW9uPSI5Ni4wIgogICB0aWZmOllSZXNvbHV0aW9uPSI5Ni4wIgogICB4bXA6TW9kaWZ5RGF0ZT0iMjAyMS0wMy0xMVQyMToyMjozMC0wNjowMCIKICAgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMS0wMy0xMVQyMToyMjozMC0wNjowMCI+CiAgIDx4bXBNTTpIaXN0b3J5PgogICAgPHJkZjpTZXE+CiAgICAgPHJkZjpsaQogICAgICBzdEV2dDphY3Rpb249InByb2R1Y2VkIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZmZpbml0eSBQaG90byAxLjcuMSIKICAgICAgc3RFdnQ6d2hlbj0iMjAyMS0wMy0xMVQyMToyMjozMC0wNjowMCIvPgogICAgPC9yZGY6U2VxPgogICA8L3htcE1NOkhpc3Rvcnk+CiAgPC9yZGY6RGVzY3JpcHRpb24+CiA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJyIj8+NRFFrAAAAYFpQ0NQc1JHQiBJRUM2MTk2Ni0yLjEAACiRdZG/S0JRFMc/amGUYZBDQ4NENVmUgdTSoJQF1WAG/Vr05Y9A7fGeEdIatAoFUUu/hvoLag2ag6AogmgLmotaSl7n+QQl8l7OOZ/7vfcc7j0X7NGMktUbBiCby2uRcNA7v7Dodb7iwCXmwRNTdHV6djxK3fH1gM2Md31mrfrn/h0tKwldAVuT8KiiannhCeGpjbxq8q6wR0nHVoTPhX2aXFD43tTjFr+ZnLL4x2QtGgmBvU3Ym6rheA0raS0rLC+nO5tZVyr3MV/iSuTmZiV2iXWiEyFMEC+TjBEiwCAj4gP04adfVtTJHyjnz7AmuYp4lQIaq6RIk8cn6rpUT0hMip6QmaFg9v9vX/XkkN+q7gpC44thfPSAcwdKRcP4PjaM0gk4nuEqV81fO4LhT9GLVa37ENxbcHFd1eJ7cLkNHU9qTIuVJYeYPZmE9zNoXYD2W2hesnpW2ef0EaKb8lU3sH8AvXLevfwLEU5nv19tQRgAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAJOSURBVHic7ZtRksMgCIaTPOcI3v9MPYBHyHv2obOZTlIVFeSHyltnm38QCehXdo0xnkulHcex7Pue/OxJZ20JUE7Um86W+wKHM1w6IYRVw59sBqHtagihO+Nr/Xlk0GeE930nRTzlBIfOZ+bEGE9KJnH68wjQ/eHWxXHp3IPSGqRWf64A5R6uWRyXTi4oNUHq9ecKUOlh6uK4dEpBoQap159H0UM7m9wLc2uhbvVn1qCCJXdjtvi3JQ+K1AiXdpOqU/oONXNKOrX+dO2K1q6O1Nl6DnD34tnrzP9nJJ3NYmcZqfP1oJizUnBqDnC5RdUcTCV1tm9/TBklOJRMoiyK4s8InfX1ep3zNUvrzBpU0Olu095bfRdRpATHOpk0RRQ1ri3wRFGbTMLf5rWpACxRRCGTsEQRhUzCE0VtMjlrUMHMEEUtMtlNFLkJnrROLZnsuiagZQcUUUQngapEEa1DQRFFKySQS6eKKFoigVw6zUTRwuuhRhTRFwVFFJFbNIdO8qCoNROIppPNIO+8mWKPDNKeCUTTeQRIex4HTecKEMpMIJrOFSCUmUA0nUcR/qVfTSk6swYVLJkds8W/LXlQ1JoJ7NXhnpl0RRQlst4NUZSamXRxm5fsvOaJovTMpGmiOGJm0g1RlHrNZg0q+OOOKHK3evH/eh5JJiVmJofMKFq+tojNKHohk2LzQV6oAPuMojcyyT6j6I1Mis0oeiGTswYVTHxG0XKLX5YBM4pWyaRLoiih44YoSum4uM1L6pgnitI6poniCB03RFFK5w8yFS9yPecAUAAAAABJRU5ErkJggg==" }}
{{ $bgdark := "iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAEGGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iCiAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIKICAgZXhpZjpQaXhlbFhEaW1lbnNpb249IjcyIgogICBleGlmOlBpeGVsWURpbWVuc2lvbj0iNzIiCiAgIHRpZmY6SW1hZ2VXaWR0aD0iNzIiCiAgIHRpZmY6SW1hZ2VMZW5ndGg9IjcyIgogICB0aWZmOlJlc29sdXRpb25Vbml0PSIyIgogICB0aWZmOlhSZXNvbHV0aW9uPSI5Ni4wIgogICB0aWZmOllSZXNvbHV0aW9uPSI5Ni4wIgogICB4bXA6TW9kaWZ5RGF0ZT0iMjAyMS0wMy0xMVQyMToyMzoxNS0wNjowMCIKICAgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMS0wMy0xMVQyMToyMzoxNS0wNjowMCI+CiAgIDx4bXBNTTpIaXN0b3J5PgogICAgPHJkZjpTZXE+CiAgICAgPHJkZjpsaQogICAgICBzdEV2dDphY3Rpb249InByb2R1Y2VkIgogICAgICBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZmZpbml0eSBQaG90byAxLjcuMSIKICAgICAgc3RFdnQ6d2hlbj0iMjAyMS0wMy0xMVQyMToyMzoxNS0wNjowMCIvPgogICAgPC9yZGY6U2VxPgogICA8L3htcE1NOkhpc3Rvcnk+CiAgPC9yZGY6RGVzY3JpcHRpb24+CiA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJyIj8+87tjqAAAAYFpQ0NQc1JHQiBJRUM2MTk2Ni0yLjEAACiRdZG/S0JRFMc/amGUYZBDQ4NENVmUgdTSoJQF1WAG/Vr05Y9A7fGeEdIatAoFUUu/hvoLag2ag6AogmgLmotaSl7n+QQl8l7OOZ/7vfcc7j0X7NGMktUbBiCby2uRcNA7v7Dodb7iwCXmwRNTdHV6djxK3fH1gM2Md31mrfrn/h0tKwldAVuT8KiiannhCeGpjbxq8q6wR0nHVoTPhX2aXFD43tTjFr+ZnLL4x2QtGgmBvU3Ym6rheA0raS0rLC+nO5tZVyr3MV/iSuTmZiV2iXWiEyFMEC+TjBEiwCAj4gP04adfVtTJHyjnz7AmuYp4lQIaq6RIk8cn6rpUT0hMip6QmaFg9v9vX/XkkN+q7gpC44thfPSAcwdKRcP4PjaM0gk4nuEqV81fO4LhT9GLVa37ENxbcHFd1eJ7cLkNHU9qTIuVJYeYPZmE9zNoXYD2W2hesnpW2ef0EaKb8lU3sH8AvXLevfwLEU5nv19tQRgAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAJSSURBVHic7ZvBbsMgDIaTHKbtnNO0vf/bcW7VS3uoFlWhgAEb//bwrVrzyxjHhq/euu/7fam0z4+v5Xq7JD970llbApQT9aaz5b7A4QyXTghh1fAnm0FouxpC6M74Wn+iDHqN8PV2IUU85QSHzmvm7Pt+p2QSpz9RgM4Pty6OS+cclNYgtfpzBCj3cM3iuHRyQakJUq8/R4BKD1MXx6VTCgo1SL3+REUP7WxyLsythbrVn1mDCpbcjdnin5Y8KFIjXNpNqk7pO9TMKenU+tO1K1q7OlJn6znAnYtnrzN/n5F0NoudZaTO24NizkrBqTnA5RZVczCV1Nne/TFllOBQMomyKIo/I3TWn+/f+3zN0jqzBhV0utu091bfRRQpwbFOJk0RRY1rCzxR1CaT8Ld5bSoASxRRyCQsUUQhk/BEUZtMzhpUMDNEUYtMdhNFboInrVNLJruuCWjZAUUU0UmgKlFE61BQRNEKCeTSqSKKlkggl04zUbTweqgRRfRFQRFF5BbNoZM8KGrNBKLpZDPIO2+mWJRB2jOBaDpRgLTncdB0jgChzASi6RwBQpkJRNOJivB/+tWUojNrUMGS2TFb/NOSB0WtmcBeHe6ZSVdEUSLr3RBFqZlJF7d5yc5rnihKz0yaJoojZibdEEWp12zWoII/7ogid6sX/6/nkWRSYmZyyIyi5WuL2IyiFzIpNh/khQqwzyh6I5PsM4reyKTYjKIXMjlrUMHEZxQtt/hlGTCjaJVMuiSKEjpuiKKUjovbvKSOeaIorWOaKI7QcUMUpXQe+31Pc6xeN0AAAAAASUVORK5CYII=" }}
<style type="text/css">
body {
{{ if .BackgroundImage.Url }}
background-image: url("{{ .BackgroundImage.Url }}?v={{ .BackgroundImage.Size }}");
background-attachment: fixed;
{{ with .BackgroundImage.Size }}
background-size: "{{ . }}";
{{ end }}
{{ else }}
{{ $bgcolor := or .Project.Color1 "999999" | hex2color }}
background-color: {{ eq .Theme "dark" | ternary (darken 0.6 $bgcolor) (brighten 0.6 $bgcolor) | color2css }};
background-image: url('data:image/png;base64,{{ eq .Theme "dark" | ternary $bgdark $bglight }}');
background-size: auto;
{{ end }}
}
</style>
<link rel="stylesheet" href="{{ .ProjectCSSUrl }}" /> <link rel="stylesheet" href="{{ .ProjectCSSUrl }}" />
<link rel="apple-touch-icon" sizes="400x400" href="{{ static "logo.png" }}"> <link rel="apple-touch-icon" sizes="400x400" href="{{ static "logo.png" }}">
<link rel="icon" type="image/png" sizes="16x16" href="{{ static "favicon-16x16.png" }}"> <link rel="icon" type="image/png" sizes="16x16" href="{{ static "favicon-16x16.png" }}">

View File

@ -37,14 +37,15 @@
/* Copy-paste from project.css yay */ /* Copy-paste from project.css yay */
{{ $c := hex2color "C8217E" }} {{ $c := hex2color "C8217E" }}
{{ $themeDim := eq .Theme "dark" | ternary (lightness 0.35 $c) (lightness 0.75 $c) | color2css }} {{/* In the 2024 redesign, these were all forced to use the dark theme variants. */}}
{{ $themeDimmer := eq .Theme "dark" | ternary (lightness 0.3 $c) (lightness 0.8 $c) | color2css }} {{ $themeDim := lightness 0.35 $c | color2css }}
{{ $themeDimmest := eq .Theme "dark" | ternary (lightness 0.2 $c) (lightness 0.85 $c) | color2css }} {{ $themeDimmer := lightness 0.3 $c | color2css }}
{{ $themeDimmest := lightness 0.2 $c | color2css }}
{{ $themeDark := eq .Theme "dark" | ternary (lightness 0.30 $c) (lightness 0.35 $c) | color2css }} {{ $themeDark := lightness 0.30 $c | color2css }}
{{ $linkColor := eq .Theme "dark" | ternary (lightness 0.55 $c) (lightness 0.35 $c) | color2css }} {{ $linkColor := lightness 0.55 $c | color2css }}
{{ $linkHoverColor := eq .Theme "dark" | ternary (lightness 0.65 $c) (lightness 0.45 $c) | color2css }} {{ $linkHoverColor := lightness 0.65 $c | color2css }}
:root { :root {
--content-background: #f8f8f8; --content-background: #f8f8f8;

View File

@ -37,14 +37,15 @@
/* Copy-paste from project.css yay */ /* Copy-paste from project.css yay */
{{ $c := hex2color "346ba6" }} {{ $c := hex2color "346ba6" }}
{{ $themeDim := eq .Theme "dark" | ternary (lightness 0.35 $c) (lightness 0.75 $c) | color2css }} {{/* In the 2024 redesign, these were all forced to use the dark theme variants. */}}
{{ $themeDimmer := eq .Theme "dark" | ternary (lightness 0.3 $c) (lightness 0.8 $c) | color2css }} {{ $themeDim := lightness 0.35 $c | color2css }}
{{ $themeDimmest := eq .Theme "dark" | ternary (lightness 0.2 $c) (lightness 0.85 $c) | color2css }} {{ $themeDimmer := lightness 0.3 $c | color2css }}
{{ $themeDimmest := lightness 0.2 $c | color2css }}
{{ $themeDark := eq .Theme "dark" | ternary (lightness 0.30 $c) (lightness 0.35 $c) | color2css }} {{ $themeDark := lightness 0.30 $c | color2css }}
{{ $linkColor := eq .Theme "dark" | ternary (lightness 0.55 $c) (lightness 0.35 $c) | color2css }} {{ $linkColor := lightness 0.55 $c | color2css }}
{{ $linkHoverColor := eq .Theme "dark" | ternary (lightness 0.65 $c) (lightness 0.45 $c) | color2css }} {{ $linkHoverColor := lightness 0.65 $c | color2css }}
:root { :root {
--content-background: #f8f8f8; --content-background: #f8f8f8;

View File

@ -38,14 +38,15 @@
{{/* {{ $c := hex2color "23CE76" }} */}} {{/* {{ $c := hex2color "23CE76" }} */}}
{{ $c := hex2color "1DB768" }}{{/* modified for contrast reasons */}} {{ $c := hex2color "1DB768" }}{{/* modified for contrast reasons */}}
{{ $themeDim := eq .Theme "dark" | ternary (lightness 0.35 $c) (lightness 0.75 $c) | color2css }} {{/* In the 2024 redesign, these were all forced to use the dark theme variants. */}}
{{ $themeDimmer := eq .Theme "dark" | ternary (lightness 0.3 $c) (lightness 0.8 $c) | color2css }} {{ $themeDim := lightness 0.35 $c | color2css }}
{{ $themeDimmest := eq .Theme "dark" | ternary (lightness 0.2 $c) (lightness 0.85 $c) | color2css }} {{ $themeDimmer := lightness 0.3 $c | color2css }}
{{ $themeDimmest := lightness 0.2 $c | color2css }}
{{ $themeDark := eq .Theme "dark" | ternary (lightness 0.30 $c) (lightness 0.35 $c) | color2css }} {{ $themeDark := lightness 0.30 $c | color2css }}
{{ $linkColor := eq .Theme "dark" | ternary (lightness 0.55 $c) (lightness 0.35 $c) | color2css }} {{ $linkColor := lightness 0.55 $c | color2css }}
{{ $linkHoverColor := eq .Theme "dark" | ternary (lightness 0.65 $c) (lightness 0.45 $c) | color2css }} {{ $linkHoverColor := lightness 0.65 $c | color2css }}
:root { :root {
--content-background: #f8f8f8; --content-background: #f8f8f8;

View File

@ -33,13 +33,6 @@
</div> </div>
</div> </div>
</div> </div>
<div class="edit-form-row">
<div>Theme:</div>
<div>
<input type="checkbox" name="darktheme" id="darktheme" {{ if .User.DarkTheme }}checked{{ end }} />
<label for="darktheme">Use dark theme</label>
</div>
</div>
<div class="edit-form-row"> <div class="edit-form-row">
<div>Avatar:</div> <div>Avatar:</div>
<div class="user_avatar"> <div class="user_avatar">
@ -52,7 +45,6 @@
document.querySelector("#user_form"), document.querySelector("#user_form"),
avatarMaxFileSize, avatarMaxFileSize,
document.querySelector(".user_avatar"), document.querySelector(".user_avatar"),
{{ .DefaultAvatarUrl }}
); );
</script> </script>
</div> </div>

View File

@ -10,7 +10,6 @@ type BaseData struct {
CanonicalLink string CanonicalLink string
OpenGraphItems []OpenGraphItem OpenGraphItems []OpenGraphItem
BackgroundImage BackgroundImage BackgroundImage BackgroundImage
Theme string
BodyClasses []string BodyClasses []string
Breadcrumbs []Breadcrumb Breadcrumbs []Breadcrumb
Notices []Notice Notices []Notice
@ -205,7 +204,6 @@ type User struct {
AvatarUrl string AvatarUrl string
ProfileUrl string ProfileUrl string
DarkTheme bool
ShowEmail bool ShowEmail bool
Timezone string Timezone string

View File

@ -83,7 +83,6 @@ func AdminAtomFeed(c *RequestContext) ResponseData {
&post.Author, &post.Author,
false, false,
true, true,
c.Theme,
) )
postItem.PostTypePrefix = fmt.Sprintf("ADMIN::UNAPPROVED: %s", postItem.PostTypePrefix) postItem.PostTypePrefix = fmt.Sprintf("ADMIN::UNAPPROVED: %s", postItem.PostTypePrefix)
@ -177,7 +176,7 @@ func AdminApprovalQueue(c *RequestContext) ResponseData {
userData = unapprovedUsers[idx] userData = unapprovedUsers[idx]
} else { } else {
userData = &unapprovedUserData{ userData = &unapprovedUserData{
User: templates.UserToTemplate(s.Owner, c.Theme), User: templates.UserToTemplate(s.Owner),
UserLinks: make([]templates.Link, 0, 10), UserLinks: make([]templates.Link, 0, 10),
} }
unapprovedUsers = append(unapprovedUsers, userData) unapprovedUsers = append(unapprovedUsers, userData)
@ -187,7 +186,7 @@ func AdminApprovalQueue(c *RequestContext) ResponseData {
if s.Snippet.When.After(userData.Date) { if s.Snippet.When.After(userData.Date) {
userData.Date = s.Snippet.When userData.Date = s.Snippet.When
} }
timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, c.Theme, false) timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, false)
timelineItem.OwnerAvatarUrl = "" timelineItem.OwnerAvatarUrl = ""
timelineItem.SmallInfo = true timelineItem.SmallInfo = true
userData.Timeline = append(userData.Timeline, timelineItem) userData.Timeline = append(userData.Timeline, timelineItem)
@ -199,7 +198,7 @@ func AdminApprovalQueue(c *RequestContext) ResponseData {
userData = unapprovedUsers[idx] userData = unapprovedUsers[idx]
} else { } else {
userData = &unapprovedUserData{ userData = &unapprovedUserData{
User: templates.UserToTemplate(&p.Author, c.Theme), User: templates.UserToTemplate(&p.Author),
UserLinks: make([]templates.Link, 0, 10), UserLinks: make([]templates.Link, 0, 10),
} }
unapprovedUsers = append(unapprovedUsers, userData) unapprovedUsers = append(unapprovedUsers, userData)
@ -209,7 +208,7 @@ func AdminApprovalQueue(c *RequestContext) ResponseData {
if p.Post.PostDate.After(userData.Date) { if p.Post.PostDate.After(userData.Date) {
userData.Date = p.Post.PostDate userData.Date = p.Post.PostDate
} }
timelineItem := PostToTimelineItem(hmndata.UrlContextForProject(&p.Project), lineageBuilder, &p.Post, &p.Thread, &p.Author, c.Theme) timelineItem := PostToTimelineItem(hmndata.UrlContextForProject(&p.Project), lineageBuilder, &p.Post, &p.Thread, &p.Author)
timelineItem.OwnerAvatarUrl = "" timelineItem.OwnerAvatarUrl = ""
timelineItem.SmallInfo = true timelineItem.SmallInfo = true
timelineItem.Description = template.HTML(p.CurrentVersion.TextParsed) timelineItem.Description = template.HTML(p.CurrentVersion.TextParsed)
@ -222,7 +221,7 @@ func AdminApprovalQueue(c *RequestContext) ResponseData {
userData = unapprovedUsers[idx] userData = unapprovedUsers[idx]
} else { } else {
userData = &unapprovedUserData{ userData = &unapprovedUserData{
User: templates.UserToTemplate(p.User, c.Theme), User: templates.UserToTemplate(p.User),
UserLinks: make([]templates.Link, 0, 10), UserLinks: make([]templates.Link, 0, 10),
} }
unapprovedUsers = append(unapprovedUsers, userData) unapprovedUsers = append(unapprovedUsers, userData)
@ -237,7 +236,7 @@ func AdminApprovalQueue(c *RequestContext) ResponseData {
userData.Date = p.ProjectAndStuff.Project.DateCreated userData.Date = p.ProjectAndStuff.Project.DateCreated
} }
userData.ProjectsWithLinks = append(userData.ProjectsWithLinks, projectWithLinks{ userData.ProjectsWithLinks = append(userData.ProjectsWithLinks, projectWithLinks{
Project: templates.ProjectAndStuffToTemplate(p.ProjectAndStuff, hmndata.UrlContextForProject(&p.ProjectAndStuff.Project).BuildHomepage(), c.Theme), Project: templates.ProjectAndStuffToTemplate(p.ProjectAndStuff, hmndata.UrlContextForProject(&p.ProjectAndStuff.Project).BuildHomepage()),
Links: projectLinks, Links: projectLinks,
}) })
} }

View File

@ -24,7 +24,7 @@ func getBaseData(c *RequestContext, title string, breadcrumbs []templates.Breadc
var templateUser *templates.User var templateUser *templates.User
var templateSession *templates.Session var templateSession *templates.Session
if c.CurrentUser != nil { if c.CurrentUser != nil {
u := templates.UserToTemplate(c.CurrentUser, c.Theme) u := templates.UserToTemplate(c.CurrentUser)
s := templates.SessionToTemplate(c.CurrentSession) s := templates.SessionToTemplate(c.CurrentSession)
templateUser = &u templateUser = &u
templateSession = &s templateSession = &s
@ -44,7 +44,6 @@ func getBaseData(c *RequestContext, title string, breadcrumbs []templates.Breadc
} }
baseData := templates.BaseData{ baseData := templates.BaseData{
Theme: c.Theme,
Title: title, Title: title,
Breadcrumbs: breadcrumbs, Breadcrumbs: breadcrumbs,

View File

@ -67,7 +67,7 @@ func BlogIndex(c *RequestContext) ResponseData {
entries = append(entries, blogIndexEntry{ entries = append(entries, blogIndexEntry{
Title: thread.Thread.Title, Title: thread.Thread.Title,
Url: c.UrlContext.BuildBlogThread(thread.Thread.ID, thread.Thread.Title), Url: c.UrlContext.BuildBlogThread(thread.Thread.ID, thread.Thread.Title),
Author: templates.UserToTemplate(thread.FirstPostAuthor, c.Theme), Author: templates.UserToTemplate(thread.FirstPostAuthor),
Date: thread.FirstPost.PostDate, Date: thread.FirstPost.PostDate,
Content: template.HTML(thread.FirstPostCurrentVersion.TextParsed), Content: template.HTML(thread.FirstPostCurrentVersion.TextParsed),
}) })
@ -140,12 +140,12 @@ func BlogThread(c *RequestContext) ResponseData {
var templatePosts []templates.Post var templatePosts []templates.Post
for _, p := range posts { for _, p := range posts {
post := templates.PostToTemplate(&p.Post, p.Author, c.Theme) post := templates.PostToTemplate(&p.Post, p.Author)
post.AddContentVersion(p.CurrentVersion, p.Editor) post.AddContentVersion(p.CurrentVersion, p.Editor)
addBlogUrlsToPost(c.UrlContext, &post, &p.Thread, p.Post.ID) addBlogUrlsToPost(c.UrlContext, &post, &p.Thread, p.Post.ID)
if p.ReplyPost != nil { if p.ReplyPost != nil {
reply := templates.PostToTemplate(p.ReplyPost, p.ReplyAuthor, c.Theme) reply := templates.PostToTemplate(p.ReplyPost, p.ReplyAuthor)
addBlogUrlsToPost(c.UrlContext, &reply, &p.Thread, p.Post.ID) addBlogUrlsToPost(c.UrlContext, &reply, &p.Thread, p.Post.ID)
post.ReplyPost = &reply post.ReplyPost = &reply
} }
@ -403,7 +403,7 @@ func BlogPostReply(c *RequestContext) ResponseData {
BlogThreadBreadcrumbs(c.UrlContext, &post.Thread), BlogThreadBreadcrumbs(c.UrlContext, &post.Thread),
) )
replyPost := templates.PostToTemplate(&post.Post, post.Author, c.Theme) replyPost := templates.PostToTemplate(&post.Post, post.Author)
replyPost.AddContentVersion(post.CurrentVersion, post.Editor) replyPost.AddContentVersion(post.CurrentVersion, post.Editor)
editData := getEditorDataForNew(c.UrlContext, c.CurrentUser, baseData, &replyPost) editData := getEditorDataForNew(c.UrlContext, c.CurrentUser, baseData, &replyPost)
@ -479,7 +479,7 @@ func BlogPostDelete(c *RequestContext) ResponseData {
BlogThreadBreadcrumbs(c.UrlContext, &post.Thread), BlogThreadBreadcrumbs(c.UrlContext, &post.Thread),
) )
templatePost := templates.PostToTemplate(&post.Post, post.Author, c.Theme) templatePost := templates.PostToTemplate(&post.Post, post.Author)
templatePost.AddContentVersion(post.CurrentVersion, post.Editor) templatePost.AddContentVersion(post.CurrentVersion, post.Editor)
type blogPostDeleteData struct { type blogPostDeleteData struct {

View File

@ -49,7 +49,7 @@ func loadCommonData(h Handler) Handler {
}) })
if err == nil { if err == nil {
c.CurrentProject = &dbProject.Project c.CurrentProject = &dbProject.Project
c.CurrentProjectLogoUrl = templates.ProjectLogoUrl(&dbProject.Project, dbProject.LogoLightAsset, dbProject.LogoDarkAsset, c.Theme) c.CurrentProjectLogoUrl = templates.ProjectLogoUrl(&dbProject.Project, dbProject.LogoLightAsset, dbProject.LogoDarkAsset)
owners = dbProject.Owners owners = dbProject.Owners
} else { } else {
if errors.Is(err, db.NotFound) { if errors.Is(err, db.NotFound) {
@ -69,7 +69,7 @@ func loadCommonData(h Handler) Handler {
panic(oops.New(err, "failed to fetch HMN project")) panic(oops.New(err, "failed to fetch HMN project"))
} }
c.CurrentProject = &dbProject.Project c.CurrentProject = &dbProject.Project
c.CurrentProjectLogoUrl = templates.ProjectLogoUrl(&dbProject.Project, dbProject.LogoLightAsset, dbProject.LogoDarkAsset, c.Theme) c.CurrentProjectLogoUrl = templates.ProjectLogoUrl(&dbProject.Project, dbProject.LogoLightAsset, dbProject.LogoDarkAsset)
} }
if c.CurrentProject == nil { if c.CurrentProject == nil {
@ -80,11 +80,6 @@ func loadCommonData(h Handler) Handler {
c.UrlContext = hmndata.UrlContextForProject(c.CurrentProject) c.UrlContext = hmndata.UrlContextForProject(c.CurrentProject)
} }
c.Theme = "light"
if c.CurrentUser != nil && c.CurrentUser.DarkTheme {
c.Theme = "dark"
}
} }
c.Perf.EndBlock() c.Perf.EndBlock()

View File

@ -168,7 +168,7 @@ func AtomFeed(c *RequestContext) ResponseData {
templateProject := templates.ProjectToTemplate(&p.Project, hmndata.UrlContextForProject(&p.Project).BuildHomepage()) templateProject := templates.ProjectToTemplate(&p.Project, hmndata.UrlContextForProject(&p.Project).BuildHomepage())
templateProject.UUID = uuid.NewSHA1(uuid.NameSpaceURL, []byte(templateProject.Url)).URN() templateProject.UUID = uuid.NewSHA1(uuid.NameSpaceURL, []byte(templateProject.Url)).URN()
for _, owner := range p.Owners { for _, owner := range p.Owners {
templateProject.Owners = append(templateProject.Owners, templates.UserToTemplate(owner, "")) templateProject.Owners = append(templateProject.Owners, templates.UserToTemplate(owner))
} }
feedData.Projects = append(feedData.Projects, templateProject) feedData.Projects = append(feedData.Projects, templateProject)
@ -216,7 +216,6 @@ func fetchAllPosts(c *RequestContext, offset int, limit int) ([]templates.PostLi
postAndStuff.Author, postAndStuff.Author,
postAndStuff.Unread, postAndStuff.Unread,
true, true,
c.Theme,
) )
postItem.UUID = uuid.NewSHA1(uuid.NameSpaceURL, []byte(postItem.Url)).URN() postItem.UUID = uuid.NewSHA1(uuid.NameSpaceURL, []byte(postItem.Url)).URN()

View File

@ -10,7 +10,7 @@ import (
) )
func FollowingTest(c *RequestContext) ResponseData { func FollowingTest(c *RequestContext) ResponseData {
timelineItems, err := FetchFollowTimelineForUser(c, c.Conn, c.CurrentUser, c.Theme) timelineItems, err := FetchFollowTimelineForUser(c, c.Conn, c.CurrentUser)
if err != nil { if err != nil {
return c.ErrorResponse(http.StatusInternalServerError, err) return c.ErrorResponse(http.StatusInternalServerError, err)
} }

View File

@ -124,9 +124,9 @@ func Forum(c *RequestContext) ResponseData {
return templates.ThreadListItem{ return templates.ThreadListItem{
Title: row.Thread.Title, Title: row.Thread.Title,
Url: c.UrlContext.BuildForumThread(cd.LineageBuilder.GetSubforumLineageSlugs(*row.Thread.SubforumID), row.Thread.ID, row.Thread.Title, 1), Url: c.UrlContext.BuildForumThread(cd.LineageBuilder.GetSubforumLineageSlugs(*row.Thread.SubforumID), row.Thread.ID, row.Thread.Title, 1),
FirstUser: templates.UserToTemplate(row.FirstPostAuthor, c.Theme), FirstUser: templates.UserToTemplate(row.FirstPostAuthor),
FirstDate: row.FirstPost.PostDate, FirstDate: row.FirstPost.PostDate,
LastUser: templates.UserToTemplate(row.LastPostAuthor, c.Theme), LastUser: templates.UserToTemplate(row.LastPostAuthor),
LastDate: row.LastPost.PostDate, LastDate: row.LastPost.PostDate,
Unread: row.Unread, Unread: row.Unread,
} }
@ -391,12 +391,12 @@ func ForumThread(c *RequestContext) ResponseData {
var posts []templates.Post var posts []templates.Post
for _, p := range postsAndStuff { for _, p := range postsAndStuff {
post := templates.PostToTemplate(&p.Post, p.Author, c.Theme) post := templates.PostToTemplate(&p.Post, p.Author)
post.AddContentVersion(p.CurrentVersion, p.Editor) post.AddContentVersion(p.CurrentVersion, p.Editor)
addForumUrlsToPost(c.UrlContext, &post, currentSubforumSlugs, thread.ID, post.ID) addForumUrlsToPost(c.UrlContext, &post, currentSubforumSlugs, thread.ID, post.ID)
if p.ReplyPost != nil { if p.ReplyPost != nil {
reply := templates.PostToTemplate(p.ReplyPost, p.ReplyAuthor, c.Theme) reply := templates.PostToTemplate(p.ReplyPost, p.ReplyAuthor)
addForumUrlsToPost(c.UrlContext, &reply, currentSubforumSlugs, thread.ID, reply.ID) addForumUrlsToPost(c.UrlContext, &reply, currentSubforumSlugs, thread.ID, reply.ID)
post.ReplyPost = &reply post.ReplyPost = &reply
} }
@ -587,7 +587,7 @@ func ForumPostReply(c *RequestContext) ResponseData {
ForumThreadBreadcrumbs(c.UrlContext, cd.LineageBuilder, &post.Thread), ForumThreadBreadcrumbs(c.UrlContext, cd.LineageBuilder, &post.Thread),
) )
replyPost := templates.PostToTemplate(&post.Post, post.Author, c.Theme) replyPost := templates.PostToTemplate(&post.Post, post.Author)
replyPost.AddContentVersion(post.CurrentVersion, post.Editor) replyPost.AddContentVersion(post.CurrentVersion, post.Editor)
editData := getEditorDataForNew(c.UrlContext, c.CurrentUser, baseData, &replyPost) editData := getEditorDataForNew(c.UrlContext, c.CurrentUser, baseData, &replyPost)
@ -779,7 +779,7 @@ func ForumPostDelete(c *RequestContext) ResponseData {
ForumThreadBreadcrumbs(c.UrlContext, cd.LineageBuilder, &post.Thread), ForumThreadBreadcrumbs(c.UrlContext, cd.LineageBuilder, &post.Thread),
) )
templatePost := templates.PostToTemplate(&post.Post, post.Author, c.Theme) templatePost := templates.PostToTemplate(&post.Post, post.Author)
templatePost.AddContentVersion(post.CurrentVersion, post.Editor) templatePost.AddContentVersion(post.CurrentVersion, post.Editor)
type forumPostDeleteData struct { type forumPostDeleteData struct {

View File

@ -57,7 +57,7 @@ func JamSaveTheDate(c *RequestContext) ResponseData {
tmpl := TemplateData{ tmpl := TemplateData{
BaseData: getBaseDataAutocrumb(c, "Upcoming Jams"), BaseData: getBaseDataAutocrumb(c, "Upcoming Jams"),
UserAvatarUrl: templates.UserAvatarUrl(c.CurrentUser, "dark"), UserAvatarUrl: templates.UserAvatarUrl(c.CurrentUser),
JamsUrl: hmnurl.BuildJamsIndex(), JamsUrl: hmnurl.BuildJamsIndex(),
Visibility2023Url: hmnurl.BuildJamIndex2023_Visibility(), Visibility2023Url: hmnurl.BuildJamIndex2023_Visibility(),
WRJ2023Url: hmnurl.BuildJamIndex2023(), WRJ2023Url: hmnurl.BuildJamIndex2023(),
@ -221,7 +221,7 @@ func getLJ2024BaseData(c *RequestContext) (JamBaseDataLJ2024, error) {
} }
if c.CurrentUser != nil { if c.CurrentUser != nil {
tmpl.UserAvatarUrl = templates.UserAvatarUrl(c.CurrentUser, "dark") tmpl.UserAvatarUrl = templates.UserAvatarUrl(c.CurrentUser)
projects, err := hmndata.FetchProjects(c, c.Conn, c.CurrentUser, hmndata.ProjectsQuery{ projects, err := hmndata.FetchProjects(c, c.Conn, c.CurrentUser, hmndata.ProjectsQuery{
OwnerIDs: []int{c.CurrentUser.ID}, OwnerIDs: []int{c.CurrentUser.ID},
JamSlugs: []string{hmndata.LJ2024.Slug}, JamSlugs: []string{hmndata.LJ2024.Slug},
@ -252,7 +252,7 @@ func getLJ2024FeedData(c *RequestContext, maxTimelineItems int) (JamFeedDataLJ20
for _, jp := range jamProjects { for _, jp := range jamProjects {
urlContext := hmndata.UrlContextForProject(&jp.Project) urlContext := hmndata.UrlContextForProject(&jp.Project)
projectUrl := urlContext.BuildHomepage() projectUrl := urlContext.BuildHomepage()
projects = append(projects, templates.ProjectAndStuffToTemplate(&jp, projectUrl, c.Theme)) projects = append(projects, templates.ProjectAndStuffToTemplate(&jp, projectUrl))
} }
projectIds := make([]int, 0, len(jamProjects)) projectIds := make([]int, 0, len(jamProjects))
@ -272,7 +272,7 @@ func getLJ2024FeedData(c *RequestContext, maxTimelineItems int) (JamFeedDataLJ20
timelineItems = make([]templates.TimelineItem, 0, len(snippets)) timelineItems = make([]templates.TimelineItem, 0, len(snippets))
for _, s := range snippets { for _, s := range snippets {
timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, c.Theme, false) timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, false)
timelineItem.SmallInfo = true timelineItem.SmallInfo = true
timelineItems = append(timelineItems, timelineItem) timelineItems = append(timelineItems, timelineItem)
} }
@ -367,7 +367,7 @@ func JamIndex2023(c *RequestContext) ResponseData {
pageProjects := make([]templates.Project, 0, len(jamProjects)) pageProjects := make([]templates.Project, 0, len(jamProjects))
for _, p := range jamProjects { for _, p := range jamProjects {
pageProjects = append(pageProjects, templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage(), c.Theme)) pageProjects = append(pageProjects, templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage()))
} }
projectIds := make([]int, 0, len(jamProjects)) projectIds := make([]int, 0, len(jamProjects))
@ -385,7 +385,7 @@ func JamIndex2023(c *RequestContext) ResponseData {
} }
showcaseItems = make([]templates.TimelineItem, 0, len(snippets)) showcaseItems = make([]templates.TimelineItem, 0, len(snippets))
for _, s := range snippets { for _, s := range snippets {
timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, c.Theme, false) timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, false)
if timelineItem.CanShowcase { if timelineItem.CanShowcase {
showcaseItems = append(showcaseItems, timelineItem) showcaseItems = append(showcaseItems, timelineItem)
} }
@ -452,7 +452,7 @@ func JamFeed2023(c *RequestContext) ResponseData {
timelineItems = make([]templates.TimelineItem, 0, len(snippets)) timelineItems = make([]templates.TimelineItem, 0, len(snippets))
for _, s := range snippets { for _, s := range snippets {
timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, c.Theme, false) timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, false)
timelineItem.SmallInfo = true timelineItem.SmallInfo = true
timelineItems = append(timelineItems, timelineItem) timelineItems = append(timelineItems, timelineItem)
} }
@ -460,7 +460,7 @@ func JamFeed2023(c *RequestContext) ResponseData {
pageProjects := make([]templates.Project, 0, len(jamProjects)) pageProjects := make([]templates.Project, 0, len(jamProjects))
for _, p := range jamProjects { for _, p := range jamProjects {
pageProjects = append(pageProjects, templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage(), c.Theme)) pageProjects = append(pageProjects, templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage()))
} }
type JamFeedData struct { type JamFeedData struct {
@ -553,7 +553,7 @@ func JamIndex2023_Visibility(c *RequestContext) ResponseData {
pageProjects := make([]templates.Project, 0, len(jamProjects)) pageProjects := make([]templates.Project, 0, len(jamProjects))
for _, p := range jamProjects { for _, p := range jamProjects {
pageProjects = append(pageProjects, templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage(), c.Theme)) pageProjects = append(pageProjects, templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage()))
} }
projectIds := make([]int, 0, len(jamProjects)) projectIds := make([]int, 0, len(jamProjects))
@ -571,7 +571,7 @@ func JamIndex2023_Visibility(c *RequestContext) ResponseData {
} }
showcaseItems = make([]templates.TimelineItem, 0, len(snippets)) showcaseItems = make([]templates.TimelineItem, 0, len(snippets))
for _, s := range snippets { for _, s := range snippets {
timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, c.Theme, false) timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, false)
if timelineItem.CanShowcase { if timelineItem.CanShowcase {
showcaseItems = append(showcaseItems, timelineItem) showcaseItems = append(showcaseItems, timelineItem)
} }
@ -620,7 +620,7 @@ func JamFeed2023_Visibility(c *RequestContext) ResponseData {
timelineItems = make([]templates.TimelineItem, 0, len(snippets)) timelineItems = make([]templates.TimelineItem, 0, len(snippets))
for _, s := range snippets { for _, s := range snippets {
timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, c.Theme, false) timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, false)
timelineItem.SmallInfo = true timelineItem.SmallInfo = true
timelineItems = append(timelineItems, timelineItem) timelineItems = append(timelineItems, timelineItem)
} }
@ -628,7 +628,7 @@ func JamFeed2023_Visibility(c *RequestContext) ResponseData {
pageProjects := make([]templates.Project, 0, len(jamProjects)) pageProjects := make([]templates.Project, 0, len(jamProjects))
for _, p := range jamProjects { for _, p := range jamProjects {
pageProjects = append(pageProjects, templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage(), c.Theme)) pageProjects = append(pageProjects, templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage()))
} }
type JamFeedData struct { type JamFeedData struct {
@ -681,7 +681,7 @@ func JamRecap2023_Visibility(c *RequestContext) ResponseData {
var ben templates.User var ben templates.User
benUser, err := hmndata.FetchUserByUsername(c, c.Conn, c.CurrentUser, "bvisness", hmndata.UsersQuery{}) benUser, err := hmndata.FetchUserByUsername(c, c.Conn, c.CurrentUser, "bvisness", hmndata.UsersQuery{})
if err == nil { if err == nil {
ben = templates.UserToTemplate(benUser, c.Theme) ben = templates.UserToTemplate(benUser)
} else if err == db.NotFound { } else if err == db.NotFound {
ben = templates.UnknownUser ben = templates.UnknownUser
} else { } else {
@ -767,7 +767,7 @@ func JamIndex2022(c *RequestContext) ResponseData {
pageProjects := make([]templates.Project, 0, len(jamProjects)) pageProjects := make([]templates.Project, 0, len(jamProjects))
for _, p := range jamProjects { for _, p := range jamProjects {
pageProjects = append(pageProjects, templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage(), c.Theme)) pageProjects = append(pageProjects, templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage()))
} }
projectIds := make([]int, 0, len(jamProjects)) projectIds := make([]int, 0, len(jamProjects))
@ -785,7 +785,7 @@ func JamIndex2022(c *RequestContext) ResponseData {
} }
showcaseItems = make([]templates.TimelineItem, 0, len(snippets)) showcaseItems = make([]templates.TimelineItem, 0, len(snippets))
for _, s := range snippets { for _, s := range snippets {
timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, c.Theme, false) timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, false)
if timelineItem.CanShowcase { if timelineItem.CanShowcase {
showcaseItems = append(showcaseItems, timelineItem) showcaseItems = append(showcaseItems, timelineItem)
} }
@ -833,7 +833,7 @@ func JamFeed2022(c *RequestContext) ResponseData {
timelineItems = make([]templates.TimelineItem, 0, len(snippets)) timelineItems = make([]templates.TimelineItem, 0, len(snippets))
for _, s := range snippets { for _, s := range snippets {
timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, c.Theme, false) timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, false)
timelineItem.SmallInfo = true timelineItem.SmallInfo = true
timelineItems = append(timelineItems, timelineItem) timelineItems = append(timelineItems, timelineItem)
} }
@ -841,7 +841,7 @@ func JamFeed2022(c *RequestContext) ResponseData {
pageProjects := make([]templates.Project, 0, len(jamProjects)) pageProjects := make([]templates.Project, 0, len(jamProjects))
for _, p := range jamProjects { for _, p := range jamProjects {
pageProjects = append(pageProjects, templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage(), c.Theme)) pageProjects = append(pageProjects, templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage()))
} }
type JamFeedData struct { type JamFeedData struct {
@ -901,7 +901,7 @@ func JamIndex2021(c *RequestContext) ResponseData {
} }
showcaseItems := make([]templates.TimelineItem, 0, len(snippets)) showcaseItems := make([]templates.TimelineItem, 0, len(snippets))
for _, s := range snippets { for _, s := range snippets {
timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, c.Theme, false) timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, false)
if timelineItem.CanShowcase { if timelineItem.CanShowcase {
showcaseItems = append(showcaseItems, timelineItem) showcaseItems = append(showcaseItems, timelineItem)
} }

View File

@ -40,6 +40,8 @@ func Index(c *RequestContext) ResponseData {
var timelineItems []templates.TimelineItem var timelineItems []templates.TimelineItem
FetchFollowTimelineForUser(c, c.Conn, c.CurrentUser)
// This is essentially an alternate for feed page 1. // This is essentially an alternate for feed page 1.
posts, err := hmndata.FetchPosts(c, c.Conn, c.CurrentUser, hmndata.PostsQuery{ posts, err := hmndata.FetchPosts(c, c.Conn, c.CurrentUser, hmndata.PostsQuery{
ThreadTypes: feedThreadTypes, ThreadTypes: feedThreadTypes,
@ -54,7 +56,7 @@ func Index(c *RequestContext) ResponseData {
continue // ignore news posts et. al. continue // ignore news posts et. al.
} }
item := PostToTimelineItem(hmndata.UrlContextForProject(&p.Project), lineageBuilder, &p.Post, &p.Thread, p.Author, c.Theme) item := PostToTimelineItem(hmndata.UrlContextForProject(&p.Project), lineageBuilder, &p.Post, &p.Thread, p.Author)
if p.Thread.Type == models.ThreadTypeProjectBlogPost && p.Post.ID == p.Thread.FirstID { if p.Thread.Type == models.ThreadTypeProjectBlogPost && p.Post.ID == p.Thread.FirstID {
// blog post // blog post
item.Description = template.HTML(p.CurrentVersion.TextParsed) item.Description = template.HTML(p.CurrentVersion.TextParsed)
@ -75,7 +77,7 @@ func Index(c *RequestContext) ResponseData {
var newsPostItem *templates.TimelineItem var newsPostItem *templates.TimelineItem
if len(newsThreads) > 0 { if len(newsThreads) > 0 {
t := newsThreads[0] t := newsThreads[0]
item := PostToTimelineItem(hmndata.UrlContextForProject(&t.Project), lineageBuilder, &t.FirstPost, &t.Thread, t.FirstPostAuthor, c.Theme) item := PostToTimelineItem(hmndata.UrlContextForProject(&t.Project), lineageBuilder, &t.FirstPost, &t.Thread, t.FirstPostAuthor)
item.Breadcrumbs = nil item.Breadcrumbs = nil
item.TypeTitle = "" item.TypeTitle = ""
item.AllowTitleWrap = true item.AllowTitleWrap = true

View File

@ -85,14 +85,13 @@ func MakePostListItem(
user *models.User, user *models.User,
unread bool, unread bool,
includeBreadcrumbs bool, includeBreadcrumbs bool,
currentTheme string,
) templates.PostListItem { ) templates.PostListItem {
var result templates.PostListItem var result templates.PostListItem
urlContext := hmndata.UrlContextForProject(project) urlContext := hmndata.UrlContextForProject(project)
result.Title = thread.Title result.Title = thread.Title
result.User = templates.UserToTemplate(user, currentTheme) result.User = templates.UserToTemplate(user)
result.Date = post.PostDate result.Date = post.PostDate
result.Unread = unread result.Unread = unread
result.Url = UrlForGenericPost(urlContext, thread, post, lineageBuilder) result.Url = UrlForGenericPost(urlContext, thread, post, lineageBuilder)

View File

@ -238,7 +238,7 @@ func getShuffledOfficialProjects(c *RequestContext) ([]templates.Project, error)
var restProjects []templates.Project var restProjects []templates.Project
now := time.Now() now := time.Now()
for _, p := range official { for _, p := range official {
templateProject := templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage(), c.Theme) templateProject := templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage())
if p.Project.Slug == "hero" { if p.Project.Slug == "hero" {
// NOTE(asaf): Handmade Hero gets special treatment. Must always be first in the list. // NOTE(asaf): Handmade Hero gets special treatment. Must always be first in the list.
@ -297,7 +297,7 @@ func getPersonalProjects(c *RequestContext, jamSlug string) ([]templates.Project
var personalProjects []templates.Project var personalProjects []templates.Project
for _, p := range projects { for _, p := range projects {
templateProject := templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage(), c.Theme) templateProject := templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage())
personalProjects = append(personalProjects, templateProject) personalProjects = append(personalProjects, templateProject)
} }
@ -410,9 +410,9 @@ func ProjectHomepage(c *RequestContext) ResponseData {
if err != nil { if err != nil {
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch project details")) return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch project details"))
} }
templateData.Project = templates.ProjectAndStuffToTemplate(&p, c.UrlContext.BuildHomepage(), c.Theme) templateData.Project = templates.ProjectAndStuffToTemplate(&p, c.UrlContext.BuildHomepage())
for _, owner := range owners { for _, owner := range owners {
templateData.Owners = append(templateData.Owners, templates.UserToTemplate(owner, c.Theme)) templateData.Owners = append(templateData.Owners, templates.UserToTemplate(owner))
} }
if c.CurrentProject.Hidden { if c.CurrentProject.Hidden {
@ -467,7 +467,7 @@ func ProjectHomepage(c *RequestContext) ResponseData {
} }
} }
templateData.RecentActivity, err = FetchTimeline(c, c.Conn, c.CurrentUser, c.Theme, TimelineQuery{ templateData.RecentActivity, err = FetchTimeline(c, c.Conn, c.CurrentUser, TimelineQuery{
ProjectIDs: []int{c.CurrentProject.ID}, ProjectIDs: []int{c.CurrentProject.ID},
}) })
if err != nil { if err != nil {
@ -486,12 +486,12 @@ func ProjectHomepage(c *RequestContext) ResponseData {
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch user projects")) return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch user projects"))
} }
templateProjects := make([]templates.Project, 0, len(userProjects)) templateProjects := make([]templates.Project, 0, len(userProjects))
templateProjects = append(templateProjects, templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage(), c.Theme)) templateProjects = append(templateProjects, templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage()))
for _, p := range userProjects { for _, p := range userProjects {
if p.Project.ID == c.CurrentProject.ID { if p.Project.ID == c.CurrentProject.ID {
continue continue
} }
templateProject := templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage(), c.Theme) templateProject := templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage())
templateProjects = append(templateProjects, templateProject) templateProjects = append(templateProjects, templateProject)
} }
templateData.SnippetEdit = templates.SnippetEdit{ templateData.SnippetEdit = templates.SnippetEdit{
@ -550,7 +550,7 @@ func ProjectNew(c *RequestContext) ResponseData {
} }
var project templates.ProjectSettings var project templates.ProjectSettings
project.Owners = append(project.Owners, templates.UserToTemplate(c.CurrentUser, c.Theme)) project.Owners = append(project.Owners, templates.UserToTemplate(c.CurrentUser))
project.Personal = true project.Personal = true
var currentJam *hmndata.Jam var currentJam *hmndata.Jam
@ -696,7 +696,6 @@ func ProjectEdit(c *RequestContext) ResponseData {
p.Owners, p.Owners,
p.TagText(), p.TagText(),
p.LogoLightAsset, p.LogoDarkAsset, p.HeaderImage, p.LogoLightAsset, p.LogoDarkAsset, p.HeaderImage,
c.Theme,
) )
projectSettings.LinksJSON = string(utils.Must1(json.Marshal(templates.LinksToTemplate(projectLinks)))) projectSettings.LinksJSON = string(utils.Must1(json.Marshal(templates.LinksToTemplate(projectLinks))))

View File

@ -190,7 +190,6 @@ type RequestContext struct {
CurrentProjectLogoUrl string CurrentProjectLogoUrl string
CurrentUser *models.User CurrentUser *models.User
CurrentSession *models.Session CurrentSession *models.Session
Theme string
UrlContext *hmnurl.UrlContext UrlContext *hmnurl.UrlContext
CurrentUserCanEditCurrentProject bool CurrentUserCanEditCurrentProject bool

View File

@ -57,7 +57,7 @@ func Snippet(c *RequestContext) ResponseData {
c.Perf.EndBlock() c.Perf.EndBlock()
canEdit := (c.CurrentUser != nil && (c.CurrentUser.IsStaff || c.CurrentUser.ID == s.Owner.ID)) canEdit := (c.CurrentUser != nil && (c.CurrentUser.IsStaff || c.CurrentUser.ID == s.Owner.ID))
snippet := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, c.Theme, canEdit) snippet := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, canEdit)
snippet.SmallInfo = true snippet.SmallInfo = true
opengraph := []templates.OpenGraphItem{ opengraph := []templates.OpenGraphItem{
@ -114,7 +114,7 @@ func Snippet(c *RequestContext) ResponseData {
} }
templateProjects := make([]templates.Project, 0, len(userProjects)) templateProjects := make([]templates.Project, 0, len(userProjects))
for _, p := range userProjects { for _, p := range userProjects {
templateProject := templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage(), c.Theme) templateProject := templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage())
templateProjects = append(templateProjects, templateProject) templateProjects = append(templateProjects, templateProject)
} }
snippetEdit = templates.SnippetEdit{ snippetEdit = templates.SnippetEdit{

View File

@ -20,7 +20,7 @@ import (
"git.handmade.network/hmn/hmn/src/templates" "git.handmade.network/hmn/hmn/src/templates"
) )
func FetchFollowTimelineForUser(ctx context.Context, conn db.ConnOrTx, user *models.User, theme string) ([]templates.TimelineItem, error) { func FetchFollowTimelineForUser(ctx context.Context, conn db.ConnOrTx, user *models.User) ([]templates.TimelineItem, error) {
perf := perf.ExtractPerf(ctx) perf := perf.ExtractPerf(ctx)
type Follower struct { type Follower struct {
UserID int `db:"user_id"` UserID int `db:"user_id"`
@ -50,7 +50,7 @@ func FetchFollowTimelineForUser(ctx context.Context, conn db.ConnOrTx, user *mod
} }
} }
timelineItems, err := FetchTimeline(ctx, conn, user, theme, TimelineQuery{ timelineItems, err := FetchTimeline(ctx, conn, user, TimelineQuery{
UserIDs: userIDs, UserIDs: userIDs,
ProjectIDs: projectIDs, ProjectIDs: projectIDs,
}) })
@ -64,7 +64,7 @@ type TimelineQuery struct {
ProjectIDs []int ProjectIDs []int
} }
func FetchTimeline(ctx context.Context, conn db.ConnOrTx, currentUser *models.User, theme string, q TimelineQuery) ([]templates.TimelineItem, error) { func FetchTimeline(ctx context.Context, conn db.ConnOrTx, currentUser *models.User, q TimelineQuery) ([]templates.TimelineItem, error) {
perf := perf.ExtractPerf(ctx) perf := perf.ExtractPerf(ctx)
var users []*models.User var users []*models.User
var projects []hmndata.ProjectAndStuff var projects []hmndata.ProjectAndStuff
@ -159,7 +159,6 @@ func FetchTimeline(ctx context.Context, conn db.ConnOrTx, currentUser *models.Us
&post.Post, &post.Post,
&post.Thread, &post.Thread,
post.Author, post.Author,
theme,
)) ))
} }
} }
@ -171,7 +170,6 @@ func FetchTimeline(ctx context.Context, conn db.ConnOrTx, currentUser *models.Us
s.DiscordMessage, s.DiscordMessage,
s.Projects, s.Projects,
s.Owner, s.Owner,
theme,
false, false,
) )
item.SmallInfo = true item.SmallInfo = true
@ -188,7 +186,7 @@ func FetchTimeline(ctx context.Context, conn db.ConnOrTx, currentUser *models.Us
if streamer.UserID != nil { if streamer.UserID != nil {
for _, u := range users { for _, u := range users {
if u.ID == *streamer.UserID { if u.ID == *streamer.UserID {
ownerAvatarUrl = templates.UserAvatarUrl(u, theme) ownerAvatarUrl = templates.UserAvatarUrl(u)
ownerName = u.BestName() ownerName = u.BestName()
ownerUrl = hmnurl.BuildUserProfile(u.Username) ownerUrl = hmnurl.BuildUserProfile(u.Username)
break break
@ -197,7 +195,7 @@ func FetchTimeline(ctx context.Context, conn db.ConnOrTx, currentUser *models.Us
} else if streamer.ProjectID != nil { } else if streamer.ProjectID != nil {
for _, p := range projects { for _, p := range projects {
if p.Project.ID == *streamer.ProjectID { if p.Project.ID == *streamer.ProjectID {
ownerAvatarUrl = templates.ProjectLogoUrl(&p.Project, p.LogoLightAsset, p.LogoDarkAsset, theme) ownerAvatarUrl = templates.ProjectLogoUrl(&p.Project, p.LogoLightAsset, p.LogoDarkAsset)
ownerName = p.Project.Name ownerName = p.Project.Name
ownerUrl = hmndata.UrlContextForProject(&p.Project).BuildHomepage() ownerUrl = hmndata.UrlContextForProject(&p.Project).BuildHomepage()
} }
@ -207,9 +205,6 @@ func FetchTimeline(ctx context.Context, conn db.ConnOrTx, currentUser *models.Us
break break
} }
} }
if ownerAvatarUrl == "" {
ownerAvatarUrl = templates.UserAvatarDefaultUrl(theme)
}
item := TwitchStreamToTimelineItem(s, ownerAvatarUrl, ownerName, ownerUrl) item := TwitchStreamToTimelineItem(s, ownerAvatarUrl, ownerName, ownerUrl)
timelineItems = append(timelineItems, item) timelineItems = append(timelineItems, item)
} }
@ -241,7 +236,6 @@ func PostToTimelineItem(
post *models.Post, post *models.Post,
thread *models.Thread, thread *models.Thread,
owner *models.User, owner *models.User,
currentTheme string,
) templates.TimelineItem { ) templates.TimelineItem {
item := templates.TimelineItem{ item := templates.TimelineItem{
Date: post.PostDate, Date: post.PostDate,
@ -249,7 +243,7 @@ func PostToTimelineItem(
Breadcrumbs: GenericThreadBreadcrumbs(urlContext, lineageBuilder, thread), Breadcrumbs: GenericThreadBreadcrumbs(urlContext, lineageBuilder, thread),
Url: UrlForGenericPost(urlContext, thread, post, lineageBuilder), Url: UrlForGenericPost(urlContext, thread, post, lineageBuilder),
OwnerAvatarUrl: templates.UserAvatarUrl(owner, currentTheme), OwnerAvatarUrl: templates.UserAvatarUrl(owner),
OwnerName: owner.BestName(), OwnerName: owner.BestName(),
OwnerUrl: hmnurl.BuildUserProfile(owner.Username), OwnerUrl: hmnurl.BuildUserProfile(owner.Username),
} }
@ -313,7 +307,6 @@ func SnippetToTimelineItem(
discordMessage *models.DiscordMessage, discordMessage *models.DiscordMessage,
projects []*hmndata.ProjectAndStuff, projects []*hmndata.ProjectAndStuff,
owner *models.User, owner *models.User,
currentTheme string,
editable bool, editable bool,
) templates.TimelineItem { ) templates.TimelineItem {
item := templates.TimelineItem{ item := templates.TimelineItem{
@ -322,7 +315,7 @@ func SnippetToTimelineItem(
FilterTitle: "Snippets", FilterTitle: "Snippets",
Url: hmnurl.BuildSnippet(snippet.ID), Url: hmnurl.BuildSnippet(snippet.ID),
OwnerAvatarUrl: templates.UserAvatarUrl(owner, currentTheme), OwnerAvatarUrl: templates.UserAvatarUrl(owner),
OwnerName: owner.BestName(), OwnerName: owner.BestName(),
OwnerUrl: hmnurl.BuildUserProfile(owner.Username), OwnerUrl: hmnurl.BuildUserProfile(owner.Username),
@ -366,7 +359,7 @@ func SnippetToTimelineItem(
return projects[i].Project.Name < projects[j].Project.Name return projects[i].Project.Name < projects[j].Project.Name
}) })
for _, proj := range projects { for _, proj := range projects {
item.Projects = append(item.Projects, templates.ProjectAndStuffToTemplate(proj, hmndata.UrlContextForProject(&proj.Project).BuildHomepage(), currentTheme)) item.Projects = append(item.Projects, templates.ProjectAndStuffToTemplate(proj, hmndata.UrlContextForProject(&proj.Project).BuildHomepage()))
} }
return item return item

View File

@ -106,7 +106,7 @@ func UserProfile(c *RequestContext) ResponseData {
templateProjects := make([]templates.Project, 0, len(projectsAndStuff)) templateProjects := make([]templates.Project, 0, len(projectsAndStuff))
numPersonalProjects := 0 numPersonalProjects := 0
for _, p := range projectsAndStuff { for _, p := range projectsAndStuff {
templateProject := templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage(), c.Theme) templateProject := templates.ProjectAndStuffToTemplate(&p, hmndata.UrlContextForProject(&p.Project).BuildHomepage())
templateProjects = append(templateProjects, templateProject) templateProjects = append(templateProjects, templateProject)
if p.Project.Personal { if p.Project.Personal {
@ -115,14 +115,14 @@ func UserProfile(c *RequestContext) ResponseData {
} }
c.Perf.EndBlock() c.Perf.EndBlock()
timelineItems, err := FetchTimeline(c, c.Conn, c.CurrentUser, c.Theme, TimelineQuery{ timelineItems, err := FetchTimeline(c, c.Conn, c.CurrentUser, TimelineQuery{
UserIDs: []int{profileUser.ID}, UserIDs: []int{profileUser.ID},
}) })
if err != nil { if err != nil {
return c.ErrorResponse(http.StatusInternalServerError, err) return c.ErrorResponse(http.StatusInternalServerError, err)
} }
templateUser := templates.UserToTemplate(profileUser, c.Theme) templateUser := templates.UserToTemplate(profileUser)
baseData := getBaseDataAutocrumb(c, templateUser.Name) baseData := getBaseDataAutocrumb(c, templateUser.Name)
@ -183,7 +183,6 @@ func UserSettings(c *RequestContext) ResponseData {
templates.BaseData templates.BaseData
AvatarMaxFileSize int AvatarMaxFileSize int
DefaultAvatarUrl string
User templates.User User templates.User
Avatar *templates.Asset Avatar *templates.Asset
@ -254,14 +253,13 @@ func UserSettings(c *RequestContext) ResponseData {
} }
} }
templateUser := templates.UserToTemplate(c.CurrentUser, c.Theme) templateUser := templates.UserToTemplate(c.CurrentUser)
baseData := getBaseDataAutocrumb(c, templateUser.Name) baseData := getBaseDataAutocrumb(c, templateUser.Name)
res.MustWriteTemplate("user_settings.html", UserSettingsTemplateData{ res.MustWriteTemplate("user_settings.html", UserSettingsTemplateData{
BaseData: baseData, BaseData: baseData,
AvatarMaxFileSize: UserAvatarMaxFileSize, AvatarMaxFileSize: UserAvatarMaxFileSize,
DefaultAvatarUrl: templates.UserAvatarDefaultUrl(c.Theme),
User: templateUser, User: templateUser,
Avatar: templates.AssetToTemplate(c.CurrentUser.AvatarAsset), Avatar: templates.AssetToTemplate(c.CurrentUser.AvatarAsset),
Email: c.CurrentUser.Email, Email: c.CurrentUser.Email,
@ -319,7 +317,6 @@ func UserSettingsSave(c *RequestContext) ResponseData {
} }
showEmail := form.Get("showemail") != "" showEmail := form.Get("showemail") != ""
darkTheme := form.Get("darktheme") != ""
blurb := form.Get("shortbio") blurb := form.Get("shortbio")
signature := form.Get("signature") signature := form.Get("signature")
@ -336,7 +333,6 @@ func UserSettingsSave(c *RequestContext) ResponseData {
name = $?, name = $?,
email = $?, email = $?,
showemail = $?, showemail = $?,
darktheme = $?,
blurb = $?, blurb = $?,
signature = $?, signature = $?,
bio = $? bio = $?
@ -344,7 +340,6 @@ func UserSettingsSave(c *RequestContext) ResponseData {
name, name,
email, email,
showEmail, showEmail,
darkTheme,
blurb, blurb,
signature, signature,
bio, bio,

View File

@ -54,3 +54,5 @@
- Threads? - Threads?
- TikTok? - TikTok?
- Trello? - Trello?
- [ ] Handle empty avatar URLs correctly in various places (render as theme-dependent default)
- [ ] Resolve TODO(redesign) comments