From 027a93facc73b78e3c3747ab796f4a14b1b4936f Mon Sep 17 00:00:00 2001
From: tobi <31960611+tsmethurst@users.noreply.github.com>
Date: Sun, 21 Jul 2024 14:22:08 +0200
Subject: [PATCH] [feature/frontend] Respect `prefers-reduced-motion` for
avatars, headers, and emojis (#3118)
* [feature/frontend] Respect `prefers-reduced-motion` for avatars, headers, and emojis
* go fmt
* fix tests
* use static version of instance thumbnail when appropriate
* use prefers-reduced-motion
* simplify account conversion a bit
* fix c&p error
---
docs/api/swagger.yaml | 22 ++++
.../api/client/instance/instancepatch_test.go | 4 +
internal/api/model/account.go | 24 ++--
internal/api/model/attachment.go | 4 +
internal/api/model/instancev1.go | 6 +
internal/api/model/instancev2.go | 7 ++
internal/api/model/status.go | 3 +
internal/api/util/opengraph.go | 4 +-
internal/api/util/opengraph_test.go | 12 +-
internal/processing/account/get.go | 2 +-
internal/processing/account/rss_test.go | 116 +++++++++++++++++-
internal/text/emojify.go | 80 ++++++++----
internal/typeutils/internaltofrontend.go | 108 ++++++++++++----
internal/typeutils/internaltofrontend_test.go | 53 ++++----
internal/typeutils/internaltorss_test.go | 2 +-
internal/web/thread.go | 2 +-
web/source/css/base.css | 26 ++--
web/source/css/index.css | 3 +-
web/source/css/page.css | 3 +-
web/source/css/status.css | 8 --
web/template/page.tmpl | 2 +-
web/template/page_header.tmpl | 19 ++-
web/template/profile.tmpl | 47 +++++--
web/template/status_header.tmpl | 18 ++-
24 files changed, 435 insertions(+), 140 deletions(-)
diff --git a/docs/api/swagger.yaml b/docs/api/swagger.yaml
index 66f7e53a5..9fcc8bab3 100644
--- a/docs/api/swagger.yaml
+++ b/docs/api/swagger.yaml
@@ -1526,6 +1526,16 @@ definitions:
example: picture of a cute lil' friendly sloth
type: string
x-go-name: ThumbnailDescription
+ thumbnail_static:
+ description: URL of the static instance avatar/banner image.
+ example: https://example.org/files/instance/static/thumbnail.webp
+ type: string
+ x-go-name: ThumbnailStatic
+ thumbnail_static_type:
+ description: MIME type of the static instance thumbnail.
+ example: image/webp
+ type: string
+ x-go-name: ThumbnailStaticType
thumbnail_type:
description: MIME type of the instance thumbnail.
example: image/png
@@ -1759,6 +1769,11 @@ definitions:
example: UeKUpFxuo~R%0nW;WCnhF6RjaJt757oJodS$
type: string
x-go-name: Blurhash
+ static_url:
+ description: StaticURL version of the thumbnail image.
+ example: https://example.org/fileserver/01BPSX2MKCRVMD4YN4D71G9CP5/attachment/static/01H88X0KQ2DFYYDSWYP93VDJZA.webp
+ type: string
+ x-go-name: StaticURL
thumbnail_description:
description: |-
Description of the instance thumbnail.
@@ -1766,6 +1781,13 @@ definitions:
example: picture of a cute lil' friendly sloth
type: string
x-go-name: Description
+ thumbnail_static_type:
+ description: |-
+ MIME type of the instance thumbnail.
+ Key/value not set if thumbnail image type unknown.
+ example: image/png
+ type: string
+ x-go-name: StaticType
thumbnail_type:
description: |-
MIME type of the instance thumbnail.
diff --git a/internal/api/client/instance/instancepatch_test.go b/internal/api/client/instance/instancepatch_test.go
index ba0d026f3..e68508fc2 100644
--- a/internal/api/client/instance/instancepatch_test.go
+++ b/internal/api/client/instance/instancepatch_test.go
@@ -762,6 +762,8 @@ func (suite *InstancePatchTestSuite) TestInstancePatch8() {
},
"thumbnail": "http://localhost:8080/fileserver/01AY6P665V14JJR0AFVRT7311Y/attachment/original/`+instanceAccount.AvatarMediaAttachment.ID+`.gif",`+`
"thumbnail_type": "image/gif",
+ "thumbnail_static": "http://localhost:8080/fileserver/01AY6P665V14JJR0AFVRT7311Y/attachment/small/`+instanceAccount.AvatarMediaAttachment.ID+`.webp",`+`
+ "thumbnail_static_type": "image/webp",
"thumbnail_description": "A bouncing little green peglin.",
"contact_account": {
"id": "01F8MH17FWEB39HZJ76B6VXSKF",
@@ -818,6 +820,8 @@ func (suite *InstancePatchTestSuite) TestInstancePatch8() {
suite.Equal(`{
"url": "http://localhost:8080/fileserver/01AY6P665V14JJR0AFVRT7311Y/attachment/original/`+instanceAccount.AvatarMediaAttachment.ID+`.gif",`+`
"thumbnail_type": "image/gif",
+ "static_url": "http://localhost:8080/fileserver/01AY6P665V14JJR0AFVRT7311Y/attachment/small/`+instanceAccount.AvatarMediaAttachment.ID+`.webp",`+`
+ "thumbnail_static_type": "image/webp",
"thumbnail_description": "A bouncing little green peglin.",
"blurhash": "LE9kG#M}4YtO%dRkWEt5Dmoxx?WC"
}`, string(instanceV2ThumbnailJson))
diff --git a/internal/api/model/account.go b/internal/api/model/account.go
index cf39dd08e..c5b629db0 100644
--- a/internal/api/model/account.go
+++ b/internal/api/model/account.go
@@ -110,17 +110,27 @@ type Account struct {
// If set, indicates that this account is currently inactive, and has migrated to the given account.
// Key/value omitted for accounts that haven't moved, and for suspended accounts.
Moved *Account `json:"moved,omitempty"`
+}
- // Additional fields not exposed via JSON
- // (used only internally for templating etc).
+// WebAccount is like Account, but with
+// additional fields not exposed via JSON;
+// used only internally for templating etc.
+//
+// swagger:ignore
+type WebAccount struct {
+ *Account
// Proper attachment model for the avatar.
//
- // Only set if this model was converted via
- // AccountToWebAccount, AND this account had
- // an avatar set (and not just the default
- // "blank" avatar image.)
- AvatarAttachment *Attachment `json:"-"`
+ // Only set if this account had an avatar set
+ // (and not just the default "blank" image.)
+ AvatarAttachment *WebAttachment `json:"-"`
+
+ // Proper attachment model for the header.
+ //
+ // Only set if this account had a header set
+ // (and not just the default "blank" image.)
+ HeaderAttachment *WebAttachment `json:"-"`
}
// MutedAccount extends Account with a field used only by the muted user list.
diff --git a/internal/api/model/attachment.go b/internal/api/model/attachment.go
index d0b0c81e5..21523a58e 100644
--- a/internal/api/model/attachment.go
+++ b/internal/api/model/attachment.go
@@ -107,6 +107,10 @@ type WebAttachment struct {
// MIME type of
// the attachment.
MIMEType string
+
+ // MIME type of
+ // the thumbnail.
+ PreviewMIMEType string
}
// MediaMeta models media metadata.
diff --git a/internal/api/model/instancev1.go b/internal/api/model/instancev1.go
index beb4f430d..efa6d6faa 100644
--- a/internal/api/model/instancev1.go
+++ b/internal/api/model/instancev1.go
@@ -85,6 +85,12 @@ type InstanceV1 struct {
// MIME type of the instance thumbnail.
// example: image/png
ThumbnailType string `json:"thumbnail_type,omitempty"`
+ // URL of the static instance avatar/banner image.
+ // example: https://example.org/files/instance/static/thumbnail.webp
+ ThumbnailStatic string `json:"thumbnail_static,omitempty"`
+ // MIME type of the static instance thumbnail.
+ // example: image/webp
+ ThumbnailStaticType string `json:"thumbnail_static_type,omitempty"`
// Description of the instance thumbnail.
// example: picture of a cute lil' friendly sloth
ThumbnailDescription string `json:"thumbnail_description,omitempty"`
diff --git a/internal/api/model/instancev2.go b/internal/api/model/instancev2.go
index fce801117..8d6873497 100644
--- a/internal/api/model/instancev2.go
+++ b/internal/api/model/instancev2.go
@@ -102,6 +102,13 @@ type InstanceV2Thumbnail struct {
// Key/value not set if thumbnail image type unknown.
// example: image/png
Type string `json:"thumbnail_type,omitempty"`
+ // StaticURL version of the thumbnail image.
+ // example: https://example.org/fileserver/01BPSX2MKCRVMD4YN4D71G9CP5/attachment/static/01H88X0KQ2DFYYDSWYP93VDJZA.webp
+ StaticURL string `json:"static_url,omitempty"`
+ // MIME type of the instance thumbnail.
+ // Key/value not set if thumbnail image type unknown.
+ // example: image/png
+ StaticType string `json:"thumbnail_static_type,omitempty"`
// Description of the instance thumbnail.
// Key/value not set if no description available.
// example: picture of a cute lil' friendly sloth
diff --git a/internal/api/model/status.go b/internal/api/model/status.go
index 7358916ab..b3ac746d7 100644
--- a/internal/api/model/status.go
+++ b/internal/api/model/status.go
@@ -113,6 +113,9 @@ type Status struct {
type WebStatus struct {
*Status
+ // Override API account with web account.
+ Account *WebAccount `json:"account"`
+
// Web version of media
// attached to this status.
MediaAttachments []*WebAttachment `json:"media_attachments"`
diff --git a/internal/api/util/opengraph.go b/internal/api/util/opengraph.go
index 062151836..094c80021 100644
--- a/internal/api/util/opengraph.go
+++ b/internal/api/util/opengraph.go
@@ -84,7 +84,7 @@ func OGBase(instance *apimodel.InstanceV1) *OGMeta {
// WithAccount uses the given account to build an ogMeta
// struct specific to that account. It's suitable for serving
// at account profile pages.
-func (og *OGMeta) WithAccount(account *apimodel.Account) *OGMeta {
+func (og *OGMeta) WithAccount(account *apimodel.WebAccount) *OGMeta {
og.Title = AccountTitle(account, og.SiteName)
og.Type = "profile"
og.URL = account.URL
@@ -148,7 +148,7 @@ func (og *OGMeta) WithStatus(status *apimodel.WebStatus) *OGMeta {
}
// AccountTitle parses a page title from account and accountDomain
-func AccountTitle(account *apimodel.Account, accountDomain string) string {
+func AccountTitle(account *apimodel.WebAccount, accountDomain string) string {
user := "@" + account.Acct + "@" + accountDomain
if len(account.DisplayName) == 0 {
diff --git a/internal/api/util/opengraph_test.go b/internal/api/util/opengraph_test.go
index 2ecd6a740..4e94d78ef 100644
--- a/internal/api/util/opengraph_test.go
+++ b/internal/api/util/opengraph_test.go
@@ -51,13 +51,15 @@ func (suite *OpenGraphTestSuite) TestWithAccountWithNote() {
Languages: []string{"en"},
})
- accountMeta := baseMeta.WithAccount(&apimodel.Account{
+ acct := &apimodel.Account{
Acct: "example_account",
DisplayName: "example person!!",
URL: "https://example.org/@example_account",
Note: "
This is my profile, read it and weep! Weep then!
",
Username: "example_account",
- })
+ }
+
+ accountMeta := baseMeta.WithAccount(&apimodel.WebAccount{Account: acct})
suite.EqualValues(OGMeta{
Title: "example person!!, @example_account@example.org",
@@ -84,13 +86,15 @@ func (suite *OpenGraphTestSuite) TestWithAccountNoNote() {
Languages: []string{"en"},
})
- accountMeta := baseMeta.WithAccount(&apimodel.Account{
+ acct := &apimodel.Account{
Acct: "example_account",
DisplayName: "example person!!",
URL: "https://example.org/@example_account",
Note: "", // <- empty
Username: "example_account",
- })
+ }
+
+ accountMeta := baseMeta.WithAccount(&apimodel.WebAccount{Account: acct})
suite.EqualValues(OGMeta{
Title: "example person!!, @example_account@example.org",
diff --git a/internal/processing/account/get.go b/internal/processing/account/get.go
index 32d45054d..eac0f0c3f 100644
--- a/internal/processing/account/get.go
+++ b/internal/processing/account/get.go
@@ -98,7 +98,7 @@ func (p *Processor) Get(ctx context.Context, requestingAccount *gtsmodel.Account
}
// GetWeb returns the web model of a local account by username.
-func (p *Processor) GetWeb(ctx context.Context, username string) (*apimodel.Account, gtserror.WithCode) {
+func (p *Processor) GetWeb(ctx context.Context, username string) (*apimodel.WebAccount, gtserror.WithCode) {
targetAccount, err := p.state.DB.GetAccountByUsernameDomain(ctx, username, "")
if err != nil {
if errors.Is(err, db.ErrNoEntries) {
diff --git a/internal/processing/account/rss_test.go b/internal/processing/account/rss_test.go
index 0b1ae561d..e4706d3b7 100644
--- a/internal/processing/account/rss_test.go
+++ b/internal/processing/account/rss_test.go
@@ -35,7 +35,36 @@ func (suite *GetRSSTestSuite) TestGetAccountRSSAdmin() {
feed, err := getFeed()
suite.NoError(err)
- suite.Equal("\n \n Posts from @admin@localhost:8080\n http://localhost:8080/@admin\n Posts from @admin@localhost:8080\n Wed, 20 Oct 2021 10:41:37 +0000\n Wed, 20 Oct 2021 10:41:37 +0000\n - \n open to see some puppies\n http://localhost:8080/@admin/statuses/01F8MHAAY43M6RJ473VQFCVH37\n @admin@localhost:8080 made a new post: "🐕🐕🐕🐕🐕"\n \n @admin@localhost:8080\n http://localhost:8080/@admin/statuses/01F8MHAAY43M6RJ473VQFCVH37\n Wed, 20 Oct 2021 12:36:45 +0000\n \n
\n - \n hello world! #welcome ! first post on the instance :rainbow: !\n http://localhost:8080/@admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R\n @admin@localhost:8080 posted 1 attachment: "hello world! #welcome ! first post on the instance :rainbow: !"\n !]]>\n @admin@localhost:8080\n \n http://localhost:8080/@admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R\n Wed, 20 Oct 2021 11:36:45 +0000\n \n
\n \n", feed)
+ suite.Equal(`
+
+ Posts from @admin@localhost:8080
+ http://localhost:8080/@admin
+ Posts from @admin@localhost:8080
+ Wed, 20 Oct 2021 10:41:37 +0000
+ Wed, 20 Oct 2021 10:41:37 +0000
+ -
+ open to see some puppies
+ http://localhost:8080/@admin/statuses/01F8MHAAY43M6RJ473VQFCVH37
+ @admin@localhost:8080 made a new post: "🐕🐕🐕🐕🐕"
+
+ @admin@localhost:8080
+ http://localhost:8080/@admin/statuses/01F8MHAAY43M6RJ473VQFCVH37
+ Wed, 20 Oct 2021 12:36:45 +0000
+
+
+ -
+ hello world! #welcome ! first post on the instance :rainbow: !
+ http://localhost:8080/@admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R
+ @admin@localhost:8080 posted 1 attachment: "hello world! #welcome ! first post on the instance :rainbow: !"
+ !]]>
+ @admin@localhost:8080
+
+ http://localhost:8080/@admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R
+ Wed, 20 Oct 2021 11:36:45 +0000
+
+
+
+`, feed)
}
func (suite *GetRSSTestSuite) TestGetAccountRSSZork() {
@@ -45,7 +74,75 @@ func (suite *GetRSSTestSuite) TestGetAccountRSSZork() {
feed, err := getFeed()
suite.NoError(err)
- suite.Equal("\n \n Posts from @the_mighty_zork@localhost:8080\n http://localhost:8080/@the_mighty_zork\n Posts from @the_mighty_zork@localhost:8080\n Wed, 10 Jan 2024 09:24:00 +0000\n Wed, 10 Jan 2024 09:24:00 +0000\n \n http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/avatar/small/01F8MH58A357CV5K7R7TJMSH6S.webp\n Avatar for @the_mighty_zork@localhost:8080\n http://localhost:8080/@the_mighty_zork\n \n - \n HTML in post\n http://localhost:8080/@the_mighty_zork/statuses/01HH9KYNQPA416TNJ53NSATP40\n @the_mighty_zork@localhost:8080 made a new post: "Here's a bunch of HTML, read it and weep, weep then!
```html
<section class="about-user">
<div class="col-header">
<h2>About</h2>
</div>
<div class="fields">
<h3 class="sr-only">Fields</h3>
<dl>
...\n Here's a bunch of HTML, read it and weep, weep then!
<section class="about-user">\n <div class="col-header">\n <h2>About</h2>\n </div> \n <div class="fields">\n <h3 class="sr-only">Fields</h3>\n <dl>\n <div class="field">\n <dt>should you follow me?</dt>\n <dd>maybe!</dd>\n </div>\n <div class="field">\n <dt>age</dt>\n <dd>120</dd>\n </div>\n </dl>\n </div>\n <div class="bio">\n <h3 class="sr-only">Bio</h3>\n <p>i post about things that concern me</p>\n </div>\n <div class="sr-only" role="group">\n <h3 class="sr-only">Stats</h3>\n <span>Joined in Jun, 2022.</span>\n <span>8 posts.</span>\n <span>Followed by 1.</span>\n <span>Following 1.</span>\n </div>\n <div class="accountstats" aria-hidden="true">\n <b>Joined</b><time datetime="2022-06-04T13:12:00.000Z">Jun, 2022</time>\n <b>Posts</b><span>8</span>\n <b>Followed by</b><span>1</span>\n <b>Following</b><span>1</span>\n </div>\n</section>\n
There, hope you liked that!
]]>\n @the_mighty_zork@localhost:8080\n http://localhost:8080/@the_mighty_zork/statuses/01HH9KYNQPA416TNJ53NSATP40\n Sun, 10 Dec 2023 09:24:00 +0000\n \n \n - \n introduction post\n http://localhost:8080/@the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY\n @the_mighty_zork@localhost:8080 made a new post: "hello everyone!"\n \n @the_mighty_zork@localhost:8080\n http://localhost:8080/@the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY\n Wed, 20 Oct 2021 10:40:37 +0000\n \n
\n \n", feed)
+ suite.Equal(`
+
+ Posts from @the_mighty_zork@localhost:8080
+ http://localhost:8080/@the_mighty_zork
+ Posts from @the_mighty_zork@localhost:8080
+ Wed, 10 Jan 2024 09:24:00 +0000
+ Wed, 10 Jan 2024 09:24:00 +0000
+
+ http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/avatar/small/01F8MH58A357CV5K7R7TJMSH6S.webp
+ Avatar for @the_mighty_zork@localhost:8080
+ http://localhost:8080/@the_mighty_zork
+
+ -
+ HTML in post
+ http://localhost:8080/@the_mighty_zork/statuses/01HH9KYNQPA416TNJ53NSATP40
+ @the_mighty_zork@localhost:8080 made a new post: "Here's a bunch of HTML, read it and weep, weep then!
`+"```"+`html
<section class="about-user">
<div class="col-header">
<h2>About</h2>
</div>
<div class="fields">
<h3 class="sr-only">Fields</h3>
<dl>
...
+ Here's a bunch of HTML, read it and weep, weep then!
<section class="about-user">
+ <div class="col-header">
+ <h2>About</h2>
+ </div>
+ <div class="fields">
+ <h3 class="sr-only">Fields</h3>
+ <dl>
+ <div class="field">
+ <dt>should you follow me?</dt>
+ <dd>maybe!</dd>
+ </div>
+ <div class="field">
+ <dt>age</dt>
+ <dd>120</dd>
+ </div>
+ </dl>
+ </div>
+ <div class="bio">
+ <h3 class="sr-only">Bio</h3>
+ <p>i post about things that concern me</p>
+ </div>
+ <div class="sr-only" role="group">
+ <h3 class="sr-only">Stats</h3>
+ <span>Joined in Jun, 2022.</span>
+ <span>8 posts.</span>
+ <span>Followed by 1.</span>
+ <span>Following 1.</span>
+ </div>
+ <div class="accountstats" aria-hidden="true">
+ <b>Joined</b><time datetime="2022-06-04T13:12:00.000Z">Jun, 2022</time>
+ <b>Posts</b><span>8</span>
+ <b>Followed by</b><span>1</span>
+ <b>Following</b><span>1</span>
+ </div>
+</section>
+
There, hope you liked that!
]]>
+ @the_mighty_zork@localhost:8080
+ http://localhost:8080/@the_mighty_zork/statuses/01HH9KYNQPA416TNJ53NSATP40
+ Sun, 10 Dec 2023 09:24:00 +0000
+
+
+ -
+ introduction post
+ http://localhost:8080/@the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY
+ @the_mighty_zork@localhost:8080 made a new post: "hello everyone!"
+
+ @the_mighty_zork@localhost:8080
+ http://localhost:8080/@the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY
+ Wed, 20 Oct 2021 10:40:37 +0000
+
+
+
+`, feed)
}
func (suite *GetRSSTestSuite) TestGetAccountRSSZorkNoPosts() {
@@ -70,7 +167,20 @@ func (suite *GetRSSTestSuite) TestGetAccountRSSZorkNoPosts() {
feed, err := getFeed()
suite.NoError(err)
- suite.Equal("\n \n Posts from @the_mighty_zork@localhost:8080\n http://localhost:8080/@the_mighty_zork\n Posts from @the_mighty_zork@localhost:8080\n Fri, 20 May 2022 11:09:18 +0000\n Fri, 20 May 2022 11:09:18 +0000\n \n http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/avatar/small/01F8MH58A357CV5K7R7TJMSH6S.webp\n Avatar for @the_mighty_zork@localhost:8080\n http://localhost:8080/@the_mighty_zork\n \n \n", feed)
+ suite.Equal(`
+
+ Posts from @the_mighty_zork@localhost:8080
+ http://localhost:8080/@the_mighty_zork
+ Posts from @the_mighty_zork@localhost:8080
+ Fri, 20 May 2022 11:09:18 +0000
+ Fri, 20 May 2022 11:09:18 +0000
+
+ http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/avatar/small/01F8MH58A357CV5K7R7TJMSH6S.webp
+ Avatar for @the_mighty_zork@localhost:8080
+ http://localhost:8080/@the_mighty_zork
+
+
+`, feed)
}
func TestGetRSSTestSuite(t *testing.T) {
diff --git a/internal/text/emojify.go b/internal/text/emojify.go
index 23730eaf9..961ce8771 100644
--- a/internal/text/emojify.go
+++ b/internal/text/emojify.go
@@ -32,20 +32,44 @@ func EmojifyWeb(emojis []apimodel.Emoji, html template.HTML) template.HTML {
out := emojify(
emojis,
string(html),
- func(url, code string, buf *bytes.Buffer) {
- buf.WriteString(``)
+ func(url, staticURL, code string, buf *bytes.Buffer) {
+ // Open a picture tag so we
+ // can present multiple options.
+ buf.WriteString(``)
},
)
@@ -60,17 +84,18 @@ func EmojifyRSS(emojis []apimodel.Emoji, text string) string {
return emojify(
emojis,
text,
- func(url, code string, buf *bytes.Buffer) {
- buf.WriteString(``)
+ func(url, staticURL, code string, buf *bytes.Buffer) {
+ // Original image source.
+ buf.WriteString(``)
},
)
}
@@ -85,7 +110,7 @@ func Demojify(text string) string {
func emojify(
emojis []apimodel.Emoji,
input string,
- write func(url, code string, buf *bytes.Buffer),
+ write func(url, staticURL, code string, buf *bytes.Buffer),
) string {
// Build map of shortcodes. Normalize each
// shortcode by readding closing colons.
@@ -107,10 +132,11 @@ func(shortcode string, buf *bytes.Buffer) string {
// Escape raw emoji content.
url := html.EscapeString(emoji.URL)
+ staticURL := html.EscapeString(emoji.StaticURL)
code := html.EscapeString(emoji.Shortcode)
// Write emoji repr to buffer.
- write(url, code, buf)
+ write(url, staticURL, code, buf)
return buf.String()
},
)
diff --git a/internal/typeutils/internaltofrontend.go b/internal/typeutils/internaltofrontend.go
index f64f4acff..7d2889b05 100644
--- a/internal/typeutils/internaltofrontend.go
+++ b/internal/typeutils/internaltofrontend.go
@@ -170,22 +170,47 @@ func (c *Converter) AccountToAPIAccountPublic(ctx context.Context, a *gtsmodel.A
func (c *Converter) AccountToWebAccount(
ctx context.Context,
a *gtsmodel.Account,
-) (*apimodel.Account, error) {
- webAccount, err := c.AccountToAPIAccountPublic(ctx, a)
+) (*apimodel.WebAccount, error) {
+ apiAccount, err := c.AccountToAPIAccountPublic(ctx, a)
if err != nil {
return nil, err
}
+ webAccount := &apimodel.WebAccount{
+ Account: apiAccount,
+ }
+
// Set additional avatar information for
- // serving the avatar in a nice photobox.
- if a.AvatarMediaAttachment != nil {
- avatarAttachment, err := c.AttachmentToAPIAttachment(ctx, a.AvatarMediaAttachment)
+ // serving the avatar in a nice