[chore/frontend] Refactor status templates slightly, put polls behind CWs if present (#2419)

* [chore/frontend] Reorder templates, allow polls to be inside content warnings

* show when multiple-choice
This commit is contained in:
tobi 2023-12-05 12:43:07 +01:00 committed by GitHub
parent 18d850ebae
commit dacfd413dc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 245 additions and 180 deletions

View file

@ -90,6 +90,12 @@ type Attachment struct {
// A hash computed by the BlurHash algorithm, for generating colorful preview thumbnails when media has not been downloaded yet.
// See https://github.com/woltapp/blurhash
Blurhash *string `json:"blurhash"`
// Additional fields not exposed via JSON
// (used only internally for templating etc).
// Parent status of this media is sensitive.
Sensitive bool `json:"-"`
}
// MediaMeta models media metadata.

View file

@ -721,6 +721,12 @@ func (c *Converter) StatusToWebStatus(
webStatus.WebPollOptions = webPollOptions
}
// Set additional templating
// variables on media attachments.
for _, a := range webStatus.MediaAttachments {
a.Sensitive = webStatus.Sensitive
}
return webStatus, nil
}

View file

@ -113,10 +113,17 @@ main {
gap: 0.5rem;
}
details > summary {
.text-spoiler > summary, .text {
position: relative;
z-index: 2;
}
.text-spoiler > summary {
display: inline-block;
list-style: none;
padding-bottom: 0.5rem;
&::-webkit-details-marker {
display: none; /* Safari */
}
@ -124,6 +131,8 @@ main {
.button {
white-space: nowrap;
cursor: pointer;
padding: 0.2rem 0.3rem;
font-size: 1rem;
}
}
@ -132,20 +141,12 @@ main {
grid-row: span 1;
grid-column: 1 / span 3;
position: relative;
z-index: 2;
display: flex;
flex-direction: column;
gap: 0.5rem;
width: 100%;
details > summary {
padding-bottom: 0.5rem;
.button {
padding: 0.2rem 0.3rem;
font-size: 1rem;
}
}
a {
color: $link-fg;
text-decoration: underline;
@ -239,6 +240,64 @@ main {
border: $boxshadow-border;
border-radius: $br-inner;
}
.poll {
background-color: $gray2;
z-index: 2;
display: flex;
flex-direction: column;
border-radius: $br;
padding: 0.5rem;
margin: 0;
gap: 1rem;
.poll-options {
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: 1rem;
.poll-option {
display: flex;
flex-direction: column;
gap: 0.1rem;
label {
cursor: default;
}
meter {
width: 100%;
}
.poll-vote-summary {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
white-space: nowrap;
}
}
}
.poll-info {
background-color: $gray4;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
border-radius: $br-inner;
padding: 0.25rem;
gap: 0.25rem;
span {
justify-self: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
}
.media {
@ -391,64 +450,6 @@ main {
}
}
.poll {
background-color: $gray2;
z-index: 2;
display: flex;
flex-direction: column;
border-radius: $br;
padding: 0.5rem;
margin: 0;
gap: 1rem;
.poll-options {
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: 1rem;
.poll-option {
display: flex;
flex-direction: column;
gap: 0.1rem;
label {
cursor: default;
}
meter {
width: 100%;
}
.poll-vote-summary {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
white-space: nowrap;
}
}
}
.poll-info {
background-color: $gray4;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
border-radius: $br-inner;
padding: 0.25rem;
gap: 0.25rem;
span {
justify-self: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
.info {
display: flex;
background: $toot-info-bg;

View file

@ -17,127 +17,80 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ -}}
<a data-nosnippet href="{{- .URL -}}" class="toot-link">Open thread</a>
<section class="author">
<a href="{{.Account.URL}}">
<img class="avatar" src="{{.Account.Avatar}}" alt="">
<span class="displayname">
{{if .Account.DisplayName}}
{{emojify .Account.Emojis (escape .Account.DisplayName)}}
{{else}}
{{.Account.Username}}
{{end}}
<span class="sr-only">.</span>
<a href="{{- .Account.URL -}}">
<img class="avatar" src="{{- .Account.Avatar -}}" alt="">
<span aria-hidden="true" class="displayname">
{{- if .Account.DisplayName -}}
{{- emojify .Account.Emojis (escape .Account.DisplayName) -}}
{{- else -}}
{{- .Account.Username -}}
{{- end -}}
</span>
<span aria-hidden="true" class="username">@{{- .Account.Username -}}</span>
<span class="sr-only">
{{- if .Account.DisplayName -}}
{{- emojify .Account.Emojis (escape .Account.DisplayName) -}}. Username: @{{ .Account.Acct -}}.
{{- else -}}
@{{- .Account.Acct -}}.
{{- end -}}
</span>
<span class="username">@{{.Account.Username}}<span class="sr-only">, </span>{{acctInstance .Account.Acct}}</span>
</a>
</section>
<section class="body">
<div class="text">
{{if .SpoilerText}}
<details class="text-spoiler">
<summary>
<span class="spoiler-text" lang="{{ .LanguageTag.TagStr }}">{{emojify .Emojis (escape .SpoilerText)}}</span>
<span class="button" role="button" tabindex="0">Toggle visibility</span>
</summary>
<div class="content" lang="{{ .LanguageTag.TagStr }}">
{{emojify .Emojis (noescape .Content)}}
{{- if .SpoilerText }}
<details class="text-spoiler">
<summary>
<span class="spoiler-text" lang="{{- .LanguageTag.TagStr -}}">{{- emojify .Emojis (escape .SpoilerText) -}}</span>
<span class="button" role="button" tabindex="0">Toggle visibility</span>
</summary>
<div class="text">
<div class="content" lang="{{- .LanguageTag.TagStr -}}">
{{ emojify .Emojis (noescape .Content) }}
</div>
</details>
{{else}}
<div class="content" lang="{{ .LanguageTag.TagStr }}">
{{emojify .Emojis (noescape .Content)}}
{{- if .Poll }}
{{ template "status_poll.tmpl" . }}
{{- end }}
</div>
{{end}}
</details>
{{- else }}
<div class="text">
<div class="content" lang="{{- .LanguageTag.TagStr -}}">
{{ emojify .Emojis (noescape .Content) }}
</div>
{{- if .Poll }}
{{ template "status_poll.tmpl" . }}
{{- end }}
</div>
{{with .MediaAttachments}}
<div
class="media photoswipe-gallery {{(len .) | oddOrEven }}{{if eq (len .) 1}} single{{end}}{{if eq (len .) 2}} double{{end}}">
{{range $index, $media := .}}
{{with $media}}
<div class="media-wrapper">
<details class="{{.Type}}-spoiler media-spoiler" {{if not $.Sensitive}}open{{end}}>
<summary>
<div class="show sensitive button" aria-hidden="true">
Show sensitive media
</div>
<span class="eye button" role="button" tabindex="0" aria-label="Toggle media">
<i class="hide fa fa-fw fa-eye-slash" aria-hidden="true"></i>
<i class="show fa fa-fw fa-eye" aria-hidden="true"></i>
</span>
{{if eq .Type "video"}}
<video {{if .Description}} title="{{.Description}}" {{end}}>
<source type="video/mp4" src="{{.URL}}" />
</video>
{{else if eq .Type "image"}}
<img {{if .Description}} title="{{.Description}}" {{end}} src="{{.PreviewURL}}" />
{{end}}
</summary>
{{if eq .Type "video"}}
<video class="plyr-video photoswipe-slide" controls {{if .Description}}alt="{{.Description}}"
title="{{.Description}}" {{end}} data-pswp-index="{{$index}}" data-pswp-width="{{.Meta.Original.Width}}px"
data-pswp-height="{{.Meta.Original.Height}}px">
<source type="video/mp4" src="{{.URL}}" />
</video>
{{else if eq .Type "image"}}
<a class="photoswipe-slide" href="{{.URL}}" target="_blank" {{if .Description}}title="{{.Description}}" {{end}}
data-pswp-width="{{.Meta.Original.Width}}px" data-pswp-height="{{.Meta.Original.Height}}px"
data-cropped="true">
<img src="{{.PreviewURL}}" {{if .Description}}alt="{{.Description}}" {{end}} />
</a>
{{else}}
<a
class="unknown-attachment"
href="{{.RemoteURL}}"
target="_blank"
{{if .Description}}
title="Link to external media: {{.Description}}&#10;&#13;{{.RemoteURL}}"
{{else}}
title="Link to external media.&#10;&#13;{{.RemoteURL}}"
{{end}}
>
<div class="placeholder" aria-hidden="true">
<i class="placeholder-external-link fa fa-external-link"></i>
<i class="placeholder-icon fa fa-file-text"></i>
<div class="placeholder-link-to">External media</div>
</div>
</a>
{{end}}
</details>
</div>
{{end}}
{{end}}
</div>
{{end}}
{{- if .Poll -}}{{ template "poll.tmpl" . }}{{ end -}}
{{- end }}
{{- if .MediaAttachments }}
{{ template "status_attachments.tmpl" . }}
{{- end }}
</section>
<aside class="info">
<time datetime="{{.CreatedAt}}">{{.CreatedAt | timestampPrecise}}</time>
<time datetime="{{- .CreatedAt -}}">{{- .CreatedAt | timestampPrecise -}}</time>
<div class="stats" role="group">
<div class="stats-item">
<span aria-hidden="true"><i class="fa fa-reply-all"></i> {{.RepliesCount}}</span>
<span class="sr-only">{{.RepliesCount}} {{if .RepliesCount | eq 1}}reply{{else}}replies{{end}}</span>
<span aria-hidden="true"><i class="fa fa-reply-all"></i> {{ .RepliesCount -}}</span>
<span class="sr-only">{{- .RepliesCount }} {{ if .RepliesCount | eq 1 }}reply{{ else }}replies{{ end -}}</span>
</div>
<div class="stats-item">
<span aria-hidden="true"><i class="fa fa-star"></i> {{.FavouritesCount}}</span>
<span class="sr-only">{{.FavouritesCount}} favourite{{if .FavouritesCount | eq 1 | not}}s{{end}}</span>
<span aria-hidden="true"><i class="fa fa-star"></i> {{ .FavouritesCount -}}</span>
<span class="sr-only">{{- .FavouritesCount }} {{ if .FavouritesCount | eq 1 }}favourite{{ else }}favourites{{ end -}}</span>
</div>
<div class="stats-item">
<span aria-hidden="true"><i class="fa fa-retweet"></i> {{.ReblogsCount}}</span>
<span class="sr-only">{{.ReblogsCount}} boost{{if .ReblogsCount | eq 1 | not}}s{{end}}</span>
<span aria-hidden="true"><i class="fa fa-retweet"></i> {{ .ReblogsCount -}}</span>
<span class="sr-only">{{- .ReblogsCount }} {{ if .ReblogsCount | eq 1 }}boost{{ else }}boosts{{ end -}}</span>
</div>
{{if .Pinned}}
<div class="stats-item">
<i class="fa fa-thumb-tack" aria-hidden="true"></i>
<span class="sr-only">pinned</span>
</div>
{{end}}
{{ if .LanguageTag.DisplayStr }}
<div class="stats-item language" title="Language: {{ .LanguageTag.DisplayStr }}">
{{ .LanguageTag.TagStr }}
</div>
{{ end }}
{{- if .Pinned }}
<div class="stats-item">
<i class="fa fa-thumb-tack" aria-hidden="true"></i>
<span class="sr-only">pinned</span>
</div>
{{- end }}
{{- if .LanguageTag.DisplayStr }}
<div class="stats-item language" title="Language: {{ .LanguageTag.DisplayStr }}">{{ .LanguageTag.TagStr }}</div>
{{- end }}
</div>
</aside>
<a data-nosnippet href="{{.URL}}" class="toot-link">Open
thread</a>

View file

@ -0,0 +1,94 @@
{{- /*
// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ -}}
{{- /*
Template for rendering a gallery of status media attachments.
To use this template, pass a web view status into it.
*/ -}}
{{ with .MediaAttachments }}
<div class="media photoswipe-gallery {{ (len .) | oddOrEven }} {{ if eq (len .) 1 }}single{{ else if eq (len .) 2 }}double{{- end -}}">
{{- range $index, $media := . }}
<div class="media-wrapper">
<details class="{{- $media.Type -}}-spoiler media-spoiler" {{- if not $media.Sensitive }} open{{ end -}}>
<summary>
<div class="show sensitive button" aria-hidden="true">Show sensitive media</div>
<span class="eye button" role="button" tabindex="0" aria-label="Toggle media">
<i class="hide fa fa-fw fa-eye-slash" aria-hidden="true"></i>
<i class="show fa fa-fw fa-eye" aria-hidden="true"></i>
</span>
{{- if eq .Type "video" }}
<video {{- if .Description }} title="{{- $media.Description -}}" {{- end -}}>
<source type="video/mp4" src="{{- $media.URL -}}"/>
</video>
{{- else if eq .Type "image" }}
<img src="{{- $media.PreviewURL -}}" {{- if .Description }} title="{{- $media.Description -}}" {{- end }}/>
{{- end }}
</summary>
{{- if eq .Type "video" }}
<video
class="plyr-video photoswipe-slide"
controls
data-pswp-index="{{- $index -}}"
data-pswp-width="{{- $media.Meta.Original.Width -}}px"
data-pswp-height="{{- $media.Meta.Original.Height -}}px"
{{- if .Description }}
alt="{{- $media.Description -}}"
title="{{- $media.Description -}}"
{{- end }}
>
<source type="video/mp4" src="{{- $media.URL -}}"/>
</video>
{{- else if eq .Type "image" }}
<a
class="photoswipe-slide"
href="{{- $media.URL -}}"
target="_blank"
data-pswp-width="{{- $media.Meta.Original.Width -}}px"
data-pswp-height="{{- $media.Meta.Original.Height -}}px"
data-cropped="true"
{{- if .Description }}
title="{{- $media.Description -}}"
{{- end }}
>
<img src="{{$media.PreviewURL}}" {{if .Description}}alt="{{$media.Description}}" {{end}} />
</a>
{{- else }}
<a
class="unknown-attachment"
href="{{- $media.RemoteURL -}}"
target="_blank"
{{- if .Description }}
title="Link to external media: {{ $media.Description -}}&#10;&#13;{{- $media.RemoteURL -}}"
{{- else }}
title="Link to external media.&#10;&#13;{{- $media.RemoteURL -}}"
{{- end }}
>
<div class="placeholder" aria-hidden="true">
<i class="placeholder-external-link fa fa-external-link"></i>
<i class="placeholder-icon fa fa-file-text"></i>
<div class="placeholder-link-to">External media</div>
</div>
</a>
{{- end }}
</details>
</div>
{{- end }}
</div>
{{- end }}

View file

@ -25,12 +25,17 @@
<figure class="poll">
<figcaption class="poll-info">
<span class="poll-expiry">
{{- if .Poll.Expired -}}
Poll closed&nbsp;{{- .Poll.ExpiresAt | timestampPrecise -}}
{{- else if .Poll.ExpiresAt -}}
Poll open until&nbsp;{{- .Poll.ExpiresAt | timestampPrecise -}}
{{- if .Poll.Multiple -}}
Multiple-choice poll&nbsp;
{{- else -}}
Infinite poll (no expiry)
Poll&nbsp;
{{- end -}}
{{- if .Poll.Expired -}}
closed {{ .Poll.ExpiresAt | timestampPrecise -}}
{{- else if .Poll.ExpiresAt -}}
open until {{ .Poll.ExpiresAt | timestampPrecise -}}
{{- else -}}
open forever
{{- end -}}
</span>
<span class="total-votes">Total votes: {{ .Poll.VotesCount }}</span>