* [feature] Allow user to choose "gallery" style web layout * find a bug and squish it up and all day long you'll have good luck * just a sec * [performance] reindex public timeline + tinker with query a bit * fiddling * should be good now * last bit of finagling, i'm done now i prommy * panic normallypull/3945/head
|
After Width: | Height: | Size: 947 KiB |
|
After Width: | Height: | Size: 793 KiB |
@ -0,0 +1,85 @@ |
|||||||
|
// 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/>.
|
||||||
|
|
||||||
|
package migrations |
||||||
|
|
||||||
|
import ( |
||||||
|
"context" |
||||||
|
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/log" |
||||||
|
"github.com/uptrace/bun" |
||||||
|
) |
||||||
|
|
||||||
|
func init() { |
||||||
|
up := func(ctx context.Context, db *bun.DB) error { |
||||||
|
return db.RunInTx(ctx, nil, func(ctx context.Context, tx bun.Tx) error { |
||||||
|
|
||||||
|
// Add new column to settings.
|
||||||
|
if _, err := tx. |
||||||
|
NewAddColumn(). |
||||||
|
Table("account_settings"). |
||||||
|
ColumnExpr( |
||||||
|
"? SMALLINT NOT NULL DEFAULT ?", |
||||||
|
bun.Ident("web_layout"), 1, |
||||||
|
). |
||||||
|
Exec(ctx); err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
// Drop existing statuses web index as it's out of date.
|
||||||
|
log.Info(ctx, "updating statuses_profile_web_view_idx, this may take a while, please wait!") |
||||||
|
if _, err := tx. |
||||||
|
NewDropIndex(). |
||||||
|
Index("statuses_profile_web_view_idx"). |
||||||
|
IfExists(). |
||||||
|
Exec(ctx); err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
// Note: "attachments" field is not included in
|
||||||
|
// the index below as SQLite is fussy about using it,
|
||||||
|
// and it prevents this index from being used
|
||||||
|
// properly in non media-only queries.
|
||||||
|
if _, err := tx. |
||||||
|
NewCreateIndex(). |
||||||
|
Table("statuses"). |
||||||
|
Index("statuses_profile_web_view_idx"). |
||||||
|
Column( |
||||||
|
"account_id", |
||||||
|
"visibility", |
||||||
|
"in_reply_to_uri", |
||||||
|
"boost_of_id", |
||||||
|
"federated", |
||||||
|
). |
||||||
|
ColumnExpr("? DESC", bun.Ident("id")). |
||||||
|
IfNotExists(). |
||||||
|
Exec(ctx); err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
return nil |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
down := func(ctx context.Context, db *bun.DB) error { |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
if err := Migrations.Register(up, down); err != nil { |
||||||
|
panic(err) |
||||||
|
} |
||||||
|
} |
||||||
|
After Width: | Height: | Size: 324 B |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 636 B |
|
After Width: | Height: | Size: 406 B |
|
After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 9.8 KiB |
|
After Width: | Height: | Size: 761 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 284 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 396 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 134 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 372 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 104 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 501 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 358 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
@ -0,0 +1,207 @@ |
|||||||
|
/* |
||||||
|
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/>. |
||||||
|
*/ |
||||||
|
|
||||||
|
@import "photoswipe/dist/photoswipe.css"; |
||||||
|
@import "photoswipe-dynamic-caption-plugin/photoswipe-dynamic-caption-plugin.css"; |
||||||
|
@import "plyr/dist/plyr.css"; |
||||||
|
|
||||||
|
.media-wrapper { |
||||||
|
height: 100%; |
||||||
|
width: 100%; |
||||||
|
box-sizing: border-box; |
||||||
|
border: 0.15rem solid $gray1; |
||||||
|
border-radius: $br; |
||||||
|
position: relative; |
||||||
|
overflow: hidden; |
||||||
|
z-index: 2; |
||||||
|
|
||||||
|
img { |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
object-fit: cover; |
||||||
|
} |
||||||
|
|
||||||
|
details { |
||||||
|
position: absolute; |
||||||
|
height: 100%; |
||||||
|
width: 100%; |
||||||
|
|
||||||
|
&[open] summary { |
||||||
|
height: auto; |
||||||
|
width: auto; |
||||||
|
margin: 1rem; |
||||||
|
padding: 0; |
||||||
|
|
||||||
|
.show, video, img { |
||||||
|
display: none; |
||||||
|
} |
||||||
|
|
||||||
|
.eye.button .hide { |
||||||
|
display: inline-block; |
||||||
|
grid-column: 1 / span 3; |
||||||
|
grid-row: 1 / span 2; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
summary { |
||||||
|
position: absolute; |
||||||
|
height: 100%; |
||||||
|
width: 100%; |
||||||
|
z-index: 3; |
||||||
|
overflow: hidden; |
||||||
|
|
||||||
|
display: grid; |
||||||
|
padding: 1rem; |
||||||
|
grid-template-columns: 1fr auto 1fr; |
||||||
|
grid-template-rows: 1fr 1fr; |
||||||
|
grid-template-areas: |
||||||
|
"eye sensitive ." |
||||||
|
". sensitive ."; |
||||||
|
|
||||||
|
&::-webkit-details-marker { |
||||||
|
display: none; /* Safari */ |
||||||
|
} |
||||||
|
|
||||||
|
.eye.button { |
||||||
|
grid-area: eye; |
||||||
|
align-self: start; |
||||||
|
justify-self: start; |
||||||
|
margin: 0; |
||||||
|
padding: 0.4rem; |
||||||
|
|
||||||
|
.fa-fw { |
||||||
|
line-height: $fa-fw; |
||||||
|
} |
||||||
|
|
||||||
|
.hide { |
||||||
|
display: none; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.show.sensitive { |
||||||
|
grid-area: sensitive; |
||||||
|
align-self: center; |
||||||
|
|
||||||
|
text-overflow: ellipsis; |
||||||
|
overflow: hidden; |
||||||
|
white-space: nowrap; |
||||||
|
|
||||||
|
.button { |
||||||
|
cursor: pointer; |
||||||
|
align-self: center; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
video, img { |
||||||
|
z-index: -1; |
||||||
|
position: absolute; |
||||||
|
height: calc(100% + 1.2rem); |
||||||
|
width: calc(100% + 1.2rem); |
||||||
|
top: -0.6rem; |
||||||
|
left: -0.6rem; |
||||||
|
filter: blur(1.2rem); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
video.plyr-video, .plyr { |
||||||
|
position: absolute; |
||||||
|
height: 100%; |
||||||
|
width: 100%; |
||||||
|
object-fit: contain; |
||||||
|
background: $gray1; |
||||||
|
} |
||||||
|
|
||||||
|
.unknown-attachment { |
||||||
|
.placeholder { |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
padding: 0.8rem; |
||||||
|
border: 0.2rem dashed $white2; |
||||||
|
|
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
align-items: center; |
||||||
|
gap: 0.25rem; |
||||||
|
|
||||||
|
color: $white2; |
||||||
|
|
||||||
|
.placeholder-external-link { |
||||||
|
align-self: end; |
||||||
|
font-size: 2.5rem; |
||||||
|
} |
||||||
|
|
||||||
|
.placeholder-icon { |
||||||
|
width: 100%; |
||||||
|
font-size: 3.5rem; |
||||||
|
text-align: center; |
||||||
|
margin-top: auto; |
||||||
|
} |
||||||
|
|
||||||
|
.placeholder-link-to { |
||||||
|
width: 100%; |
||||||
|
text-align: center; |
||||||
|
margin-bottom: auto; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.pswp__button--open-post-link { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
|
||||||
|
span > i { |
||||||
|
background: $status-bg; |
||||||
|
color: $fg; |
||||||
|
border-radius: 25%; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.plyr--video { |
||||||
|
flex-direction: column-reverse; |
||||||
|
|
||||||
|
.plyr__video-wrapper { |
||||||
|
position: relative; |
||||||
|
} |
||||||
|
|
||||||
|
.plyr__controls { |
||||||
|
align-self: stretch; |
||||||
|
position: initial; |
||||||
|
padding: 0.1rem; |
||||||
|
padding-top: 0.2rem; |
||||||
|
} |
||||||
|
|
||||||
|
.plyr__control { |
||||||
|
box-shadow: none; |
||||||
|
} |
||||||
|
|
||||||
|
.plyr__control--overlaid { |
||||||
|
top: calc(50% - 18px); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.pswp__content { |
||||||
|
padding: 2rem; |
||||||
|
|
||||||
|
.plyr { |
||||||
|
max-height: 100%; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,343 @@ |
|||||||
|
/* |
||||||
|
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/>. |
||||||
|
*/ |
||||||
|
|
||||||
|
.profile .profile-header { |
||||||
|
background: $profile-bg; |
||||||
|
border-radius: $br; |
||||||
|
overflow: hidden; |
||||||
|
margin-bottom: 1rem; |
||||||
|
|
||||||
|
.moved-to { |
||||||
|
padding: 1rem; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
|
||||||
|
.header-image-wrapper { |
||||||
|
position: relative; |
||||||
|
padding-top: 33.33%; /* aspect-ratio 1/3 */ |
||||||
|
|
||||||
|
img { |
||||||
|
position: absolute; |
||||||
|
top: 0; |
||||||
|
left: 0; |
||||||
|
right: 0; |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
object-fit: cover; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
Basic info container has the user's avatar, display- and username, and role |
||||||
|
It's partially overlapped over the header image, by a negative margin-top. |
||||||
|
*/ |
||||||
|
$avatar-size: 8.5rem; |
||||||
|
$name-size: 3rem; |
||||||
|
$username-size: 2rem; |
||||||
|
$overlap: calc($avatar-size - $name-size - $username-size); |
||||||
|
|
||||||
|
.basic-info { |
||||||
|
position: relative; |
||||||
|
display: grid; |
||||||
|
box-sizing: border-box; |
||||||
|
grid-template-columns: $avatar-size auto 1fr; |
||||||
|
grid-template-rows: $overlap $name-size auto; |
||||||
|
grid-template-areas: |
||||||
|
"avatar . ." |
||||||
|
"avatar namerole namerole" |
||||||
|
"avatar namerole namerole"; |
||||||
|
|
||||||
|
margin: 1rem; |
||||||
|
margin-top: calc(-1 * $overlap); |
||||||
|
gap: 0 1rem; |
||||||
|
|
||||||
|
.avatar-image-wrapper { |
||||||
|
grid-area: avatar; |
||||||
|
|
||||||
|
border: 0.2rem solid $avatar-border; |
||||||
|
border-radius: $br; |
||||||
|
|
||||||
|
/* |
||||||
|
Wrapper always same |
||||||
|
size + proportions no |
||||||
|
matter image inside. |
||||||
|
*/ |
||||||
|
height: $avatar-size; |
||||||
|
width: $avatar-size; |
||||||
|
|
||||||
|
.avatar { |
||||||
|
/* |
||||||
|
Fit 100% of the wrapper. |
||||||
|
*/ |
||||||
|
height: 100%; |
||||||
|
width: 100%; |
||||||
|
|
||||||
|
/* |
||||||
|
Normalize non-square images. |
||||||
|
*/ |
||||||
|
object-fit: cover; |
||||||
|
|
||||||
|
/* |
||||||
|
Prevent image extending |
||||||
|
beyond rounded borders. |
||||||
|
*/ |
||||||
|
border-radius: $br-inner; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.namerole { |
||||||
|
grid-area: namerole; |
||||||
|
|
||||||
|
display: grid; |
||||||
|
gap: 0 1rem; |
||||||
|
box-sizing: border-box; |
||||||
|
grid-template-columns: 1fr auto; |
||||||
|
grid-template-rows: $name-size auto; |
||||||
|
grid-template-areas: |
||||||
|
"displayname displayname" |
||||||
|
"username role"; |
||||||
|
|
||||||
|
.displayname { |
||||||
|
grid-area: displayname; |
||||||
|
line-height: $name-size; |
||||||
|
font-size: 1.5rem; |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
|
||||||
|
.bot-username-wrapper { |
||||||
|
display: flex; |
||||||
|
gap: 0.5rem; |
||||||
|
grid-area: username; |
||||||
|
align-items: center; |
||||||
|
|
||||||
|
.bot-legend-wrapper { |
||||||
|
display: flex; |
||||||
|
gap: 0.25rem; |
||||||
|
align-items: center; |
||||||
|
|
||||||
|
background: $bg; |
||||||
|
color: $fg; |
||||||
|
|
||||||
|
border-radius: $br; |
||||||
|
padding: 0.1rem 0.4rem 0.2rem 0.4rem; |
||||||
|
|
||||||
|
font-variant: small-caps; |
||||||
|
font-weight: bold; |
||||||
|
|
||||||
|
cursor: default; |
||||||
|
|
||||||
|
.bot-icon { |
||||||
|
/* |
||||||
|
FA icon is weirdly |
||||||
|
aligned so tweak it |
||||||
|
*/ |
||||||
|
margin-top: 0.25rem; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.username { |
||||||
|
min-width: 0; |
||||||
|
line-height: $username-size; |
||||||
|
|
||||||
|
font-size: 1rem; |
||||||
|
font-weight: bold; |
||||||
|
color: $fg-accent; |
||||||
|
user-select: all; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.role { |
||||||
|
background: $bg; |
||||||
|
color: $fg; |
||||||
|
border: 0.13rem solid $bg; |
||||||
|
|
||||||
|
grid-area: role; |
||||||
|
align-self: center; |
||||||
|
justify-self: start; |
||||||
|
border-radius: $br; |
||||||
|
padding: 0.3rem; |
||||||
|
|
||||||
|
line-height: 1.1rem; |
||||||
|
font-size: 0.9rem; |
||||||
|
font-variant: small-caps; |
||||||
|
font-weight: bold; |
||||||
|
|
||||||
|
&.admin { |
||||||
|
color: $role-admin; |
||||||
|
border-color: $role-admin; |
||||||
|
} |
||||||
|
|
||||||
|
&.moderator { |
||||||
|
color: $role-mod; |
||||||
|
border-color: $role-mod; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.profile .about-user { |
||||||
|
flex: 35 14rem; |
||||||
|
border-radius: $br; |
||||||
|
overflow: hidden; |
||||||
|
|
||||||
|
.col-header { |
||||||
|
margin-bottom: -0.25rem; |
||||||
|
} |
||||||
|
|
||||||
|
dt { |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
|
||||||
|
.fields { |
||||||
|
background: $profile-bg; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
padding: 0 0.5rem; |
||||||
|
padding-top: 0.25rem; |
||||||
|
|
||||||
|
.field { |
||||||
|
padding: 0.25rem; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
border-bottom: 0.1rem solid $gray2; |
||||||
|
|
||||||
|
> dt, > dd { |
||||||
|
word-break: break-word; |
||||||
|
} |
||||||
|
|
||||||
|
&:first-child { |
||||||
|
border-top: 0.1rem solid $gray2; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.bio { |
||||||
|
background: $profile-bg; |
||||||
|
padding: 1rem 0.75rem; |
||||||
|
padding-bottom: 1.25rem; |
||||||
|
} |
||||||
|
|
||||||
|
.accountstats { |
||||||
|
background: $bg-accent; |
||||||
|
padding: 0.75rem; |
||||||
|
|
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
gap: 0.25rem; |
||||||
|
|
||||||
|
.stats-item { |
||||||
|
display: flex; |
||||||
|
dt { |
||||||
|
width: 7rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
RSS icon isn't really part of the profile header exactly, |
||||||
|
but also it sort of is, and we want it styled the same for |
||||||
|
both microblog and gallery view anyway, so include it here. |
||||||
|
*/ |
||||||
|
.rss-icon { |
||||||
|
display: block; |
||||||
|
margin: -0.25rem 0; |
||||||
|
|
||||||
|
.fa { |
||||||
|
font-size: 2rem; |
||||||
|
object-fit: contain; |
||||||
|
vertical-align: middle; |
||||||
|
color: $orange2; |
||||||
|
/* |
||||||
|
Can't size a single-color background, so we use |
||||||
|
a linear-gradient that's effectively white. |
||||||
|
*/ |
||||||
|
background: linear-gradient(to right, $white1 100%, transparent 0) no-repeat center center; |
||||||
|
background-size: 1.2rem 1.4rem; |
||||||
|
/* light mode */ |
||||||
|
@media (prefers-color-scheme: light) { |
||||||
|
background: linear-gradient(to right, $white 100%, transparent 0) no-repeat center center; |
||||||
|
background-size: 1.2rem 1.4rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
Tablet-ish-kinda size. |
||||||
|
*/ |
||||||
|
@media screen and (max-width: 750px) { |
||||||
|
.profile .profile-header { |
||||||
|
.basic-info { |
||||||
|
grid-template-columns: auto 1fr; |
||||||
|
grid-template-rows: $avatar-size $name-size auto; |
||||||
|
grid-template-areas: |
||||||
|
"avatar avatar" |
||||||
|
"namerole namerole" |
||||||
|
"namerole namerole"; |
||||||
|
|
||||||
|
/* |
||||||
|
Make display name a bit smaller |
||||||
|
so there's more chance of being |
||||||
|
able to read everything. |
||||||
|
*/ |
||||||
|
.namerole { |
||||||
|
.displayname { |
||||||
|
font-size: 1.2rem; |
||||||
|
line-height: 2rem; |
||||||
|
margin-top: 0.5rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
Phone-ish-kinda size. |
||||||
|
*/ |
||||||
|
@media screen and (max-width: 500px) { |
||||||
|
.profile |
||||||
|
.profile-header |
||||||
|
.basic-info |
||||||
|
.namerole { |
||||||
|
/* |
||||||
|
Line up in smallest possible |
||||||
|
horizontal space to avoid overflow. |
||||||
|
*/ |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
gap: 0.5rem; |
||||||
|
|
||||||
|
/* |
||||||
|
Don't hug the right anymore |
||||||
|
(good life advice in general). |
||||||
|
*/ |
||||||
|
.role { |
||||||
|
align-self: flex-start; |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
Allow this to wrap in case |
||||||
|
of a really skinny screen. |
||||||
|
*/ |
||||||
|
.bot-username-wrapper { |
||||||
|
flex-wrap: wrap; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,44 @@ |
|||||||
|
/* |
||||||
|
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/>. |
||||||
|
*/ |
||||||
|
|
||||||
|
@import "./_media-wrapper.css"; |
||||||
|
|
||||||
|
.media { |
||||||
|
grid-column: span 3; |
||||||
|
display: grid; |
||||||
|
grid-template-columns: 50% 50%; |
||||||
|
grid-auto-rows: 10rem; |
||||||
|
overflow: hidden; |
||||||
|
|
||||||
|
&.single .media-wrapper { |
||||||
|
grid-column: span 2; |
||||||
|
} |
||||||
|
|
||||||
|
&.odd .media-wrapper:first-child, |
||||||
|
&.double .media-wrapper { |
||||||
|
grid-row: span 2; |
||||||
|
} |
||||||
|
|
||||||
|
@media screen and (max-width: 42rem) { |
||||||
|
.media-wrapper { |
||||||
|
grid-column: span 2; |
||||||
|
grid-row: span 2; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,108 @@ |
|||||||
|
/* |
||||||
|
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/>. |
||||||
|
*/ |
||||||
|
|
||||||
|
@import "./_profile-header.css"; |
||||||
|
@import "./_media-wrapper.css"; |
||||||
|
|
||||||
|
.page { |
||||||
|
/* |
||||||
|
Profile gallery can be wider than default. |
||||||
|
*/ |
||||||
|
grid-template-columns: 1fr min(95%, 65rem) 1fr; |
||||||
|
} |
||||||
|
|
||||||
|
.profile { |
||||||
|
.about-user { |
||||||
|
margin-bottom: 1rem; |
||||||
|
|
||||||
|
.accountstats { |
||||||
|
flex-direction: row; |
||||||
|
justify-content: space-between; |
||||||
|
|
||||||
|
.stats-item { |
||||||
|
gap: 0.5rem; |
||||||
|
width: 25%; |
||||||
|
justify-content: space-around; |
||||||
|
|
||||||
|
dt { |
||||||
|
width: fit-content; |
||||||
|
margin-left: auto; |
||||||
|
} |
||||||
|
|
||||||
|
dd { |
||||||
|
margin-right: auto; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@media screen and (max-width: 750px) { |
||||||
|
flex-direction: column; |
||||||
|
.stats-item { |
||||||
|
width: fit-content; |
||||||
|
dt { |
||||||
|
width: 7rem; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.media-galleries-wrapper { |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
gap: 1rem; |
||||||
|
min-width: 0%; |
||||||
|
|
||||||
|
.media-gallery { |
||||||
|
margin-top: 0.15rem; |
||||||
|
margin-bottom: 0.15rem; |
||||||
|
|
||||||
|
display: grid; |
||||||
|
gap: 0.15rem; |
||||||
|
|
||||||
|
/* Desktop-ish width, show 3 cols of media */ |
||||||
|
grid-template-columns: repeat(3, 1fr); |
||||||
|
|
||||||
|
@media screen and (max-width: 55rem) { |
||||||
|
/* Tablet-ish width, switch to 2 cols */ |
||||||
|
grid-template-columns: repeat(2, 1fr); |
||||||
|
} |
||||||
|
|
||||||
|
@media screen and (max-width: 36rem) { |
||||||
|
/* Mobile-ish width, switch to 1 col */ |
||||||
|
grid-template-columns: repeat(1, 1fr); |
||||||
|
} |
||||||
|
|
||||||
|
.media-wrapper { |
||||||
|
aspect-ratio: 4/3; |
||||||
|
border: 0; |
||||||
|
border-radius: 0; |
||||||
|
background: $bg; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.backnextlinks { |
||||||
|
display: flex; |
||||||
|
justify-content: space-between; |
||||||
|
|
||||||
|
.next { |
||||||
|
margin-left: auto; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,87 @@ |
|||||||
|
{{- /* |
||||||
|
// 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/>. |
||||||
|
*/ -}} |
||||||
|
|
||||||
|
{{- with . }} |
||||||
|
<main class="profile h-card"> |
||||||
|
{{- with . }} |
||||||
|
{{- include "profile_header.tmpl" . | indent 1 }} |
||||||
|
{{- end }} |
||||||
|
{{- with . }} |
||||||
|
{{- include "profile_about_user.tmpl" . | indent 1 }} |
||||||
|
{{- end }} |
||||||
|
<div |
||||||
|
class="media-galleries-wrapper" |
||||||
|
role="region" |
||||||
|
aria-label="Media by {{ .account.Username -}}" |
||||||
|
> |
||||||
|
{{- if .pinned_statuses }} |
||||||
|
<section class="pinned h-feed" aria-labelledby="pinned"> |
||||||
|
<div class="col-header"> |
||||||
|
<h3 class="p-name" id="pinned">Pinned media</h3> |
||||||
|
<a href="#recent">jump to recent</a> |
||||||
|
</div> |
||||||
|
<div |
||||||
|
class="media-gallery photoswipe-gallery" |
||||||
|
role="group" |
||||||
|
> |
||||||
|
{{- range $index, $attachment := .pinnedGalleryItems }} |
||||||
|
{{- includeIndex "status_attachment.tmpl" $attachment $index | indent 4 }} |
||||||
|
{{- end }} |
||||||
|
</div> |
||||||
|
</section> |
||||||
|
{{- end }} |
||||||
|
<section class="recent h-feed" aria-labelledby="recent"> |
||||||
|
<div class="col-header"> |
||||||
|
<h3 id="recent p-name" tabindex="-1">Recent media</h3> |
||||||
|
{{- if .rssFeed }} |
||||||
|
<a href="{{- .rssFeed -}}" class="rss-icon" aria-label="RSS feed"> |
||||||
|
<i class="fa fa-rss-square" aria-hidden="true"></i> |
||||||
|
</a> |
||||||
|
{{- end }} |
||||||
|
</div> |
||||||
|
{{- if not .galleryItems }} |
||||||
|
<div data-nosnippet class="nothinghere"> |
||||||
|
{{- if .show_back_to_top }} |
||||||
|
Reached the end of visible media! |
||||||
|
{{- else }} |
||||||
|
Nothing to see here! {{ .account.Username }} has either not posted any public media yet, or has opted not to make posts visible via the World Wide Web. |
||||||
|
{{- end }} |
||||||
|
</div> |
||||||
|
{{- else }} |
||||||
|
<div |
||||||
|
class="media-gallery photoswipe-gallery" |
||||||
|
role="group" |
||||||
|
> |
||||||
|
{{- range $index, $attachment := .galleryItems }} |
||||||
|
{{- includeIndex "status_attachment.tmpl" $attachment $index | indent 4 }} |
||||||
|
{{- end }} |
||||||
|
</div> |
||||||
|
{{- end }} |
||||||
|
<nav class="backnextlinks"> |
||||||
|
{{- if .show_back_to_top }} |
||||||
|
<a href="/@{{- .account.Username -}}">Back to top</a> |
||||||
|
{{- end }} |
||||||
|
{{- if .statuses_next }} |
||||||
|
<a href="{{- .statuses_next -}}" class="next">Show older</a> |
||||||
|
{{- end }} |
||||||
|
</nav> |
||||||
|
</section> |
||||||
|
</div> |
||||||
|
</main> |
||||||
|
{{- end }} |
||||||
@ -0,0 +1,56 @@ |
|||||||
|
{{- /* |
||||||
|
// 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/>. |
||||||
|
*/ -}} |
||||||
|
|
||||||
|
{{- with . }} |
||||||
|
<section class="about-user" role="region" aria-labelledby="about-header"> |
||||||
|
<div class="col-header"> |
||||||
|
<h3 id="about-header">About<span class="sr-only"> {{- .account.Username -}}</span></h3> |
||||||
|
</div> |
||||||
|
{{- if .account.Fields }} |
||||||
|
{{- include "profile_fields.tmpl" . | indent 1 }} |
||||||
|
{{- end }} |
||||||
|
<h4 class="sr-only">Bio</h4> |
||||||
|
<div class="bio p-note"> |
||||||
|
{{- if .account.Note }} |
||||||
|
{{ emojify .account.Emojis (noescape .account.Note) }} |
||||||
|
{{- else }} |
||||||
|
<p>This GoToSocial user hasn't written a bio yet!</p> |
||||||
|
{{- end }} |
||||||
|
</div> |
||||||
|
<h4 class="sr-only">Stats</h4> |
||||||
|
<dl class="accountstats"> |
||||||
|
<div class="stats-item"> |
||||||
|
<dt class="joineddt text-cutoff">Joined</dt> |
||||||
|
<dd class="joineddd text-cutoff"><time datetime="{{- .account.CreatedAt -}}">{{- .account.CreatedAt | timestampVague -}}</time></dd> |
||||||
|
</div> |
||||||
|
<div class="stats-item"> |
||||||
|
<dt class="postsdt text-cutoff">Posts</dt> |
||||||
|
<dd class="postsdd text-cutoff">{{- .account.StatusesCount -}}</dd> |
||||||
|
</div> |
||||||
|
<div class="stats-item"> |
||||||
|
<dt class="followeddt text-cutoff">Followed by</dt> |
||||||
|
<dd class="followeddd text-cutoff">{{- if .account.HideCollections -}}<i>hidden</i>{{- else -}}{{- .account.FollowersCount -}}{{- end -}}</dd> |
||||||
|
</div> |
||||||
|
<div class="stats-item"> |
||||||
|
<dt class="followingdt text-cutoff">Following</dt> |
||||||
|
<dd class="followingdd text-cutoff">{{- if .account.HideCollections -}}<i>hidden</i>{{- else -}}{{- .account.FollowingCount -}}{{- end -}}</dd> |
||||||
|
</div> |
||||||
|
</dl> |
||||||
|
</section> |
||||||
|
{{- end }} |
||||||
@ -0,0 +1,179 @@ |
|||||||
|
{{- /* |
||||||
|
// 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/>. |
||||||
|
*/ -}} |
||||||
|
|
||||||
|
{{- define "imagePreview" }} |
||||||
|
<img |
||||||
|
src="{{- .PreviewURL -}}" |
||||||
|
loading="lazy" |
||||||
|
{{- if .Description }} |
||||||
|
alt="{{- .Description -}}" |
||||||
|
title="{{- .Description -}}" |
||||||
|
{{- end }} |
||||||
|
width="{{- .Meta.Original.Width -}}" |
||||||
|
height="{{- .Meta.Original.Height -}}" |
||||||
|
/> |
||||||
|
{{- end }} |
||||||
|
|
||||||
|
{{- define "videoPreview" }} |
||||||
|
<img |
||||||
|
src="{{- .PreviewURL -}}" |
||||||
|
loading="lazy" |
||||||
|
{{- if .Description }} |
||||||
|
alt="{{- .Description -}}" |
||||||
|
title="{{- .Description -}}" |
||||||
|
{{- end }} |
||||||
|
width="{{- .Meta.Small.Width -}}" |
||||||
|
height="{{- .Meta.Small.Height -}}" |
||||||
|
/> |
||||||
|
{{- end }} |
||||||
|
|
||||||
|
{{- define "audioPreview" }} |
||||||
|
{{- if and .PreviewURL .Meta.Small.Width }} |
||||||
|
<img |
||||||
|
src="{{- .PreviewURL -}}" |
||||||
|
loading="lazy" |
||||||
|
{{- if .Description }} |
||||||
|
alt="{{- .Description -}}" |
||||||
|
title="{{- .Description -}}" |
||||||
|
{{- end }} |
||||||
|
width="{{- .Meta.Small.Width -}}" |
||||||
|
height="{{- .Meta.Small.Height -}}" |
||||||
|
/> |
||||||
|
{{- else }} |
||||||
|
<img |
||||||
|
src="/assets/logo.webp" |
||||||
|
loading="lazy" |
||||||
|
{{- if .Description }} |
||||||
|
alt="{{- .Description -}}" |
||||||
|
title="{{- .Description -}}" |
||||||
|
{{- end }} |
||||||
|
width="518" |
||||||
|
height="460" |
||||||
|
/> |
||||||
|
{{- end }} |
||||||
|
{{- end }} |
||||||
|
|
||||||
|
{{- with . }} |
||||||
|
<div class="media-wrapper"> |
||||||
|
<details class="{{- .Item.Type -}}-spoiler media-spoiler" {{- if not .Item.Sensitive }} open{{- end -}}> |
||||||
|
<summary> |
||||||
|
<div class="show sensitive button" aria-hidden="true">Show sensitive</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 or (eq .Item.Type "video") (eq .Item.Type "gifv") }} |
||||||
|
{{- include "videoPreview" .Item | indent 3 }} |
||||||
|
{{- else if eq .Item.Type "image" }} |
||||||
|
{{- include "imagePreview" .Item | indent 3 }} |
||||||
|
{{- else if eq .Item.Type "audio" }} |
||||||
|
{{- include "audioPreview" .Item | indent 3 }} |
||||||
|
{{- end }} |
||||||
|
</summary> |
||||||
|
{{- if or (eq .Item.Type "video") (eq .Item.Type "gifv") }} |
||||||
|
<video |
||||||
|
{{- if eq .Item.Type "video" }} |
||||||
|
preload="none" |
||||||
|
{{- else }} |
||||||
|
preload="auto" |
||||||
|
muted |
||||||
|
{{- end }} |
||||||
|
class="plyr-video photoswipe-slide{{- if eq .Item.Type "gifv" }} gifv{{ end }}" |
||||||
|
controls |
||||||
|
playsinline |
||||||
|
data-pswp-index="{{- .Index -}}" |
||||||
|
data-pswp-parent-status="{{- .Item.ParentStatusLink -}}" |
||||||
|
data-pswp-attachment-id="{{- .Item.ID -}}" |
||||||
|
poster="{{- .Item.PreviewURL -}}" |
||||||
|
data-pswp-width="{{- .Item.Meta.Original.Width -}}px" |
||||||
|
data-pswp-height="{{- .Item.Meta.Original.Height -}}px" |
||||||
|
{{- if .Item.Description }} |
||||||
|
alt="{{- .Item.Description -}}" |
||||||
|
title="{{- .Item.Description -}}" |
||||||
|
{{- end }} |
||||||
|
> |
||||||
|
<source type="{{- .Item.MIMEType -}}" src="{{- .Item.URL -}}"/> |
||||||
|
</video> |
||||||
|
{{- else if eq .Item.Type "audio" }} |
||||||
|
<video |
||||||
|
preload="none" |
||||||
|
class="plyr-video photoswipe-slide" |
||||||
|
controls |
||||||
|
playsinline |
||||||
|
data-pswp-index="{{- .Index -}}" |
||||||
|
data-pswp-parent-status="{{- .Item.ParentStatusLink -}}" |
||||||
|
data-pswp-attachment-id="{{- .Item.ID -}}" |
||||||
|
{{- if and .Item.PreviewURL .Item.Meta.Small.Width }} |
||||||
|
poster="{{- .Item.PreviewURL -}}" |
||||||
|
data-pswp-width="{{- .Item.Meta.Small.Width -}}px" |
||||||
|
data-pswp-height="{{- .Item.Meta.Small.Height -}}px" |
||||||
|
{{- else }} |
||||||
|
poster="/assets/logo.webp" |
||||||
|
width="518px" |
||||||
|
height="460px" |
||||||
|
{{- end }} |
||||||
|
{{- if .Item.Description }} |
||||||
|
alt="{{- .Item.Description -}}" |
||||||
|
title="{{- .Item.Description -}}" |
||||||
|
{{- end }} |
||||||
|
> |
||||||
|
<source type="{{- .Item.MIMEType -}}" src="{{- .Item.URL -}}"/> |
||||||
|
</video> |
||||||
|
{{- else if eq .Item.Type "image" }} |
||||||
|
<a |
||||||
|
class="photoswipe-slide" |
||||||
|
data-pswp-index="{{- .Index -}}" |
||||||
|
data-pswp-parent-status="{{- .Item.ParentStatusLink -}}" |
||||||
|
data-pswp-attachment-id="{{- .Item.ID -}}" |
||||||
|
href="{{- .Item.URL -}}" |
||||||
|
target="_blank" |
||||||
|
data-pswp-width="{{- .Item.Meta.Original.Width -}}px" |
||||||
|
data-pswp-height="{{- .Item.Meta.Original.Height -}}px" |
||||||
|
data-cropped="true" |
||||||
|
{{- if .Item.Description }} |
||||||
|
alt="{{- .Item.Description -}}" |
||||||
|
title="{{- .Item.Description -}}" |
||||||
|
{{- end }} |
||||||
|
> |
||||||
|
{{- with .Item }} |
||||||
|
{{- include "imagePreview" . | indent 3 }} |
||||||
|
{{- end }} |
||||||
|
</a> |
||||||
|
{{- else }} |
||||||
|
<a |
||||||
|
class="unknown-attachment" |
||||||
|
href="{{- .Item.RemoteURL -}}" |
||||||
|
rel="nofollow noreferrer noopener" |
||||||
|
target="_blank" |
||||||
|
{{- if .Item.Description }} |
||||||
|
title="Open external media: {{ .Item.Description -}} {{- .Item.RemoteURL -}}" |
||||||
|
{{- else }} |
||||||
|
title="Open external media. {{- .Item.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 }} |
||||||
@ -1,195 +0,0 @@ |
|||||||
{{- /* |
|
||||||
// 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. |
|
||||||
*/ -}} |
|
||||||
|
|
||||||
{{- define "imagePreview" }} |
|
||||||
<img |
|
||||||
src="{{- .PreviewURL -}}" |
|
||||||
loading="lazy" |
|
||||||
{{- if .Description }} |
|
||||||
alt="{{- .Description -}}" |
|
||||||
title="{{- .Description -}}" |
|
||||||
{{- end }} |
|
||||||
width="{{- .Meta.Original.Width -}}" |
|
||||||
height="{{- .Meta.Original.Height -}}" |
|
||||||
/> |
|
||||||
{{- end }} |
|
||||||
|
|
||||||
{{- define "videoPreview" }} |
|
||||||
<img |
|
||||||
src="{{- .PreviewURL -}}" |
|
||||||
loading="lazy" |
|
||||||
{{- if .Description }} |
|
||||||
alt="{{- .Description -}}" |
|
||||||
title="{{- .Description -}}" |
|
||||||
{{- end }} |
|
||||||
width="{{- .Meta.Small.Width -}}" |
|
||||||
height="{{- .Meta.Small.Height -}}" |
|
||||||
/> |
|
||||||
{{- end }} |
|
||||||
|
|
||||||
{{- define "audioPreview" }} |
|
||||||
{{- if and .PreviewURL .Meta.Small.Width }} |
|
||||||
<img |
|
||||||
src="{{- .PreviewURL -}}" |
|
||||||
loading="lazy" |
|
||||||
{{- if .Description }} |
|
||||||
alt="{{- .Description -}}" |
|
||||||
title="{{- .Description -}}" |
|
||||||
{{- end }} |
|
||||||
width="{{- .Meta.Small.Width -}}" |
|
||||||
height="{{- .Meta.Small.Height -}}" |
|
||||||
/> |
|
||||||
{{- else }} |
|
||||||
<img |
|
||||||
src="/assets/logo.webp" |
|
||||||
loading="lazy" |
|
||||||
{{- if .Description }} |
|
||||||
alt="{{- .Description -}}" |
|
||||||
title="{{- .Description -}}" |
|
||||||
{{- end }} |
|
||||||
width="518" |
|
||||||
height="460" |
|
||||||
/> |
|
||||||
{{- end }} |
|
||||||
{{- end }} |
|
||||||
|
|
||||||
{{- /* Produces something like "1 attachment", "2 attachments", etc */ -}} |
|
||||||
{{- define "attachmentsLength" -}} |
|
||||||
{{- (len .) }}{{- if eq (len .) 1 }} attachment{{- else }} attachments{{- end -}} |
|
||||||
{{- end -}} |
|
||||||
|
|
||||||
{{- /* Produces something like "media photoswipe-gallery odd single" */ -}} |
|
||||||
{{- define "galleryClass" -}} |
|
||||||
media photoswipe-gallery {{ (len .) | oddOrEven }} {{ if eq (len .) 1 }}single{{ else if eq (len .) 2 }}double{{ end }} |
|
||||||
{{- end -}} |
|
||||||
|
|
||||||
{{- with .MediaAttachments }} |
|
||||||
<div |
|
||||||
class="{{- template "galleryClass" . -}}" |
|
||||||
role="group" |
|
||||||
aria-label="{{- template "attachmentsLength" . -}}" |
|
||||||
> |
|
||||||
{{- 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 or (eq .Type "video") (eq .Type "gifv") }} |
|
||||||
{{- include "videoPreview" $media | indent 4 }} |
|
||||||
{{- else if eq .Type "image" }} |
|
||||||
{{- include "imagePreview" $media | indent 4 }} |
|
||||||
{{- else if eq .Type "audio" }} |
|
||||||
{{- include "audioPreview" $media | indent 4 }} |
|
||||||
{{- end }} |
|
||||||
</summary> |
|
||||||
{{- if or (eq .Type "video") (eq .Type "gifv") }} |
|
||||||
<video |
|
||||||
{{- if eq .Type "video" }} |
|
||||||
preload="none" |
|
||||||
{{- else }} |
|
||||||
preload="auto" |
|
||||||
muted |
|
||||||
{{- end }} |
|
||||||
class="plyr-video photoswipe-slide{{- if eq .Type "gifv" }} gifv{{ end }}" |
|
||||||
controls |
|
||||||
playsinline |
|
||||||
data-pswp-index="{{- $index -}}" |
|
||||||
poster="{{- .PreviewURL -}}" |
|
||||||
data-pswp-width="{{- $media.Meta.Small.Width -}}px" |
|
||||||
data-pswp-height="{{- $media.Meta.Small.Height -}}px" |
|
||||||
{{- if .Description }} |
|
||||||
alt="{{- $media.Description -}}" |
|
||||||
title="{{- $media.Description -}}" |
|
||||||
{{- end }} |
|
||||||
> |
|
||||||
<source type="{{- $media.MIMEType -}}" src="{{- $media.URL -}}"/> |
|
||||||
</video> |
|
||||||
{{- else if eq .Type "audio" }} |
|
||||||
<video |
|
||||||
preload="none" |
|
||||||
class="plyr-video photoswipe-slide" |
|
||||||
controls |
|
||||||
playsinline |
|
||||||
data-pswp-index="{{- $index -}}" |
|
||||||
{{- if and $media.PreviewURL $media.Meta.Small.Width }} |
|
||||||
poster="{{- .PreviewURL -}}" |
|
||||||
data-pswp-width="{{- $media.Meta.Small.Width -}}px" |
|
||||||
data-pswp-height="{{- $media.Meta.Small.Height -}}px" |
|
||||||
{{- else }} |
|
||||||
poster="/assets/logo.webp" |
|
||||||
width="518px" |
|
||||||
height="460px" |
|
||||||
{{- end }} |
|
||||||
{{- if .Description }} |
|
||||||
alt="{{- $media.Description -}}" |
|
||||||
title="{{- $media.Description -}}" |
|
||||||
{{- end }} |
|
||||||
> |
|
||||||
<source type="{{- $media.MIMEType -}}" 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 }} |
|
||||||
alt="{{- $media.Description -}}" |
|
||||||
title="{{- $media.Description -}}" |
|
||||||
{{- end }} |
|
||||||
> |
|
||||||
{{- with $media }} |
|
||||||
{{- include "imagePreview" . | indent 4 }} |
|
||||||
{{- end }} |
|
||||||
</a> |
|
||||||
{{- else }} |
|
||||||
<a |
|
||||||
class="unknown-attachment" |
|
||||||
href="{{- $media.RemoteURL -}}" |
|
||||||
rel="nofollow noreferrer noopener" |
|
||||||
target="_blank" |
|
||||||
{{- if .Description }} |
|
||||||
title="Open external media: {{ $media.Description -}} {{- $media.RemoteURL -}}" |
|
||||||
{{- else }} |
|
||||||
title="Open external media. {{- $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 }} |
|
||||||