mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2024-12-04 17:42:46 +00:00
Compare commits
10 commits
924a2a86b3
...
14f1e6bbb4
Author | SHA1 | Date | |
---|---|---|---|
14f1e6bbb4 | |||
6f3583559f | |||
497ebd8c4e | |||
c1c8849322 | |||
2f582e2e33 | |||
40c33ccc49 | |||
90b773ae2a | |||
4b7d7f9b8b | |||
af5a766f62 | |||
d9e59820ed |
|
@ -284,6 +284,12 @@ definitions:
|
|||
example: https://example.org/media/some_user/header/static/header.png
|
||||
type: string
|
||||
x-go-name: HeaderStatic
|
||||
hide_boosts:
|
||||
description: |-
|
||||
Account has opted to hide boosts from their profile.
|
||||
Key/value omitted if false.
|
||||
type: boolean
|
||||
x-go-name: HideBoosts
|
||||
hide_collections:
|
||||
description: |-
|
||||
Account has opted to hide their followers/following collections.
|
||||
|
@ -2284,6 +2290,12 @@ definitions:
|
|||
example: https://example.org/media/some_user/header/static/header.png
|
||||
type: string
|
||||
x-go-name: HeaderStatic
|
||||
hide_boosts:
|
||||
description: |-
|
||||
Account has opted to hide boosts from their profile.
|
||||
Key/value omitted if false.
|
||||
type: boolean
|
||||
x-go-name: HideBoosts
|
||||
hide_collections:
|
||||
description: |-
|
||||
Account has opted to hide their followers/following collections.
|
||||
|
|
|
@ -88,9 +88,9 @@ This setting does not affect visibility of your posts over the ActivityPub proto
|
|||
|
||||
!!! warning
|
||||
Be aware that changes to this setting also apply retroactively.
|
||||
|
||||
|
||||
That is, if you previously made a post on Unlisted visibility, while set to show only Public posts on your profile, and you change this setting to show Public and Unlisted, then the Unlisted post you previously made will be visible on your profile alongside your Public posts.
|
||||
|
||||
|
||||
Likewise, if you change this setting to show no posts, then all your posts will be hidden from your profile, regardless of when you created them, and what this option was set to at the time. This will apply until you change this setting again.
|
||||
|
||||
!!! tip
|
||||
|
@ -134,6 +134,11 @@ This feed only includes posts set as 'Public' (see [Privacy Settings](./posts.md
|
|||
!!! warning
|
||||
Exposing your RSS feed allows *anyone* to subscribe to updates on your Public posts anonymously, bypassing follows and follow requests.
|
||||
|
||||
#### Hide boosts from your public page
|
||||
|
||||
By default, GoToSocial will display posts boosted by you on your public web profile. If you do not wish to display them, You can hide them by checking this box.
|
||||
|
||||
|
||||
#### Hide Who You Follow / Are Followed By
|
||||
|
||||
By default, GoToSocial shows your following/followers counts on your public web profile, and allows others to see who you follow and are followed by. This can be useful for account discovery purposes. However, for privacy + safety reasons you may wish to hide these counts, and to hide your following/followers lists from other accounts. You can do this by checking this box.
|
||||
|
@ -196,7 +201,7 @@ If you want to reset all your policies to the initial defaults, you can click on
|
|||
|
||||
!!! danger
|
||||
While GoToSocial respects interaction policies, it is not guaranteed that other server softwares will, and it is possible that accounts on other servers will still send out replies and boosts of your post to their followers, even if your instance forbids these interactions.
|
||||
|
||||
|
||||
As more ActivityPub servers roll out support for interaction policies, this issue will hopefully diminish, but in the meantime GoToSocial can offer only a "best effort" attempt to restrict interactions with your posts according to the policies you have set.
|
||||
|
||||
## Email & Password
|
||||
|
|
6
go.mod
6
go.mod
|
@ -8,13 +8,13 @@ require (
|
|||
codeberg.org/gruf/go-bytes v1.0.2
|
||||
codeberg.org/gruf/go-bytesize v1.0.3
|
||||
codeberg.org/gruf/go-byteutil v1.3.0
|
||||
codeberg.org/gruf/go-cache/v3 v3.5.7
|
||||
codeberg.org/gruf/go-cache/v3 v3.6.1
|
||||
codeberg.org/gruf/go-debug v1.3.0
|
||||
codeberg.org/gruf/go-errors/v2 v2.3.2
|
||||
codeberg.org/gruf/go-fastcopy v1.1.3
|
||||
codeberg.org/gruf/go-ffmpreg v0.2.6
|
||||
codeberg.org/gruf/go-iotools v0.0.0-20240710125620-934ae9c654cf
|
||||
codeberg.org/gruf/go-kv v1.6.4
|
||||
codeberg.org/gruf/go-kv v1.6.5
|
||||
codeberg.org/gruf/go-list v0.0.0-20240425093752-494db03d641f
|
||||
codeberg.org/gruf/go-mempool v0.0.0-20240507125005-cef10d64a760
|
||||
codeberg.org/gruf/go-mimetypes v1.2.0
|
||||
|
@ -87,7 +87,7 @@ require (
|
|||
require (
|
||||
codeberg.org/gruf/go-fastpath/v2 v2.0.0 // indirect
|
||||
codeberg.org/gruf/go-mangler v1.4.1 // indirect
|
||||
codeberg.org/gruf/go-maps v1.0.3 // indirect
|
||||
codeberg.org/gruf/go-maps v1.0.4 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
||||
|
|
12
go.sum
12
go.sum
|
@ -36,8 +36,8 @@ codeberg.org/gruf/go-bytesize v1.0.3 h1:Tz8tCxhPLeyM5VryuBNjUHgKmLj4Bx9RbPaUSA3q
|
|||
codeberg.org/gruf/go-bytesize v1.0.3/go.mod h1:n/GU8HzL9f3UNp/mUKyr1qVmTlj7+xacpp0OHfkvLPs=
|
||||
codeberg.org/gruf/go-byteutil v1.3.0 h1:nRqJnCcRQ7xbfU6azw7zOzJrSMDIJHBqX6FL9vEMYmU=
|
||||
codeberg.org/gruf/go-byteutil v1.3.0/go.mod h1:chgnZz1LUcfaObaIFglxF5MRYQkJGjQf4WwVz95ccCM=
|
||||
codeberg.org/gruf/go-cache/v3 v3.5.7 h1:5hut49a8Wp3hdwrCEJYj6pHY2aRR1hyTmkK4+wHVYq4=
|
||||
codeberg.org/gruf/go-cache/v3 v3.5.7/go.mod h1:Thahfuf3PgHSv2+1zHpvhRdX97tx1WXurVNGWpZucAM=
|
||||
codeberg.org/gruf/go-cache/v3 v3.6.1 h1:sY1XhYeskjZAuYeMm5R0o4Qymru5taNbzmZPSn1oXLE=
|
||||
codeberg.org/gruf/go-cache/v3 v3.6.1/go.mod h1:JUNjc4E8gRccn3t+B99akxURFrU6NTDkvFVcwiZirnw=
|
||||
codeberg.org/gruf/go-debug v1.3.0 h1:PIRxQiWUFKtGOGZFdZ3Y0pqyfI0Xr87j224IYe2snZs=
|
||||
codeberg.org/gruf/go-debug v1.3.0/go.mod h1:N+vSy9uJBQgpQcJUqjctvqFz7tBHJf+S/PIjLILzpLg=
|
||||
codeberg.org/gruf/go-errors/v2 v2.3.2 h1:8ItWaOMfhDaqrJK1Pw8MO0Nu+o/tVcQtR5cJ58Vc4zo=
|
||||
|
@ -50,16 +50,16 @@ codeberg.org/gruf/go-ffmpreg v0.2.6 h1:OHlTOF+62/b+VeM3Svg7praweU/NECRIsuhilZLFa
|
|||
codeberg.org/gruf/go-ffmpreg v0.2.6/go.mod h1:sViRI0BYK2B8PJw4BrOg7DquPD71mZjDfffRAFcDtvk=
|
||||
codeberg.org/gruf/go-iotools v0.0.0-20240710125620-934ae9c654cf h1:84s/ii8N6lYlskZjHH+DG6jyia8w2mXMZlRwFn8Gs3A=
|
||||
codeberg.org/gruf/go-iotools v0.0.0-20240710125620-934ae9c654cf/go.mod h1:zZAICsp5rY7+hxnws2V0ePrWxE0Z2Z/KXcN3p/RQCfk=
|
||||
codeberg.org/gruf/go-kv v1.6.4 h1:3NZiW8HVdBM3kpOiLb7XfRiihnzZWMAixdCznguhILk=
|
||||
codeberg.org/gruf/go-kv v1.6.4/go.mod h1:O/YkSvKiS9XsRolM3rqCd9YJmND7dAXu9z+PrlYO4bc=
|
||||
codeberg.org/gruf/go-kv v1.6.5 h1:ttPf0NA8F79pDqBttSudPTVCZmGncumeNIxmeM9ztz0=
|
||||
codeberg.org/gruf/go-kv v1.6.5/go.mod h1:c4PsGqw05bDScvISpK+d31SiDEpBorweCL50hsiK3dc=
|
||||
codeberg.org/gruf/go-list v0.0.0-20240425093752-494db03d641f h1:Ss6Z+vygy+jOGhj96d/GwsYYDd22QmIcH74zM7/nQkw=
|
||||
codeberg.org/gruf/go-list v0.0.0-20240425093752-494db03d641f/go.mod h1:F9pl4h34iuVN7kucKam9fLwsItTc+9mmaKt7pNXRd/4=
|
||||
codeberg.org/gruf/go-loosy v0.0.0-20231007123304-bb910d1ab5c4 h1:IXwfoU7f2whT6+JKIKskNl/hBlmWmnF1vZd84Eb3cyA=
|
||||
codeberg.org/gruf/go-loosy v0.0.0-20231007123304-bb910d1ab5c4/go.mod h1:fiO8HE1wjZCephcYmRRsVnNI/i0+mhy44Z5dQalS0rM=
|
||||
codeberg.org/gruf/go-mangler v1.4.1 h1:Dv58jFfy9On49L11ji6tpADUknwoJA46iaiZvnNXecs=
|
||||
codeberg.org/gruf/go-mangler v1.4.1/go.mod h1:mDmW8Ia352RvNFaXoP9K60TgcmCZJtX0j6wm3vjAsJE=
|
||||
codeberg.org/gruf/go-maps v1.0.3 h1:VDwhnnaVNUIy5O93CvkcE2IZXnMB1+IJjzfop9V12es=
|
||||
codeberg.org/gruf/go-maps v1.0.3/go.mod h1:D5LNDxlC9rsDuVQVM6JObaVGAdHB6g2dTdOdkh1aXWA=
|
||||
codeberg.org/gruf/go-maps v1.0.4 h1:K+Ww4vvR3TZqm5jqrKVirmguZwa3v1VUvmig2SE8uxY=
|
||||
codeberg.org/gruf/go-maps v1.0.4/go.mod h1:ASX7osM7kFwt5O8GfGflcFjrwYGD8eIuRLl/oMjhEi8=
|
||||
codeberg.org/gruf/go-mempool v0.0.0-20240507125005-cef10d64a760 h1:m2/UCRXhjDwAg4vyji6iKCpomKw6P4PmBOUi5DvAMH4=
|
||||
codeberg.org/gruf/go-mempool v0.0.0-20240507125005-cef10d64a760/go.mod h1:E3RcaCFNq4zXpvaJb8lfpPqdUAmSkP5F1VmMiEUYTEk=
|
||||
codeberg.org/gruf/go-mimetypes v1.2.0 h1:3rZGXY/SkNYbamiddWXs2gETXIBkGIeWYnbWpp2OEbc=
|
||||
|
|
|
@ -348,6 +348,7 @@ func parseUpdateAccountForm(c *gin.Context) (*apimodel.UpdateCredentialsRequest,
|
|||
form.Theme == nil &&
|
||||
form.CustomCSS == nil &&
|
||||
form.EnableRSS == nil &&
|
||||
form.HideBoosts == nil &&
|
||||
form.HideCollections == nil &&
|
||||
form.WebVisibility == nil) {
|
||||
return nil, errors.New("empty form submitted")
|
||||
|
|
|
@ -104,6 +104,9 @@ type Account struct {
|
|||
// Account has enabled RSS feed.
|
||||
// Key/value omitted if false.
|
||||
EnableRSS bool `json:"enable_rss,omitempty"`
|
||||
// Account has opted to hide boosts from their profile.
|
||||
// Key/value omitted if false.
|
||||
HideBoosts bool `json:"hide_boosts,omitempty"`
|
||||
// Account has opted to hide their followers/following collections.
|
||||
// Key/value omitted if false.
|
||||
HideCollections bool `json:"hide_collections,omitempty"`
|
||||
|
@ -225,6 +228,8 @@ type UpdateCredentialsRequest struct {
|
|||
CustomCSS *string `form:"custom_css" json:"custom_css"`
|
||||
// Enable RSS feed of public toots for this account at /@[username]/feed.rss
|
||||
EnableRSS *bool `form:"enable_rss" json:"enable_rss"`
|
||||
// Hide boosts from this account's profile page.
|
||||
HideBoosts *bool `form:"hide_boosts" json:"hide_boosts"`
|
||||
// Hide this account's following/followers collections.
|
||||
HideCollections *bool `form:"hide_collections" json:"hide_collections"`
|
||||
// Visibility of statuses to show via the web view.
|
||||
|
|
|
@ -118,6 +118,10 @@ type WebStatus struct {
|
|||
// Override API account with web account.
|
||||
Account *WebAccount `json:"account"`
|
||||
|
||||
// Account that reblogged the status.
|
||||
// needed to properly render reblogged statuses on profile pages.
|
||||
ReblogAccount *WebAccount `json:"reblog_account"`
|
||||
|
||||
// Web version of media
|
||||
// attached to this status.
|
||||
MediaAttachments []*WebAttachment `json:"media_attachments"`
|
||||
|
|
|
@ -1017,6 +1017,7 @@ func (a *accountDB) GetAccountWebStatuses(
|
|||
) ([]*gtsmodel.Status, error) {
|
||||
// Check for an easy case: account exposes no statuses via the web.
|
||||
webVisibility := account.Settings.WebVisibility
|
||||
hideBoosts := *account.Settings.HideBoosts
|
||||
if webVisibility == gtsmodel.VisibilityNone {
|
||||
return nil, db.ErrNoEntries
|
||||
}
|
||||
|
@ -1035,9 +1036,12 @@ func (a *accountDB) GetAccountWebStatuses(
|
|||
// Select only IDs from table
|
||||
Column("status.id").
|
||||
Where("? = ?", bun.Ident("status.account_id"), account.ID).
|
||||
// Don't show replies or boosts.
|
||||
Where("? IS NULL", bun.Ident("status.in_reply_to_uri")).
|
||||
Where("? IS NULL", bun.Ident("status.boost_of_id"))
|
||||
// Don't show replies.
|
||||
Where("? IS NULL", bun.Ident("status.in_reply_to_uri"))
|
||||
|
||||
if hideBoosts {
|
||||
q = q.Where("? IS NULL", bun.Ident("status.boost_of_id"))
|
||||
}
|
||||
|
||||
// Select statuses for this account according
|
||||
// to their web visibility preference.
|
||||
|
|
|
@ -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/>.
|
||||
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
func init() {
|
||||
up := func(ctx context.Context, db *bun.DB) error {
|
||||
_, err := db.ExecContext(ctx, "ALTER TABLE ? ADD COLUMN ? BOOLEAN DEFAULT FALSE", bun.Ident("account_settings"), bun.Ident("hide_boosts"))
|
||||
if err != nil && !(strings.Contains(err.Error(), "already exists") || strings.Contains(err.Error(), "duplicate column name") || strings.Contains(err.Error(), "SQLSTATE 42701")) {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
down := func(ctx context.Context, db *bun.DB) error {
|
||||
_, err := db.ExecContext(ctx, "ALTER TABLE ? DROP COLUMN ?", bun.Ident("account_settings"), bun.Ident("hide_boosts"))
|
||||
return err
|
||||
}
|
||||
|
||||
if err := Migrations.Register(up, down); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
|
@ -40,8 +40,22 @@
|
|||
notRelevantKey
|
||||
spamKey
|
||||
notPermittedKey
|
||||
limitReachedKey
|
||||
)
|
||||
|
||||
// LimitReached indicates that this error was caused by
|
||||
// some kind of limit being reached, e.g. media upload limit.
|
||||
func LimitReached(err error) bool {
|
||||
_, ok := errors.Value(err, limitReachedKey).(struct{})
|
||||
return ok
|
||||
}
|
||||
|
||||
// SetLimitReached will wrap the given error to store a "limit reached"
|
||||
// flag, returning wrapped error. See LimitReached() for example use-cases.
|
||||
func SetLimitReached(err error) error {
|
||||
return errors.WithValue(err, limitReachedKey, struct{}{})
|
||||
}
|
||||
|
||||
// IsUnretrievable indicates that a call to retrieve a resource
|
||||
// (account, status, attachment, etc) could not be fulfilled, either
|
||||
// because it was not found locally, or because some prerequisite
|
||||
|
|
|
@ -33,6 +33,7 @@ type AccountSettings struct {
|
|||
Theme string `bun:",nullzero"` // Preset CSS theme filename selected by this Account (empty string if nothing set).
|
||||
CustomCSS string `bun:",nullzero"` // Custom CSS that should be displayed for this Account's profile and statuses.
|
||||
EnableRSS *bool `bun:",nullzero,notnull,default:false"` // enable RSS feed subscription for this account's public posts at [URL]/feed
|
||||
HideBoosts *bool `bun:",nullzero,notnull,default:false"` // Hide boosts from this accounts profile page.
|
||||
HideCollections *bool `bun:",nullzero,notnull,default:false"` // Hide this account's followers/following collections.
|
||||
WebVisibility Visibility `bun:",nullzero,notnull,default:public"` // Visibility level of statuses that visitors can view via the web profile.
|
||||
InteractionPolicyDirect *InteractionPolicy `bun:""` // Interaction policy to use for new direct visibility statuses by this account. If null, assume default policy.
|
||||
|
|
|
@ -381,11 +381,19 @@ func (res *result) GetFileType() (gtsmodel.FileType, string) {
|
|||
return gtsmodel.FileTypeAudio, "wma"
|
||||
}
|
||||
case "ogg":
|
||||
switch {
|
||||
case len(res.video) > 0:
|
||||
return gtsmodel.FileTypeVideo, "ogv"
|
||||
case len(res.audio) > 0:
|
||||
return gtsmodel.FileTypeAudio, "ogg"
|
||||
if len(res.video) > 0 {
|
||||
switch res.video[0].codec {
|
||||
case "theora", "dirac": // daala, tarkin
|
||||
return gtsmodel.FileTypeVideo, "ogv"
|
||||
}
|
||||
}
|
||||
if len(res.audio) > 0 {
|
||||
switch res.audio[0].codec {
|
||||
case "opus", "libopus":
|
||||
return gtsmodel.FileTypeAudio, "opus"
|
||||
default:
|
||||
return gtsmodel.FileTypeAudio, "ogg"
|
||||
}
|
||||
}
|
||||
case "matroska,webm":
|
||||
switch {
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
"codeberg.org/gruf/go-bytesize"
|
||||
"codeberg.org/gruf/go-iotools"
|
||||
"codeberg.org/gruf/go-mimetypes"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
)
|
||||
|
||||
// file represents one file
|
||||
|
@ -143,8 +144,9 @@ func drainToTmp(rc io.ReadCloser) (string, error) {
|
|||
|
||||
// Check to see if limit was reached,
|
||||
// (produces more useful error messages).
|
||||
if lr != nil && !iotools.AtEOF(lr.R) {
|
||||
return path, fmt.Errorf("reached read limit %s", bytesize.Size(limit))
|
||||
if lr != nil && lr.N <= 0 {
|
||||
err := fmt.Errorf("reached read limit %s", bytesize.Size(limit))
|
||||
return path, gtserror.SetLimitReached(err)
|
||||
}
|
||||
|
||||
return path, nil
|
||||
|
|
|
@ -42,6 +42,16 @@ func (suite *GetRSSTestSuite) TestGetAccountRSSAdmin() {
|
|||
<description>Posts from @admin@localhost:8080</description>
|
||||
<pubDate>Wed, 20 Oct 2021 10:41:37 +0000</pubDate>
|
||||
<lastBuildDate>Wed, 20 Oct 2021 10:41:37 +0000</lastBuildDate>
|
||||
<item>
|
||||
<title>introduction post</title>
|
||||
<link>http://localhost:8080/@the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY</link>
|
||||
<description>@the_mighty_zork@localhost:8080 made a new post: "hello everyone!"</description>
|
||||
<content:encoded><![CDATA[hello everyone!]]></content:encoded>
|
||||
<author>@the_mighty_zork@localhost:8080</author>
|
||||
<guid isPermaLink="true">http://localhost:8080/@the_mighty_zork/statuses/01F8MHAMCHF6Y650WCRSCP4WMY</guid>
|
||||
<pubDate>Wed, 20 Oct 2021 10:40:37 +0000</pubDate>
|
||||
<source>http://localhost:8080/@the_mighty_zork/feed.rss</source>
|
||||
</item>
|
||||
<item>
|
||||
<title>open to see some puppies</title>
|
||||
<link>http://localhost:8080/@admin/statuses/01F8MHAAY43M6RJ473VQFCVH37</link>
|
||||
|
|
|
@ -274,6 +274,11 @@ func (p *Processor) Update(ctx context.Context, account *gtsmodel.Account, form
|
|||
settingsColumns = append(settingsColumns, "enable_rss")
|
||||
}
|
||||
|
||||
if form.HideBoosts != nil {
|
||||
account.Settings.HideBoosts = form.HideBoosts
|
||||
settingsColumns = append(settingsColumns, "hide_boosts")
|
||||
}
|
||||
|
||||
if form.HideCollections != nil {
|
||||
account.Settings.HideCollections = form.HideCollections
|
||||
settingsColumns = append(settingsColumns, "hide_collections")
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/media"
|
||||
|
@ -51,11 +52,18 @@ func (p *Processor) StoreLocalMedia(
|
|||
|
||||
// Immediately trigger write to storage.
|
||||
attachment, err := processing.Load(ctx)
|
||||
if err != nil {
|
||||
const text = "error processing emoji"
|
||||
switch {
|
||||
case gtserror.LimitReached(err):
|
||||
limit := config.GetMediaLocalMaxSize()
|
||||
text := fmt.Sprintf("local media size limit reached: %s", limit)
|
||||
return nil, gtserror.NewErrorUnprocessableEntity(err, text)
|
||||
|
||||
case err != nil:
|
||||
const text = "error processing media"
|
||||
err := gtserror.Newf("error processing media: %w", err)
|
||||
return nil, gtserror.NewErrorUnprocessableEntity(err, text)
|
||||
} else if attachment.Type == gtsmodel.FileTypeUnknown {
|
||||
|
||||
case attachment.Type == gtsmodel.FileTypeUnknown:
|
||||
text := fmt.Sprintf("could not process %s type media", attachment.File.ContentType)
|
||||
return nil, gtserror.NewErrorUnprocessableEntity(errors.New(text), text)
|
||||
}
|
||||
|
@ -86,9 +94,15 @@ func (p *Processor) StoreLocalEmoji(
|
|||
return nil, gtserror.NewErrorInternalError(err)
|
||||
}
|
||||
|
||||
// Immediately write to storage.
|
||||
// Immediately trigger write to storage.
|
||||
emoji, err := processing.Load(ctx)
|
||||
if err != nil {
|
||||
switch {
|
||||
case gtserror.LimitReached(err):
|
||||
limit := config.GetMediaEmojiLocalMaxSize()
|
||||
text := fmt.Sprintf("local emoji size limit reached: %s", limit)
|
||||
return nil, gtserror.NewErrorUnprocessableEntity(err, text)
|
||||
|
||||
case err != nil:
|
||||
const text = "error processing emoji"
|
||||
err := gtserror.Newf("error processing emoji %s: %w", shortcode, err)
|
||||
return nil, gtserror.NewErrorUnprocessableEntity(err, text)
|
||||
|
|
|
@ -302,7 +302,7 @@ func (c *Converter) accountToAPIAccountPublic(ctx context.Context, a *gtsmodel.A
|
|||
// Bits that vary between remote + local accounts:
|
||||
// - Account (acct) string.
|
||||
// - Role.
|
||||
// - Settings things (enableRSS, theme, customCSS, hideCollections).
|
||||
// - Settings things (enableRSS, theme, customCSS, hideBoosts ,hideCollections).
|
||||
|
||||
var (
|
||||
acct string
|
||||
|
@ -310,6 +310,7 @@ func (c *Converter) accountToAPIAccountPublic(ctx context.Context, a *gtsmodel.A
|
|||
enableRSS bool
|
||||
theme string
|
||||
customCSS string
|
||||
hideBoosts bool
|
||||
hideCollections bool
|
||||
)
|
||||
|
||||
|
@ -338,6 +339,7 @@ func (c *Converter) accountToAPIAccountPublic(ctx context.Context, a *gtsmodel.A
|
|||
enableRSS = *a.Settings.EnableRSS
|
||||
theme = a.Settings.Theme
|
||||
customCSS = a.Settings.CustomCSS
|
||||
hideBoosts = *a.Settings.HideBoosts
|
||||
hideCollections = *a.Settings.HideCollections
|
||||
}
|
||||
|
||||
|
@ -380,6 +382,7 @@ func (c *Converter) accountToAPIAccountPublic(ctx context.Context, a *gtsmodel.A
|
|||
Theme: theme,
|
||||
CustomCSS: customCSS,
|
||||
EnableRSS: enableRSS,
|
||||
HideBoosts: hideBoosts,
|
||||
HideCollections: hideCollections,
|
||||
Roles: roles,
|
||||
}
|
||||
|
@ -1092,7 +1095,15 @@ func (c *Converter) StatusToWebStatus(
|
|||
ctx context.Context,
|
||||
s *gtsmodel.Status,
|
||||
) (*apimodel.WebStatus, error) {
|
||||
apiStatus, err := c.statusToFrontend(ctx, s,
|
||||
|
||||
isBoost := s.BoostOf != nil
|
||||
status := s
|
||||
|
||||
if isBoost {
|
||||
status = s.BoostOf
|
||||
}
|
||||
|
||||
apiStatus, err := c.statusToFrontend(ctx, status,
|
||||
nil, // No authed requester.
|
||||
statusfilter.FilterContextNone, // No filters.
|
||||
nil, // No filters.
|
||||
|
@ -1103,7 +1114,7 @@ func (c *Converter) StatusToWebStatus(
|
|||
}
|
||||
|
||||
// Convert status author to web model.
|
||||
acct, err := c.AccountToWebAccount(ctx, s.Account)
|
||||
acct, err := c.AccountToWebAccount(ctx, status.Account)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1113,6 +1124,14 @@ func (c *Converter) StatusToWebStatus(
|
|||
Account: acct,
|
||||
}
|
||||
|
||||
if isBoost {
|
||||
reblogAcct, err := c.AccountToWebAccount(ctx, s.Account)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
webStatus.ReblogAccount = reblogAcct
|
||||
}
|
||||
|
||||
// Whack a newline before and after each "pre" to make it easier to outdent it.
|
||||
webStatus.Content = strings.ReplaceAll(webStatus.Content, "<pre>", "\n<pre>")
|
||||
webStatus.Content = strings.ReplaceAll(webStatus.Content, "</pre>", "</pre>\n")
|
||||
|
|
|
@ -1402,6 +1402,7 @@ func (suite *InternalToFrontendTestSuite) TestStatusToWebStatus() {
|
|||
"emojis": [],
|
||||
"fields": []
|
||||
},
|
||||
"reblog_account": null,
|
||||
"media_attachments": [
|
||||
{
|
||||
"id": "01HE7Y3C432WRSNS10EZM86SA5",
|
||||
|
|
|
@ -39,6 +39,12 @@
|
|||
func (c *Converter) StatusToRSSItem(ctx context.Context, s *gtsmodel.Status) (*feeds.Item, error) {
|
||||
// see https://cyber.harvard.edu/rss/rss.html
|
||||
|
||||
// If status is a boost,
|
||||
// display the boost instead.
|
||||
if s.BoostOf != nil {
|
||||
s = s.BoostOf
|
||||
}
|
||||
|
||||
// Title -- The title of the item.
|
||||
// example: Venice Film Festival Tries to Quit Sinking
|
||||
var title string
|
||||
|
|
|
@ -657,6 +657,7 @@ func NewTestAccountSettings() map[string]*gtsmodel.AccountSettings {
|
|||
Sensitive: util.Ptr(false),
|
||||
Language: "en",
|
||||
EnableRSS: util.Ptr(false),
|
||||
HideBoosts: util.Ptr(false),
|
||||
HideCollections: util.Ptr(false),
|
||||
WebVisibility: gtsmodel.VisibilityPublic,
|
||||
},
|
||||
|
@ -668,6 +669,7 @@ func NewTestAccountSettings() map[string]*gtsmodel.AccountSettings {
|
|||
Sensitive: util.Ptr(false),
|
||||
Language: "en",
|
||||
EnableRSS: util.Ptr(true),
|
||||
HideBoosts: util.Ptr(false),
|
||||
HideCollections: util.Ptr(false),
|
||||
WebVisibility: gtsmodel.VisibilityPublic,
|
||||
},
|
||||
|
@ -679,6 +681,7 @@ func NewTestAccountSettings() map[string]*gtsmodel.AccountSettings {
|
|||
Sensitive: util.Ptr(false),
|
||||
Language: "en",
|
||||
EnableRSS: util.Ptr(true),
|
||||
HideBoosts: util.Ptr(false),
|
||||
HideCollections: util.Ptr(false),
|
||||
WebVisibility: gtsmodel.VisibilityUnlocked,
|
||||
},
|
||||
|
@ -690,6 +693,7 @@ func NewTestAccountSettings() map[string]*gtsmodel.AccountSettings {
|
|||
Sensitive: util.Ptr(true),
|
||||
Language: "fr",
|
||||
EnableRSS: util.Ptr(false),
|
||||
HideBoosts: util.Ptr(false),
|
||||
HideCollections: util.Ptr(true),
|
||||
WebVisibility: gtsmodel.VisibilityPublic,
|
||||
},
|
||||
|
|
6
vendor/codeberg.org/gruf/go-cache/v3/README.md
generated
vendored
6
vendor/codeberg.org/gruf/go-cache/v3/README.md
generated
vendored
|
@ -9,9 +9,3 @@ A `cache.Cache{}` implementation with much more of the inner workings exposed. D
|
|||
## ttl
|
||||
|
||||
A `cache.TTLCache{}` implementation with much more of the inner workings exposed. Designed to be used as a base for your own customizations, or used as-is.
|
||||
|
||||
## result
|
||||
|
||||
`result.Cache` is an example of a more complex cache implementation using `ttl.Cache{}` as its underpinning.
|
||||
|
||||
It provides caching specifically of loadable struct types, with automatic keying by multiple different field members and caching of negative (error) values. All useful when wrapping, for example, a database.
|
6
vendor/codeberg.org/gruf/go-kv/format/format.go
generated
vendored
6
vendor/codeberg.org/gruf/go-kv/format/format.go
generated
vendored
|
@ -197,7 +197,8 @@ func (f format) AppendBytes(b []byte) {
|
|||
|
||||
// Quoted only if spaces/requires escaping
|
||||
case f.Key():
|
||||
f.AppendStringSafe(b2s(b))
|
||||
s := byteutil.B2S(b)
|
||||
f.AppendStringSafe(s)
|
||||
|
||||
// Append as separate ASCII quoted bytes in slice
|
||||
case f.Verbose():
|
||||
|
@ -214,7 +215,8 @@ func (f format) AppendBytes(b []byte) {
|
|||
|
||||
// Quoted only if spaces/requires escaping
|
||||
case f.Value():
|
||||
f.AppendStringSafe(b2s(b))
|
||||
s := byteutil.B2S(b)
|
||||
f.AppendStringSafe(s)
|
||||
|
||||
// Append as raw bytes
|
||||
default:
|
||||
|
|
5
vendor/codeberg.org/gruf/go-kv/format/util.go
generated
vendored
5
vendor/codeberg.org/gruf/go-kv/format/util.go
generated
vendored
|
@ -98,8 +98,3 @@ func isNil(i interface{}) bool {
|
|||
type eface struct{ _type, data unsafe.Pointer } //nolint
|
||||
return (*(*eface)(unsafe.Pointer(&i))).data == nil //nolint
|
||||
}
|
||||
|
||||
// b2s converts a byteslice to string without allocation.
|
||||
func b2s(b []byte) string {
|
||||
return *(*string)(unsafe.Pointer(&b))
|
||||
}
|
||||
|
|
20
vendor/codeberg.org/gruf/go-maps/common.go
generated
vendored
20
vendor/codeberg.org/gruf/go-maps/common.go
generated
vendored
|
@ -17,7 +17,7 @@ type ordered[K comparable, V any] struct {
|
|||
}
|
||||
|
||||
// write_check panics if map is not in a safe-state to write to.
|
||||
func (m ordered[K, V]) write_check() {
|
||||
func (m *ordered[K, V]) write_check() {
|
||||
if m.rnly {
|
||||
panic("map write during read loop")
|
||||
}
|
||||
|
@ -54,15 +54,17 @@ func (m *ordered[K, V]) Delete(key K) bool {
|
|||
|
||||
// Range passes given function over the requested range of the map.
|
||||
func (m *ordered[K, V]) Range(start, length int, fn func(int, K, V)) {
|
||||
// Nil check
|
||||
if fn == nil {
|
||||
panic("nil func")
|
||||
}
|
||||
|
||||
// Disallow writes
|
||||
m.rnly = true
|
||||
defer func() {
|
||||
m.rnly = false
|
||||
}()
|
||||
|
||||
// Nil check
|
||||
_ = fn
|
||||
|
||||
switch end := start + length; {
|
||||
// No loop to iterate
|
||||
case length == 0:
|
||||
|
@ -104,15 +106,17 @@ func (m *ordered[K, V]) Range(start, length int, fn func(int, K, V)) {
|
|||
|
||||
// RangeIf passes given function over the requested range of the map. Returns early on 'fn' -> false.
|
||||
func (m *ordered[K, V]) RangeIf(start, length int, fn func(int, K, V) bool) {
|
||||
// Nil check
|
||||
if fn == nil {
|
||||
panic("nil func")
|
||||
}
|
||||
|
||||
// Disallow writes
|
||||
m.rnly = true
|
||||
defer func() {
|
||||
m.rnly = false
|
||||
}()
|
||||
|
||||
// Nil check
|
||||
_ = fn
|
||||
|
||||
switch end := start + length; {
|
||||
// No loop to iterate
|
||||
case length == 0:
|
||||
|
@ -163,8 +167,8 @@ func (m *ordered[K, V]) Truncate(sz int, fn func(K, V)) {
|
|||
panic("index out of bounds")
|
||||
}
|
||||
|
||||
// Nil check
|
||||
if fn == nil {
|
||||
// move nil check out of loop
|
||||
fn = func(K, V) {}
|
||||
}
|
||||
|
||||
|
|
12
vendor/modules.txt
vendored
12
vendor/modules.txt
vendored
|
@ -7,8 +7,8 @@ codeberg.org/gruf/go-bytesize
|
|||
# codeberg.org/gruf/go-byteutil v1.3.0
|
||||
## explicit; go 1.20
|
||||
codeberg.org/gruf/go-byteutil
|
||||
# codeberg.org/gruf/go-cache/v3 v3.5.7
|
||||
## explicit; go 1.19
|
||||
# codeberg.org/gruf/go-cache/v3 v3.6.1
|
||||
## explicit; go 1.20
|
||||
codeberg.org/gruf/go-cache/v3
|
||||
codeberg.org/gruf/go-cache/v3/simple
|
||||
codeberg.org/gruf/go-cache/v3/ttl
|
||||
|
@ -31,8 +31,8 @@ codeberg.org/gruf/go-ffmpreg/embed/ffprobe
|
|||
# codeberg.org/gruf/go-iotools v0.0.0-20240710125620-934ae9c654cf
|
||||
## explicit; go 1.21
|
||||
codeberg.org/gruf/go-iotools
|
||||
# codeberg.org/gruf/go-kv v1.6.4
|
||||
## explicit; go 1.19
|
||||
# codeberg.org/gruf/go-kv v1.6.5
|
||||
## explicit; go 1.20
|
||||
codeberg.org/gruf/go-kv
|
||||
codeberg.org/gruf/go-kv/format
|
||||
# codeberg.org/gruf/go-list v0.0.0-20240425093752-494db03d641f
|
||||
|
@ -41,8 +41,8 @@ codeberg.org/gruf/go-list
|
|||
# codeberg.org/gruf/go-mangler v1.4.1
|
||||
## explicit; go 1.19
|
||||
codeberg.org/gruf/go-mangler
|
||||
# codeberg.org/gruf/go-maps v1.0.3
|
||||
## explicit; go 1.19
|
||||
# codeberg.org/gruf/go-maps v1.0.4
|
||||
## explicit; go 1.20
|
||||
codeberg.org/gruf/go-maps
|
||||
# codeberg.org/gruf/go-mempool v0.0.0-20240507125005-cef10d64a760
|
||||
## explicit; go 1.22.2
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
theme-title: Solarized (dark)
|
||||
theme-description: Solarized sloth (dark)
|
||||
theme-title: Solarized dark
|
||||
theme-description: Dark green and grey solarized theme with red trim
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -46,18 +46,14 @@
|
|||
--blue3: var(--base1);
|
||||
|
||||
/* Basic page styling (background + foreground) */
|
||||
--bg: var(--white1);
|
||||
--bg-accent: var(--white2);
|
||||
--bg: var(--base03);
|
||||
--bg-accent: var(--base02);
|
||||
--fg-reduced: var(--base0);
|
||||
--fg: var(--base1);
|
||||
|
||||
/* Profile page styling */
|
||||
--profile-bg: var(--white2);
|
||||
|
||||
/* Solarize buttons */
|
||||
--button-bg: var(--blue2);
|
||||
--button-fg: var(--white1);
|
||||
|
||||
/* Solarize statuses */
|
||||
--status-bg: var(--white1);
|
||||
--status-focus-bg: var(--white1);
|
||||
|
@ -65,7 +61,7 @@
|
|||
--status-focus-info-bg: var(--white2);
|
||||
|
||||
/* Used around statuses + other items */
|
||||
--boxshadow-border: 0.15rem solid var(--base01);
|
||||
--boxshadow-border: 0.1rem solid var(--base01);
|
||||
|
||||
--plyr-video-control-color: var(--fg);
|
||||
--plyr-video-control-color-hover: var(--fg-reduced);
|
||||
|
@ -84,6 +80,32 @@ html, body {
|
|||
scrollbar-color: var(--orange2) var(--white1) ;
|
||||
}
|
||||
|
||||
/* Column headers */
|
||||
.col-header {
|
||||
border: var(--boxshadow-border);
|
||||
}
|
||||
|
||||
.profile .about-user .col-header {
|
||||
border-bottom: none;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Header card */
|
||||
.profile .profile-header {
|
||||
border: var(--boxshadow-border);
|
||||
}
|
||||
|
||||
/* Fiddle around with borders on about sections */
|
||||
.profile .about-user .fields,
|
||||
.profile .about-user .bio,
|
||||
.profile .about-user .accountstats {
|
||||
border-left: var(--boxshadow-border);
|
||||
border-right: var(--boxshadow-border);
|
||||
}
|
||||
.profile .about-user .accountstats {
|
||||
border-bottom: var(--boxshadow-border);
|
||||
}
|
||||
|
||||
/* Profile fields */
|
||||
.profile .about-user .fields .field {
|
||||
border-bottom: var(--boxshadow-border);
|
||||
|
@ -98,6 +120,7 @@ html, body {
|
|||
}
|
||||
.status .media .media-wrapper details .unknown-attachment .placeholder {
|
||||
color: var(--base01);
|
||||
border: 0.2rem dashed var(--base01);
|
||||
}
|
||||
.status .media .media-wrapper details video.plyr-video {
|
||||
background: transparent;
|
||||
|
@ -143,10 +166,10 @@ button, .button,
|
|||
|
||||
/* Ensure role badge readable */
|
||||
.profile .profile-header .basic-info .namerole .role.admin {
|
||||
color: var(--base03);
|
||||
color: var(--base0);
|
||||
}
|
||||
|
||||
.col-header a {
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
/* Distinguish bot icon from background */
|
||||
.profile .profile-header .basic-info .namerole .bot-username-wrapper .bot-legend-wrapper {
|
||||
border: var(--boxshadow-border);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
theme-title: Solarized (dark)
|
||||
theme-description: Solarized sloth (dark)
|
||||
theme-title: Solarized light
|
||||
theme-description: Beige and grey solarized theme with orange trim
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -46,18 +46,14 @@
|
|||
--blue3: var(--base01);
|
||||
|
||||
/* Basic page styling (background + foreground) */
|
||||
--bg: var(--white1);
|
||||
--bg-accent: var(--white2);
|
||||
--bg: var(--base2);
|
||||
--bg-accent: var(--base3);
|
||||
--fg-reduced: var(--base00);
|
||||
--fg: var(--base01);
|
||||
|
||||
/* Profile page styling */
|
||||
--profile-bg: var(--white2);
|
||||
|
||||
/* Solarize buttons */
|
||||
--button-bg: var(--blue2);
|
||||
--button-fg: var(--white1);
|
||||
|
||||
/* Solarize statuses */
|
||||
--status-bg: var(--white1);
|
||||
--status-focus-bg: var(--white1);
|
||||
|
@ -65,7 +61,7 @@
|
|||
--status-focus-info-bg: var(--white2);
|
||||
|
||||
/* Used around statuses + other items */
|
||||
--boxshadow-border: 0.15rem solid var(--base1);
|
||||
--boxshadow-border: 0.1rem solid var(--base1);
|
||||
|
||||
--plyr-video-control-color: var(--fg);
|
||||
--plyr-video-control-color-hover: var(--fg-reduced);
|
||||
|
@ -84,6 +80,36 @@ html, body {
|
|||
scrollbar-color: var(--orange2) var(--white1) ;
|
||||
}
|
||||
|
||||
/* Column headers */
|
||||
.col-header {
|
||||
border: var(--boxshadow-border);
|
||||
background: var(--base3);
|
||||
}
|
||||
|
||||
.profile .about-user .col-header {
|
||||
border-bottom: none;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Header card */
|
||||
.profile .profile-header {
|
||||
border: var(--boxshadow-border);
|
||||
background: var(--base3);
|
||||
}
|
||||
|
||||
/* Fiddle around with borders on about sections */
|
||||
.profile .about-user .fields,
|
||||
.profile .about-user .bio,
|
||||
.profile .about-user .accountstats {
|
||||
background: var(--base3);
|
||||
color: var(--base01);
|
||||
border-left: var(--boxshadow-border);
|
||||
border-right: var(--boxshadow-border);
|
||||
}
|
||||
.profile .about-user .accountstats {
|
||||
border-bottom: var(--boxshadow-border);
|
||||
}
|
||||
|
||||
/* Profile fields */
|
||||
.profile .about-user .fields .field {
|
||||
border-bottom: var(--boxshadow-border);
|
||||
|
@ -98,6 +124,7 @@ html, body {
|
|||
}
|
||||
.status .media .media-wrapper details .unknown-attachment .placeholder {
|
||||
color: var(--base1);
|
||||
border: 0.2rem dashed var(--base1);
|
||||
}
|
||||
.status .media .media-wrapper details video.plyr-video {
|
||||
background: transparent;
|
||||
|
@ -105,10 +132,12 @@ html, body {
|
|||
|
||||
/* Status polls */
|
||||
.status .text .poll {
|
||||
background-color: var(--white2);
|
||||
background-color: var(--base3);
|
||||
border: var(--boxshadow-border);
|
||||
}
|
||||
.status .text .poll .poll-info {
|
||||
background-color: var(--white1);
|
||||
background-color: var(--base3);
|
||||
border: var(--boxshadow-border);
|
||||
}
|
||||
|
||||
/* Code snippets */
|
||||
|
@ -121,7 +150,7 @@ code, code[class*="language-"] {
|
|||
/* Block quotes */
|
||||
blockquote {
|
||||
background-color: var(--base3);
|
||||
color: var(--base00);
|
||||
color: var(--base01);
|
||||
}
|
||||
|
||||
button, .button,
|
||||
|
@ -131,22 +160,32 @@ button, .button,
|
|||
|
||||
.button {
|
||||
color: var(--base01);
|
||||
background: var(--base2);
|
||||
background: var(--base3);
|
||||
border: var(--boxshadow-border);
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
color: var(--base00);
|
||||
background: var(--base3);
|
||||
color: var(--base01);
|
||||
background: var(--base2);
|
||||
border: var(--boxshadow-border);
|
||||
}
|
||||
|
||||
/* Ensure role badge readable */
|
||||
.profile .profile-header .basic-info .namerole .role.admin {
|
||||
color: var(--base3);
|
||||
background: var(--base3);
|
||||
color: var(--base01);
|
||||
}
|
||||
|
||||
.col-header a {
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
/* Back + next links */
|
||||
.backnextlinks {
|
||||
padding: 0.5rem;
|
||||
background: var(--base3);
|
||||
border: var(--boxshadow-border);
|
||||
border-radius: var(--br);
|
||||
}
|
||||
|
||||
.page-footer {
|
||||
margin-top: 2rem;
|
||||
background-color: var(--base3);
|
||||
border-top: var(--boxshadow-border);
|
||||
}
|
||||
|
|
|
@ -41,6 +41,12 @@ main {
|
|||
text-decoration: none;
|
||||
}
|
||||
|
||||
.boosted {
|
||||
padding: 0 0.75rem 0.75rem;
|
||||
color: var(--fg-reduced);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.status-header > address {
|
||||
/*
|
||||
Avoid stretching so wide that user
|
||||
|
@ -59,17 +65,27 @@ main {
|
|||
"avatar author-strap author-strap";
|
||||
gap: 0 0.5rem;
|
||||
font-style: normal;
|
||||
|
||||
|
||||
.avatar {
|
||||
grid-area: avatar;
|
||||
height: 3.5rem;
|
||||
width: 3.5rem;
|
||||
object-fit: cover;
|
||||
|
||||
position: relative;
|
||||
|
||||
border: 0.15rem solid $avatar-border;
|
||||
border-radius: $br;
|
||||
overflow: hidden; /* hides corners from img overflowing */
|
||||
|
||||
|
||||
.boosted-avatar {
|
||||
height: 50%;
|
||||
width: 50%;
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
inset-inline-end: 0;
|
||||
}
|
||||
|
||||
img {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
@ -77,7 +93,7 @@ main {
|
|||
background: $bg;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.author-strap {
|
||||
grid-area: author-strap;
|
||||
display: grid;
|
||||
|
@ -87,7 +103,7 @@ main {
|
|||
"display display"
|
||||
"user user";
|
||||
gap: 0 0.5rem;
|
||||
|
||||
|
||||
.displayname, .username {
|
||||
justify-self: start;
|
||||
align-self: start;
|
||||
|
@ -95,12 +111,12 @@ main {
|
|||
font-size: 1rem;
|
||||
line-height: 1.3rem;
|
||||
}
|
||||
|
||||
|
||||
.displayname {
|
||||
grid-area: display;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
.username {
|
||||
grid-area: user;
|
||||
color: $link-fg;
|
||||
|
@ -200,34 +216,34 @@ 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;
|
||||
|
@ -236,7 +252,7 @@ main {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.poll-info {
|
||||
background-color: $gray4;
|
||||
display: flex;
|
||||
|
@ -245,7 +261,7 @@ main {
|
|||
border-radius: $br-inner;
|
||||
padding: 0.25rem;
|
||||
gap: 0.25rem;
|
||||
|
||||
|
||||
span {
|
||||
justify-self: center;
|
||||
white-space: nowrap;
|
||||
|
@ -301,12 +317,12 @@ main {
|
|||
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:
|
||||
grid-template-areas:
|
||||
"eye sensitive ."
|
||||
". sensitive .";
|
||||
|
||||
|
@ -369,7 +385,7 @@ main {
|
|||
height: 100%;
|
||||
padding: 0.8rem;
|
||||
border: 0.2rem dashed $white2;
|
||||
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
@ -518,4 +534,4 @@ main {
|
|||
.plyr {
|
||||
max-height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ function UserProfileForm({ data: profile }) {
|
|||
maxPinnedFields: instance?.configuration?.accounts?.max_profile_fields ?? 6
|
||||
};
|
||||
}, [instance]);
|
||||
|
||||
|
||||
// Parse out available theme options into nice format.
|
||||
const { data: themes } = useAccountThemesQuery();
|
||||
const themeOptions = useMemo(() => {
|
||||
|
@ -114,6 +114,7 @@ function UserProfileForm({ data: profile }) {
|
|||
locked: useBoolInput("locked", { source: profile }),
|
||||
discoverable: useBoolInput("discoverable", { source: profile}),
|
||||
enableRSS: useBoolInput("enable_rss", { source: profile }),
|
||||
hideBoosts: useBoolInput("hide_boosts", { source: profile }),
|
||||
hideCollections: useBoolInput("hide_collections", { source: profile }),
|
||||
webVisibility: useTextInput("web_visibility", { source: profile, valueSelector: (p) => p.source?.web_visibility }),
|
||||
fields: useFieldArrayInput("fields_attributes", {
|
||||
|
@ -158,7 +159,7 @@ function UserProfileForm({ data: profile }) {
|
|||
autoCapitalize="sentences"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="file-input-with-image-description">
|
||||
<FileInput
|
||||
label="Avatar (1:1 images look best)"
|
||||
|
@ -257,6 +258,10 @@ function UserProfileForm({ data: profile }) {
|
|||
field={form.enableRSS}
|
||||
label="Enable RSS feed of posts."
|
||||
/>
|
||||
<Checkbox
|
||||
field={form.hideBoosts}
|
||||
label="Hide boosts from your public page"
|
||||
/>
|
||||
<Checkbox
|
||||
field={form.hideCollections}
|
||||
label="Hide who you follow / are followed by."
|
||||
|
|
|
@ -247,6 +247,16 @@
|
|||
class="status expanded"
|
||||
{{- includeAttr "status_attributes.tmpl" . | indentAttr 6 }}
|
||||
>
|
||||
{{- if .ReblogAccount }}
|
||||
<div class="boosted text-cutoff">
|
||||
<i class="fa fa-retweet" aria-hidden="true"></i> 
|
||||
{{- if $.account.DisplayName }}
|
||||
{{- emojify $.account.Emojis (escape $.account.DisplayName) }} boosted
|
||||
{{- else }}
|
||||
{{- $.account.Username }} boosted
|
||||
{{- end }}
|
||||
</div>
|
||||
{{- end }}
|
||||
{{- include "status.tmpl" . | indent 6 }}
|
||||
</article>
|
||||
{{- end }}
|
||||
|
@ -264,4 +274,4 @@
|
|||
</div>
|
||||
</div>
|
||||
</main>
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
|
|
@ -48,6 +48,16 @@
|
|||
alt="Avatar for {{ .Username -}}"
|
||||
title="Avatar for {{ .Username -}}"
|
||||
>
|
||||
{{ if $.ReblogAccount }}
|
||||
<img
|
||||
class="boosted-avatar"
|
||||
src="{{ $.ReblogAccount.Avatar }}"
|
||||
alt="Avatar for {{ $.ReblogAccount.Username -}}"
|
||||
title="Avatar for {{ $.ReblogAccount.Username -}}"
|
||||
>
|
||||
{{ end }}
|
||||
|
||||
|
||||
</picture>
|
||||
<div class="author-strap">
|
||||
<span class="displayname text-cutoff">
|
||||
|
@ -63,4 +73,4 @@
|
|||
<span class="sr-only">(open profile)</span>
|
||||
</a>
|
||||
</address>
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
|
Loading…
Reference in a new issue