mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2024-10-31 22:40:01 +00:00
[feature] Web profile pages for accounts (#449)
* add default avatars * allow webModule to error * return errWithCode from account get * add AccountGetLocalByUsername * check nil requesting account * add timestampShort function for just month/year * move loading logic to New + add default avatars * add profile page view * update swagger docs * add excludeReblogs to GetAccountStatuses * ignore casing when selecting local account by username * appropriate redirects * css fiddling * add 'about' heading * adjust thread page to work with routing * return AP representation if requested + authorized * simplify auth check * go fmt * golangci-lint ignore math/rand
This commit is contained in:
parent
a7e9dee33d
commit
26683b3d49
33 changed files with 1484 additions and 88 deletions
|
@ -148,6 +148,12 @@
|
||||||
return fmt.Errorf("error creating oidc idp: %s", err)
|
return fmt.Errorf("error creating oidc idp: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// build web module
|
||||||
|
webModule, err := web.New(processor)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error creating web module: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
// build client api modules
|
// build client api modules
|
||||||
authModule := auth.New(dbService, oauthServer, idp)
|
authModule := auth.New(dbService, oauthServer, idp)
|
||||||
accountModule := account.New(processor)
|
accountModule := account.New(processor)
|
||||||
|
@ -156,7 +162,6 @@
|
||||||
followRequestsModule := followrequest.New(processor)
|
followRequestsModule := followrequest.New(processor)
|
||||||
webfingerModule := webfinger.New(processor)
|
webfingerModule := webfinger.New(processor)
|
||||||
nodeInfoModule := nodeinfo.New(processor)
|
nodeInfoModule := nodeinfo.New(processor)
|
||||||
webBaseModule := web.New(processor)
|
|
||||||
usersModule := user.New(processor)
|
usersModule := user.New(processor)
|
||||||
timelineModule := timeline.New(processor)
|
timelineModule := timeline.New(processor)
|
||||||
notificationModule := notification.New(processor)
|
notificationModule := notification.New(processor)
|
||||||
|
@ -179,8 +184,10 @@
|
||||||
securityModule,
|
securityModule,
|
||||||
authModule,
|
authModule,
|
||||||
|
|
||||||
|
// now the web module
|
||||||
|
webModule,
|
||||||
|
|
||||||
// now everything else
|
// now everything else
|
||||||
webBaseModule,
|
|
||||||
accountModule,
|
accountModule,
|
||||||
instanceModule,
|
instanceModule,
|
||||||
appsModule,
|
appsModule,
|
||||||
|
|
|
@ -95,6 +95,12 @@
|
||||||
return fmt.Errorf("error creating oidc idp: %s", err)
|
return fmt.Errorf("error creating oidc idp: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// build web module
|
||||||
|
webModule, err := web.New(processor)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error creating web module: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
// build client api modules
|
// build client api modules
|
||||||
authModule := auth.New(dbService, oauthServer, idp)
|
authModule := auth.New(dbService, oauthServer, idp)
|
||||||
accountModule := account.New(processor)
|
accountModule := account.New(processor)
|
||||||
|
@ -103,7 +109,6 @@
|
||||||
followRequestsModule := followrequest.New(processor)
|
followRequestsModule := followrequest.New(processor)
|
||||||
webfingerModule := webfinger.New(processor)
|
webfingerModule := webfinger.New(processor)
|
||||||
nodeInfoModule := nodeinfo.New(processor)
|
nodeInfoModule := nodeinfo.New(processor)
|
||||||
webBaseModule := web.New(processor)
|
|
||||||
usersModule := user.New(processor)
|
usersModule := user.New(processor)
|
||||||
timelineModule := timeline.New(processor)
|
timelineModule := timeline.New(processor)
|
||||||
notificationModule := notification.New(processor)
|
notificationModule := notification.New(processor)
|
||||||
|
@ -126,8 +131,10 @@
|
||||||
securityModule,
|
securityModule,
|
||||||
authModule,
|
authModule,
|
||||||
|
|
||||||
|
// now the web module
|
||||||
|
webModule,
|
||||||
|
|
||||||
// now everything else
|
// now everything else
|
||||||
webBaseModule,
|
|
||||||
accountModule,
|
accountModule,
|
||||||
instanceModule,
|
instanceModule,
|
||||||
appsModule,
|
appsModule,
|
||||||
|
|
|
@ -2086,6 +2086,11 @@ paths:
|
||||||
in: query
|
in: query
|
||||||
name: exclude_replies
|
name: exclude_replies
|
||||||
type: boolean
|
type: boolean
|
||||||
|
- default: false
|
||||||
|
description: Exclude statuses that are a reblog/boost of another status.
|
||||||
|
in: query
|
||||||
|
name: exclude_reblogs
|
||||||
|
type: boolean
|
||||||
- description: |-
|
- description: |-
|
||||||
Return only statuses *OLDER* than the given max status ID.
|
Return only statuses *OLDER* than the given max status ID.
|
||||||
The status with the specified ID will not be included in the response.
|
The status with the specified ID will not be included in the response.
|
||||||
|
@ -2099,7 +2104,7 @@ paths:
|
||||||
name: min_id
|
name: min_id
|
||||||
type: string
|
type: string
|
||||||
- default: false
|
- default: false
|
||||||
description: Show only pinned statuses. In other words,e xclude statuses that
|
description: Show only pinned statuses. In other words, exclude statuses that
|
||||||
are not pinned to the given account ID.
|
are not pinned to the given account ID.
|
||||||
in: query
|
in: query
|
||||||
name: pinned_only
|
name: pinned_only
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
LimitKey = "limit"
|
LimitKey = "limit"
|
||||||
// ExcludeRepliesKey is for specifying whether to exclude replies in a list of returned statuses by an account.
|
// ExcludeRepliesKey is for specifying whether to exclude replies in a list of returned statuses by an account.
|
||||||
ExcludeRepliesKey = "exclude_replies"
|
ExcludeRepliesKey = "exclude_replies"
|
||||||
|
// ExcludeReblogsKey is for specifying whether to exclude reblogs in a list of returned statuses by an account.
|
||||||
|
ExcludeReblogsKey = "exclude_reblogs"
|
||||||
// PinnedKey is for specifying whether to include pinned statuses in a list of returned statuses by an account.
|
// PinnedKey is for specifying whether to include pinned statuses in a list of returned statuses by an account.
|
||||||
PinnedKey = "pinned"
|
PinnedKey = "pinned"
|
||||||
// MaxIDKey is for specifying the maximum ID of the status to retrieve.
|
// MaxIDKey is for specifying the maximum ID of the status to retrieve.
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/api"
|
"github.com/superseriousbusiness/gotosocial/internal/api"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
||||||
)
|
)
|
||||||
|
@ -76,9 +77,10 @@ func (m *Module) AccountGETHandler(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
acctInfo, err := m.processor.AccountGet(c.Request.Context(), authed, targetAcctID)
|
acctInfo, errWithCode := m.processor.AccountGet(c.Request.Context(), authed, targetAcctID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
|
logrus.Debug(errWithCode.Error())
|
||||||
|
c.JSON(errWithCode.Code(), gin.H{"error": errWithCode.Safe()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,12 @@
|
||||||
// default: false
|
// default: false
|
||||||
// in: query
|
// in: query
|
||||||
// required: false
|
// required: false
|
||||||
|
// - name: exclude_reblogs
|
||||||
|
// type: boolean
|
||||||
|
// description: Exclude statuses that are a reblog/boost of another status.
|
||||||
|
// default: false
|
||||||
|
// in: query
|
||||||
|
// required: false
|
||||||
// - name: max_id
|
// - name: max_id
|
||||||
// type: string
|
// type: string
|
||||||
// description: |-
|
// description: |-
|
||||||
|
@ -75,7 +81,7 @@
|
||||||
// required: false
|
// required: false
|
||||||
// - name: pinned_only
|
// - name: pinned_only
|
||||||
// type: boolean
|
// type: boolean
|
||||||
// description: Show only pinned statuses. In other words,e xclude statuses that are not pinned to the given account ID.
|
// description: Show only pinned statuses. In other words, exclude statuses that are not pinned to the given account ID.
|
||||||
// default: false
|
// default: false
|
||||||
// in: query
|
// in: query
|
||||||
// required: false
|
// required: false
|
||||||
|
@ -149,13 +155,25 @@ func (m *Module) AccountStatusesGETHandler(c *gin.Context) {
|
||||||
if excludeRepliesString != "" {
|
if excludeRepliesString != "" {
|
||||||
i, err := strconv.ParseBool(excludeRepliesString)
|
i, err := strconv.ParseBool(excludeRepliesString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Debugf("error parsing replies string: %s", err)
|
l.Debugf("error parsing exclude replies string: %s", err)
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "couldn't parse exclude replies query param"})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "couldn't parse exclude replies query param"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
excludeReplies = i
|
excludeReplies = i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
excludeReblogs := false
|
||||||
|
excludeReblogsString := c.Query(ExcludeReblogsKey)
|
||||||
|
if excludeReblogsString != "" {
|
||||||
|
i, err := strconv.ParseBool(excludeReblogsString)
|
||||||
|
if err != nil {
|
||||||
|
l.Debugf("error parsing exclude reblogs string: %s", err)
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": "couldn't parse exclude reblogs query param"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
excludeReblogs = i
|
||||||
|
}
|
||||||
|
|
||||||
maxID := ""
|
maxID := ""
|
||||||
maxIDString := c.Query(MaxIDKey)
|
maxIDString := c.Query(MaxIDKey)
|
||||||
if maxIDString != "" {
|
if maxIDString != "" {
|
||||||
|
@ -204,7 +222,7 @@ func (m *Module) AccountStatusesGETHandler(c *gin.Context) {
|
||||||
publicOnly = i
|
publicOnly = i
|
||||||
}
|
}
|
||||||
|
|
||||||
statuses, errWithCode := m.processor.AccountStatusesGet(c.Request.Context(), authed, targetAcctID, limit, excludeReplies, maxID, minID, pinnedOnly, mediaOnly, publicOnly)
|
statuses, errWithCode := m.processor.AccountStatusesGet(c.Request.Context(), authed, targetAcctID, limit, excludeReplies, excludeReblogs, maxID, minID, pinnedOnly, mediaOnly, publicOnly)
|
||||||
if errWithCode != nil {
|
if errWithCode != nil {
|
||||||
l.Debugf("error from processor account statuses get: %s", errWithCode)
|
l.Debugf("error from processor account statuses get: %s", errWithCode)
|
||||||
c.JSON(errWithCode.Code(), gin.H{"error": errWithCode.Safe()})
|
c.JSON(errWithCode.Code(), gin.H{"error": errWithCode.Safe()})
|
||||||
|
|
|
@ -440,7 +440,7 @@ func (suite *InboxPostTestSuite) TestPostDelete() {
|
||||||
suite.ErrorIs(err, db.ErrNoEntries)
|
suite.ErrorIs(err, db.ErrNoEntries)
|
||||||
|
|
||||||
// no statuses from foss satan should be left in the database
|
// no statuses from foss satan should be left in the database
|
||||||
dbStatuses, err := suite.db.GetAccountStatuses(ctx, deletedAccount.ID, 0, false, "", "", false, false, false)
|
dbStatuses, err := suite.db.GetAccountStatuses(ctx, deletedAccount.ID, 0, false, false, "", "", false, false, false)
|
||||||
suite.ErrorIs(err, db.ErrNoEntries)
|
suite.ErrorIs(err, db.ErrNoEntries)
|
||||||
suite.Empty(dbStatuses)
|
suite.Empty(dbStatuses)
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ type Account interface {
|
||||||
// then all statuses will be returned. If limit is set to 0, the size of the returned slice will not be limited. This can
|
// then all statuses will be returned. If limit is set to 0, the size of the returned slice will not be limited. This can
|
||||||
// be very memory intensive so you probably shouldn't do this!
|
// be very memory intensive so you probably shouldn't do this!
|
||||||
// In case of no entries, a 'no entries' error will be returned
|
// In case of no entries, a 'no entries' error will be returned
|
||||||
GetAccountStatuses(ctx context.Context, accountID string, limit int, excludeReplies bool, maxID string, minID string, pinnedOnly bool, mediaOnly bool, publicOnly bool) ([]*gtsmodel.Status, Error)
|
GetAccountStatuses(ctx context.Context, accountID string, limit int, excludeReplies bool, excludeReblogs bool, maxID string, minID string, pinnedOnly bool, mediaOnly bool, publicOnly bool) ([]*gtsmodel.Status, Error)
|
||||||
|
|
||||||
GetAccountBlocks(ctx context.Context, accountID string, maxID string, sinceID string, limit int) ([]*gtsmodel.Account, string, string, Error)
|
GetAccountBlocks(ctx context.Context, accountID string, maxID string, sinceID string, limit int) ([]*gtsmodel.Account, string, string, Error)
|
||||||
|
|
||||||
|
|
|
@ -199,7 +199,7 @@ func (a *accountDB) GetLocalAccountByUsername(ctx context.Context, username stri
|
||||||
account := new(gtsmodel.Account)
|
account := new(gtsmodel.Account)
|
||||||
|
|
||||||
q := a.newAccountQ(account).
|
q := a.newAccountQ(account).
|
||||||
Where("username = ?", username).
|
Where("LOWER(?) = LOWER(?)", bun.Ident("username"), username). // ignore casing
|
||||||
WhereGroup(" AND ", whereEmptyOrNull("domain"))
|
WhereGroup(" AND ", whereEmptyOrNull("domain"))
|
||||||
|
|
||||||
if err := q.Scan(ctx); err != nil {
|
if err := q.Scan(ctx); err != nil {
|
||||||
|
@ -230,7 +230,7 @@ func (a *accountDB) CountAccountStatuses(ctx context.Context, accountID string)
|
||||||
Count(ctx)
|
Count(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *accountDB) GetAccountStatuses(ctx context.Context, accountID string, limit int, excludeReplies bool, maxID string, minID string, pinnedOnly bool, mediaOnly bool, publicOnly bool) ([]*gtsmodel.Status, db.Error) {
|
func (a *accountDB) GetAccountStatuses(ctx context.Context, accountID string, limit int, excludeReplies bool, excludeReblogs bool, maxID string, minID string, pinnedOnly bool, mediaOnly bool, publicOnly bool) ([]*gtsmodel.Status, db.Error) {
|
||||||
statuses := []*gtsmodel.Status{}
|
statuses := []*gtsmodel.Status{}
|
||||||
|
|
||||||
q := a.conn.
|
q := a.conn.
|
||||||
|
@ -250,6 +250,10 @@ func (a *accountDB) GetAccountStatuses(ctx context.Context, accountID string, li
|
||||||
q = q.WhereGroup(" AND ", whereEmptyOrNull("in_reply_to_id"))
|
q = q.WhereGroup(" AND ", whereEmptyOrNull("in_reply_to_id"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if excludeReblogs {
|
||||||
|
q = q.WhereGroup(" AND ", whereEmptyOrNull("boost_of_id"))
|
||||||
|
}
|
||||||
|
|
||||||
if maxID != "" {
|
if maxID != "" {
|
||||||
q = q.Where("id < ?", maxID)
|
q = q.Where("id < ?", maxID)
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,16 +34,20 @@ func (p *processor) AccountDeleteLocal(ctx context.Context, authed *oauth.Auth,
|
||||||
return p.accountProcessor.DeleteLocal(ctx, authed.Account, form)
|
return p.accountProcessor.DeleteLocal(ctx, authed.Account, form)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *processor) AccountGet(ctx context.Context, authed *oauth.Auth, targetAccountID string) (*apimodel.Account, error) {
|
func (p *processor) AccountGet(ctx context.Context, authed *oauth.Auth, targetAccountID string) (*apimodel.Account, gtserror.WithCode) {
|
||||||
return p.accountProcessor.Get(ctx, authed.Account, targetAccountID)
|
return p.accountProcessor.Get(ctx, authed.Account, targetAccountID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *processor) AccountGetLocalByUsername(ctx context.Context, authed *oauth.Auth, username string) (*apimodel.Account, gtserror.WithCode) {
|
||||||
|
return p.accountProcessor.GetLocalByUsername(ctx, authed.Account, username)
|
||||||
|
}
|
||||||
|
|
||||||
func (p *processor) AccountUpdate(ctx context.Context, authed *oauth.Auth, form *apimodel.UpdateCredentialsRequest) (*apimodel.Account, error) {
|
func (p *processor) AccountUpdate(ctx context.Context, authed *oauth.Auth, form *apimodel.UpdateCredentialsRequest) (*apimodel.Account, error) {
|
||||||
return p.accountProcessor.Update(ctx, authed.Account, form)
|
return p.accountProcessor.Update(ctx, authed.Account, form)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *processor) AccountStatusesGet(ctx context.Context, authed *oauth.Auth, targetAccountID string, limit int, excludeReplies bool, maxID string, minID string, pinnedOnly bool, mediaOnly bool, publicOnly bool) ([]apimodel.Status, gtserror.WithCode) {
|
func (p *processor) AccountStatusesGet(ctx context.Context, authed *oauth.Auth, targetAccountID string, limit int, excludeReplies bool, excludeReblogs bool, maxID string, minID string, pinnedOnly bool, mediaOnly bool, publicOnly bool) ([]apimodel.Status, gtserror.WithCode) {
|
||||||
return p.accountProcessor.StatusesGet(ctx, authed.Account, targetAccountID, limit, excludeReplies, maxID, minID, pinnedOnly, mediaOnly, publicOnly)
|
return p.accountProcessor.StatusesGet(ctx, authed.Account, targetAccountID, limit, excludeReplies, excludeReblogs, maxID, minID, pinnedOnly, mediaOnly, publicOnly)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *processor) AccountFollowersGet(ctx context.Context, authed *oauth.Auth, targetAccountID string) ([]apimodel.Account, gtserror.WithCode) {
|
func (p *processor) AccountFollowersGet(ctx context.Context, authed *oauth.Auth, targetAccountID string) ([]apimodel.Account, gtserror.WithCode) {
|
||||||
|
|
|
@ -47,12 +47,14 @@ type Processor interface {
|
||||||
// Unlike Delete, it will propagate the deletion out across the federating API to other instances.
|
// Unlike Delete, it will propagate the deletion out across the federating API to other instances.
|
||||||
DeleteLocal(ctx context.Context, account *gtsmodel.Account, form *apimodel.AccountDeleteRequest) gtserror.WithCode
|
DeleteLocal(ctx context.Context, account *gtsmodel.Account, form *apimodel.AccountDeleteRequest) gtserror.WithCode
|
||||||
// Get processes the given request for account information.
|
// Get processes the given request for account information.
|
||||||
Get(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccountID string) (*apimodel.Account, error)
|
Get(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccountID string) (*apimodel.Account, gtserror.WithCode)
|
||||||
|
// GetLocalByUsername processes the given request for account information targeting a local account by username.
|
||||||
|
GetLocalByUsername(ctx context.Context, requestingAccount *gtsmodel.Account, username string) (*apimodel.Account, gtserror.WithCode)
|
||||||
// Update processes the update of an account with the given form
|
// Update processes the update of an account with the given form
|
||||||
Update(ctx context.Context, account *gtsmodel.Account, form *apimodel.UpdateCredentialsRequest) (*apimodel.Account, error)
|
Update(ctx context.Context, account *gtsmodel.Account, form *apimodel.UpdateCredentialsRequest) (*apimodel.Account, error)
|
||||||
// StatusesGet fetches a number of statuses (in time descending order) from the given account, filtered by visibility for
|
// StatusesGet fetches a number of statuses (in time descending order) from the given account, filtered by visibility for
|
||||||
// the account given in authed.
|
// the account given in authed.
|
||||||
StatusesGet(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccountID string, limit int, excludeReplies bool, maxID string, minID string, pinned bool, mediaOnly bool, publicOnly bool) ([]apimodel.Status, gtserror.WithCode)
|
StatusesGet(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccountID string, limit int, excludeReplies bool, excludeReblogs bool, maxID string, minID string, pinned bool, mediaOnly bool, publicOnly bool) ([]apimodel.Status, gtserror.WithCode)
|
||||||
// FollowersGet fetches a list of the target account's followers.
|
// FollowersGet fetches a list of the target account's followers.
|
||||||
FollowersGet(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccountID string) ([]apimodel.Account, gtserror.WithCode)
|
FollowersGet(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccountID string) ([]apimodel.Account, gtserror.WithCode)
|
||||||
// FollowingGet fetches a list of the accounts that target account is following.
|
// FollowingGet fetches a list of the accounts that target account is following.
|
||||||
|
|
|
@ -143,7 +143,7 @@ func (p *processor) Delete(ctx context.Context, account *gtsmodel.Account, origi
|
||||||
var maxID string
|
var maxID string
|
||||||
selectStatusesLoop:
|
selectStatusesLoop:
|
||||||
for {
|
for {
|
||||||
statuses, err := p.db.GetAccountStatuses(ctx, account.ID, 20, false, maxID, "", false, false, false)
|
statuses, err := p.db.GetAccountStatuses(ctx, account.ID, 20, false, false, maxID, "", false, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == db.ErrNoEntries {
|
if err == db.ErrNoEntries {
|
||||||
// no statuses left for this instance so we're done
|
// no statuses left for this instance so we're done
|
||||||
|
|
|
@ -26,23 +26,41 @@
|
||||||
|
|
||||||
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *processor) Get(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccountID string) (*apimodel.Account, error) {
|
func (p *processor) Get(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccountID string) (*apimodel.Account, gtserror.WithCode) {
|
||||||
targetAccount, err := p.db.GetAccountByID(ctx, targetAccountID)
|
targetAccount, err := p.db.GetAccountByID(ctx, targetAccountID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == db.ErrNoEntries {
|
if err == db.ErrNoEntries {
|
||||||
return nil, errors.New("account not found")
|
return nil, gtserror.NewErrorNotFound(errors.New("account not found"))
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("db error: %s", err)
|
return nil, gtserror.NewErrorInternalError(fmt.Errorf("db error: %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return p.getAccountFor(ctx, requestingAccount, targetAccount)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *processor) GetLocalByUsername(ctx context.Context, requestingAccount *gtsmodel.Account, username string) (*apimodel.Account, gtserror.WithCode) {
|
||||||
|
targetAccount, err := p.db.GetLocalAccountByUsername(ctx, username)
|
||||||
|
if err != nil {
|
||||||
|
if err == db.ErrNoEntries {
|
||||||
|
return nil, gtserror.NewErrorNotFound(errors.New("account not found"))
|
||||||
|
}
|
||||||
|
return nil, gtserror.NewErrorInternalError(fmt.Errorf("db error: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.getAccountFor(ctx, requestingAccount, targetAccount)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *processor) getAccountFor(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccount *gtsmodel.Account) (*apimodel.Account, gtserror.WithCode) {
|
||||||
var blocked bool
|
var blocked bool
|
||||||
|
var err error
|
||||||
if requestingAccount != nil {
|
if requestingAccount != nil {
|
||||||
blocked, err = p.db.IsBlocked(ctx, requestingAccount.ID, targetAccountID, true)
|
blocked, err = p.db.IsBlocked(ctx, requestingAccount.ID, targetAccount.ID, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error checking account block: %s", err)
|
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error checking account block: %s", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +68,7 @@ func (p *processor) Get(ctx context.Context, requestingAccount *gtsmodel.Account
|
||||||
if blocked {
|
if blocked {
|
||||||
apiAccount, err = p.tc.AccountToAPIAccountBlocked(ctx, targetAccount)
|
apiAccount, err = p.tc.AccountToAPIAccountBlocked(ctx, targetAccount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error converting account: %s", err)
|
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting account: %s", err))
|
||||||
}
|
}
|
||||||
return apiAccount, nil
|
return apiAccount, nil
|
||||||
}
|
}
|
||||||
|
@ -59,7 +77,7 @@ func (p *processor) Get(ctx context.Context, requestingAccount *gtsmodel.Account
|
||||||
if targetAccount.Domain != "" {
|
if targetAccount.Domain != "" {
|
||||||
targetAccountURI, err := url.Parse(targetAccount.URI)
|
targetAccountURI, err := url.Parse(targetAccount.URI)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error parsing url %s: %s", targetAccount.URI, err)
|
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error parsing url %s: %s", targetAccount.URI, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
a, err := p.federator.GetRemoteAccount(ctx, requestingAccount.Username, targetAccountURI, true, false)
|
a, err := p.federator.GetRemoteAccount(ctx, requestingAccount.Username, targetAccountURI, true, false)
|
||||||
|
@ -74,7 +92,7 @@ func (p *processor) Get(ctx context.Context, requestingAccount *gtsmodel.Account
|
||||||
apiAccount, err = p.tc.AccountToAPIAccountPublic(ctx, targetAccount)
|
apiAccount, err = p.tc.AccountToAPIAccountPublic(ctx, targetAccount)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error converting account: %s", err)
|
return nil, gtserror.NewErrorInternalError(fmt.Errorf("error converting account: %s", err))
|
||||||
}
|
}
|
||||||
return apiAccount, nil
|
return apiAccount, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,16 +28,18 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *processor) StatusesGet(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccountID string, limit int, excludeReplies bool, maxID string, minID string, pinnedOnly bool, mediaOnly bool, publicOnly bool) ([]apimodel.Status, gtserror.WithCode) {
|
func (p *processor) StatusesGet(ctx context.Context, requestingAccount *gtsmodel.Account, targetAccountID string, limit int, excludeReplies bool, excludeReblogs bool, maxID string, minID string, pinnedOnly bool, mediaOnly bool, publicOnly bool) ([]apimodel.Status, gtserror.WithCode) {
|
||||||
if blocked, err := p.db.IsBlocked(ctx, requestingAccount.ID, targetAccountID, true); err != nil {
|
if requestingAccount != nil {
|
||||||
return nil, gtserror.NewErrorInternalError(err)
|
if blocked, err := p.db.IsBlocked(ctx, requestingAccount.ID, targetAccountID, true); err != nil {
|
||||||
} else if blocked {
|
return nil, gtserror.NewErrorInternalError(err)
|
||||||
return nil, gtserror.NewErrorNotFound(fmt.Errorf("block exists between accounts"))
|
} else if blocked {
|
||||||
|
return nil, gtserror.NewErrorNotFound(fmt.Errorf("block exists between accounts"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
apiStatuses := []apimodel.Status{}
|
apiStatuses := []apimodel.Status{}
|
||||||
|
|
||||||
statuses, err := p.db.GetAccountStatuses(ctx, targetAccountID, limit, excludeReplies, maxID, minID, pinnedOnly, mediaOnly, publicOnly)
|
statuses, err := p.db.GetAccountStatuses(ctx, targetAccountID, limit, excludeReplies, excludeReblogs, maxID, minID, pinnedOnly, mediaOnly, publicOnly)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == db.ErrNoEntries {
|
if err == db.ErrNoEntries {
|
||||||
return apiStatuses, nil
|
return apiStatuses, nil
|
||||||
|
|
|
@ -89,7 +89,7 @@ func (p *processor) GetOutbox(ctx context.Context, requestedUsername string, pag
|
||||||
|
|
||||||
// scenario 2 -- get the requested page
|
// scenario 2 -- get the requested page
|
||||||
// limit pages to 30 entries per page
|
// limit pages to 30 entries per page
|
||||||
publicStatuses, err := p.db.GetAccountStatuses(ctx, requestedAccount.ID, 30, true, maxID, minID, false, false, true)
|
publicStatuses, err := p.db.GetAccountStatuses(ctx, requestedAccount.ID, 30, true, true, maxID, minID, false, false, true)
|
||||||
if err != nil && err != db.ErrNoEntries {
|
if err != nil && err != db.ErrNoEntries {
|
||||||
return nil, gtserror.NewErrorInternalError(err)
|
return nil, gtserror.NewErrorInternalError(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,17 +38,20 @@ func (p *processor) GetUser(ctx context.Context, requestedUsername string, reque
|
||||||
}
|
}
|
||||||
|
|
||||||
var requestedPerson vocab.ActivityStreamsPerson
|
var requestedPerson vocab.ActivityStreamsPerson
|
||||||
switch {
|
if uris.IsPublicKeyPath(requestURL) {
|
||||||
case uris.IsPublicKeyPath(requestURL):
|
|
||||||
// if it's a public key path, we don't need to authenticate but we'll only serve the bare minimum user profile needed for the public key
|
// if it's a public key path, we don't need to authenticate but we'll only serve the bare minimum user profile needed for the public key
|
||||||
requestedPerson, err = p.tc.AccountToASMinimal(ctx, requestedAccount)
|
requestedPerson, err = p.tc.AccountToASMinimal(ctx, requestedAccount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, gtserror.NewErrorInternalError(err)
|
return nil, gtserror.NewErrorInternalError(err)
|
||||||
}
|
}
|
||||||
case uris.IsUserPath(requestURL):
|
} else {
|
||||||
// if it's a user path, we want to fully authenticate the request before we serve any data, and then we can serve a more complete profile
|
// if it's any other path, we want to fully authenticate the request before we serve any data, and then we can serve a more complete profile
|
||||||
requestingAccountURI, authenticated, err := p.federator.AuthenticateFederatedRequest(ctx, requestedUsername)
|
requestingAccountURI, authenticated, err := p.federator.AuthenticateFederatedRequest(ctx, requestedUsername)
|
||||||
if err != nil || !authenticated {
|
if err != nil {
|
||||||
|
return nil, gtserror.NewErrorNotAuthorized(err, "not authorized")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !authenticated {
|
||||||
return nil, gtserror.NewErrorNotAuthorized(errors.New("not authorized"), "not authorized")
|
return nil, gtserror.NewErrorNotAuthorized(errors.New("not authorized"), "not authorized")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,8 +76,6 @@ func (p *processor) GetUser(ctx context.Context, requestedUsername string, reque
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, gtserror.NewErrorInternalError(err)
|
return nil, gtserror.NewErrorInternalError(err)
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
return nil, gtserror.NewErrorBadRequest(fmt.Errorf("path was not public key path or user path"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := streams.Serialize(requestedPerson)
|
data, err := streams.Serialize(requestedPerson)
|
||||||
|
|
|
@ -354,7 +354,7 @@ func (suite *FromFederatorTestSuite) TestProcessAccountDelete() {
|
||||||
suite.False(zorkFollowsSatan)
|
suite.False(zorkFollowsSatan)
|
||||||
|
|
||||||
// no statuses from foss satan should be left in the database
|
// no statuses from foss satan should be left in the database
|
||||||
dbStatuses, err := suite.db.GetAccountStatuses(ctx, deletedAccount.ID, 0, false, "", "", false, false, false)
|
dbStatuses, err := suite.db.GetAccountStatuses(ctx, deletedAccount.ID, 0, false, false, "", "", false, false, false)
|
||||||
suite.ErrorIs(err, db.ErrNoEntries)
|
suite.ErrorIs(err, db.ErrNoEntries)
|
||||||
suite.Empty(dbStatuses)
|
suite.Empty(dbStatuses)
|
||||||
|
|
||||||
|
|
|
@ -76,12 +76,14 @@ type Processor interface {
|
||||||
// AccountDeleteLocal processes the delete of a LOCAL account using the given form.
|
// AccountDeleteLocal processes the delete of a LOCAL account using the given form.
|
||||||
AccountDeleteLocal(ctx context.Context, authed *oauth.Auth, form *apimodel.AccountDeleteRequest) gtserror.WithCode
|
AccountDeleteLocal(ctx context.Context, authed *oauth.Auth, form *apimodel.AccountDeleteRequest) gtserror.WithCode
|
||||||
// AccountGet processes the given request for account information.
|
// AccountGet processes the given request for account information.
|
||||||
AccountGet(ctx context.Context, authed *oauth.Auth, targetAccountID string) (*apimodel.Account, error)
|
AccountGet(ctx context.Context, authed *oauth.Auth, targetAccountID string) (*apimodel.Account, gtserror.WithCode)
|
||||||
|
// AccountGet processes the given request for account information.
|
||||||
|
AccountGetLocalByUsername(ctx context.Context, authed *oauth.Auth, username string) (*apimodel.Account, gtserror.WithCode)
|
||||||
// AccountUpdate processes the update of an account with the given form
|
// AccountUpdate processes the update of an account with the given form
|
||||||
AccountUpdate(ctx context.Context, authed *oauth.Auth, form *apimodel.UpdateCredentialsRequest) (*apimodel.Account, error)
|
AccountUpdate(ctx context.Context, authed *oauth.Auth, form *apimodel.UpdateCredentialsRequest) (*apimodel.Account, error)
|
||||||
// AccountStatusesGet fetches a number of statuses (in time descending order) from the given account, filtered by visibility for
|
// AccountStatusesGet fetches a number of statuses (in time descending order) from the given account, filtered by visibility for
|
||||||
// the account given in authed.
|
// the account given in authed.
|
||||||
AccountStatusesGet(ctx context.Context, authed *oauth.Auth, targetAccountID string, limit int, excludeReplies bool, maxID string, minID string, pinned bool, mediaOnly bool, publicOnly bool) ([]apimodel.Status, gtserror.WithCode)
|
AccountStatusesGet(ctx context.Context, authed *oauth.Auth, targetAccountID string, limit int, excludeReplies bool, excludeReblogs bool, maxID string, minID string, pinned bool, mediaOnly bool, publicOnly bool) ([]apimodel.Status, gtserror.WithCode)
|
||||||
// AccountFollowersGet fetches a list of the target account's followers.
|
// AccountFollowersGet fetches a list of the target account's followers.
|
||||||
AccountFollowersGet(ctx context.Context, authed *oauth.Auth, targetAccountID string) ([]apimodel.Account, gtserror.WithCode)
|
AccountFollowersGet(ctx context.Context, authed *oauth.Auth, targetAccountID string) ([]apimodel.Account, gtserror.WithCode)
|
||||||
// AccountFollowingGet fetches a list of the accounts that target account is following.
|
// AccountFollowingGet fetches a list of the accounts that target account is following.
|
||||||
|
|
|
@ -67,6 +67,11 @@ func timestamp(stamp string) string {
|
||||||
return t.Format("January 2, 2006, 15:04:05")
|
return t.Format("January 2, 2006, 15:04:05")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func timestampShort(stamp string) string {
|
||||||
|
t, _ := time.Parse(time.RFC3339, stamp)
|
||||||
|
return t.Format("January, 2006")
|
||||||
|
}
|
||||||
|
|
||||||
type iconWithLabel struct {
|
type iconWithLabel struct {
|
||||||
faIcon string
|
faIcon string
|
||||||
label string
|
label string
|
||||||
|
@ -98,5 +103,6 @@ func LoadTemplateFunctions(engine *gin.Engine) {
|
||||||
"oddOrEven": oddOrEven,
|
"oddOrEven": oddOrEven,
|
||||||
"visibilityIcon": visibilityIcon,
|
"visibilityIcon": visibilityIcon,
|
||||||
"timestamp": timestamp,
|
"timestamp": timestamp,
|
||||||
|
"timestampShort": timestampShort,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,7 +132,7 @@ func (suite *InternalToASTestSuite) TestStatusesToASOutboxPage() {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
// get public statuses from testaccount
|
// get public statuses from testaccount
|
||||||
statuses, err := suite.db.GetAccountStatuses(ctx, testAccount.ID, 30, true, "", "", false, false, true)
|
statuses, err := suite.db.GetAccountStatuses(ctx, testAccount.ID, 30, true, true, "", "", false, false, true)
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
|
|
||||||
page, err := suite.typeconverter.StatusesToASOutboxPage(ctx, testAccount.OutboxURI, "", "", statuses)
|
page, err := suite.typeconverter.StatusesToASOutboxPage(ctx, testAccount.OutboxURI, "", "", statuses)
|
||||||
|
|
|
@ -20,8 +20,10 @@
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
@ -36,18 +38,68 @@
|
||||||
const (
|
const (
|
||||||
confirmEmailPath = "/" + uris.ConfirmEmailPath
|
confirmEmailPath = "/" + uris.ConfirmEmailPath
|
||||||
tokenParam = "token"
|
tokenParam = "token"
|
||||||
|
usernameKey = "username"
|
||||||
|
statusIDKey = "status"
|
||||||
|
profilePath = "/@:" + usernameKey
|
||||||
|
statusPath = profilePath + "/statuses/:" + statusIDKey
|
||||||
)
|
)
|
||||||
|
|
||||||
// Module implements the api.ClientModule interface for web pages.
|
// Module implements the api.ClientModule interface for web pages.
|
||||||
type Module struct {
|
type Module struct {
|
||||||
processor processing.Processor
|
processor processing.Processor
|
||||||
|
assetsPath string
|
||||||
|
adminPath string
|
||||||
|
defaultAvatars []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new api.ClientModule for web pages.
|
// New returns a new api.ClientModule for web pages.
|
||||||
func New(processor processing.Processor) api.ClientModule {
|
func New(processor processing.Processor) (api.ClientModule, error) {
|
||||||
return &Module{
|
assetsBaseDir := viper.GetString(config.Keys.WebAssetBaseDir)
|
||||||
processor: processor,
|
if assetsBaseDir == "" {
|
||||||
|
return nil, fmt.Errorf("%s cannot be empty and must be a relative or absolute path", config.Keys.WebAssetBaseDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assetsPath, err := filepath.Abs(assetsBaseDir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error getting absolute path of %s: %s", assetsBaseDir, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultAvatarsPath := filepath.Join(assetsPath, "default_avatars")
|
||||||
|
defaultAvatarFiles, err := ioutil.ReadDir(defaultAvatarsPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error reading default avatars at %s: %s", defaultAvatarsPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultAvatars := []string{}
|
||||||
|
for _, f := range defaultAvatarFiles {
|
||||||
|
// ignore directories
|
||||||
|
if f.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore files bigger than 50kb
|
||||||
|
if f.Size() > 50000 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
extension := strings.TrimPrefix(strings.ToLower(filepath.Ext(f.Name())), ".")
|
||||||
|
|
||||||
|
// take only files with simple extensions
|
||||||
|
switch extension {
|
||||||
|
case "svg", "jpeg", "jpg", "gif", "png":
|
||||||
|
defaultAvatarPath := fmt.Sprintf("/assets/default_avatars/%s", f.Name())
|
||||||
|
defaultAvatars = append(defaultAvatars, defaultAvatarPath)
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Module{
|
||||||
|
processor: processor,
|
||||||
|
assetsPath: assetsPath,
|
||||||
|
adminPath: filepath.Join(assetsPath, "admin"),
|
||||||
|
defaultAvatars: defaultAvatars,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Module) baseHandler(c *gin.Context) {
|
func (m *Module) baseHandler(c *gin.Context) {
|
||||||
|
@ -88,20 +140,11 @@ func (m *Module) NotFoundHandler(c *gin.Context) {
|
||||||
// Route satisfies the RESTAPIModule interface
|
// Route satisfies the RESTAPIModule interface
|
||||||
func (m *Module) Route(s router.Router) error {
|
func (m *Module) Route(s router.Router) error {
|
||||||
// serve static files from assets dir at /assets
|
// serve static files from assets dir at /assets
|
||||||
assetBaseDir := viper.GetString(config.Keys.WebAssetBaseDir)
|
s.AttachStaticFS("/assets", fileSystem{http.Dir(m.assetsPath)})
|
||||||
if assetBaseDir == "" {
|
|
||||||
return fmt.Errorf("%s cannot be empty and must be a relative or absolute path", config.Keys.WebAssetBaseDir)
|
|
||||||
}
|
|
||||||
assetPath, err := filepath.Abs(assetBaseDir)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error getting absolute path of %s: %s", assetBaseDir, err)
|
|
||||||
}
|
|
||||||
s.AttachStaticFS("/assets", fileSystem{http.Dir(assetPath)})
|
|
||||||
|
|
||||||
// serve admin panel from within assets dir at /admin/
|
// serve admin panel from within assets dir at /admin/
|
||||||
// and redirect /admin to /admin/
|
// and redirect /admin to /admin/
|
||||||
adminPath := filepath.Join(assetPath, "admin")
|
s.AttachStaticFS("/admin/", fileSystem{http.Dir(m.adminPath)})
|
||||||
s.AttachStaticFS("/admin/", fileSystem{http.Dir(adminPath)})
|
|
||||||
s.AttachHandler(http.MethodGet, "/admin", func(c *gin.Context) {
|
s.AttachHandler(http.MethodGet, "/admin", func(c *gin.Context) {
|
||||||
c.Redirect(http.StatusMovedPermanently, "/admin/")
|
c.Redirect(http.StatusMovedPermanently, "/admin/")
|
||||||
})
|
})
|
||||||
|
@ -109,8 +152,11 @@ func (m *Module) Route(s router.Router) error {
|
||||||
// serve front-page
|
// serve front-page
|
||||||
s.AttachHandler(http.MethodGet, "/", m.baseHandler)
|
s.AttachHandler(http.MethodGet, "/", m.baseHandler)
|
||||||
|
|
||||||
|
// serve profile pages at /@username
|
||||||
|
s.AttachHandler(http.MethodGet, profilePath, m.profileTemplateHandler)
|
||||||
|
|
||||||
// serve statuses
|
// serve statuses
|
||||||
s.AttachHandler(http.MethodGet, "/:user/statuses/:id", m.threadTemplateHandler)
|
s.AttachHandler(http.MethodGet, statusPath, m.threadTemplateHandler)
|
||||||
|
|
||||||
// serve email confirmation page at /confirm_email?token=whatever
|
// serve email confirmation page at /confirm_email?token=whatever
|
||||||
s.AttachHandler(http.MethodGet, confirmEmailPath, m.confirmEmailGETHandler)
|
s.AttachHandler(http.MethodGet, confirmEmailPath, m.confirmEmailGETHandler)
|
||||||
|
|
139
internal/web/profile.go
Normal file
139
internal/web/profile.go
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
/*
|
||||||
|
GoToSocial
|
||||||
|
Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
|
||||||
|
|
||||||
|
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 web
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/ap"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/api"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (m *Module) profileTemplateHandler(c *gin.Context) {
|
||||||
|
l := logrus.WithField("func", "profileTemplateHandler")
|
||||||
|
l.Trace("rendering profile template")
|
||||||
|
ctx := c.Request.Context()
|
||||||
|
|
||||||
|
username := c.Param(usernameKey)
|
||||||
|
if username == "" {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": "no account username specified"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
authed, err := oauth.Authed(c, false, false, false, false)
|
||||||
|
if err != nil {
|
||||||
|
l.Errorf("error authing profile GET request: %s", err)
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "internal server error"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
instance, errWithCode := m.processor.InstanceGet(ctx, viper.GetString(config.Keys.Host))
|
||||||
|
if errWithCode != nil {
|
||||||
|
l.Debugf("error getting instance from processor: %s", errWithCode.Error())
|
||||||
|
c.JSON(errWithCode.Code(), gin.H{"error": errWithCode.Safe()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
account, errWithCode := m.processor.AccountGetLocalByUsername(ctx, authed, username)
|
||||||
|
if errWithCode != nil {
|
||||||
|
l.Debugf("error getting account from processor: %s", errWithCode.Error())
|
||||||
|
if errWithCode.Code() == http.StatusNotFound {
|
||||||
|
m.NotFoundHandler(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(errWithCode.Code(), gin.H{"error": errWithCode.Safe()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we're getting an AP request on this endpoint we should render the account's AP representation instead
|
||||||
|
accept := c.NegotiateFormat(string(api.TextHTML), string(api.AppActivityJSON), string(api.AppActivityLDJSON))
|
||||||
|
if accept == string(api.AppActivityJSON) || accept == string(api.AppActivityLDJSON) {
|
||||||
|
m.returnAPRepresentation(ctx, c, username, accept)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// get latest 10 top-level public statuses;
|
||||||
|
// ie., exclude replies and boosts, public only,
|
||||||
|
// with or without media
|
||||||
|
statuses, errWithCode := m.processor.AccountStatusesGet(ctx, authed, account.ID, 10, true, true, "", "", false, false, true)
|
||||||
|
if errWithCode != nil {
|
||||||
|
l.Debugf("error getting statuses from processor: %s", errWithCode.Error())
|
||||||
|
c.JSON(errWithCode.Code(), gin.H{"error": errWithCode.Safe()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// pick a random dummy avatar if this account avatar isn't set yet
|
||||||
|
if account.Avatar == "" && len(m.defaultAvatars) > 0 {
|
||||||
|
//nolint:gosec
|
||||||
|
randomIndex := rand.Intn(len(m.defaultAvatars))
|
||||||
|
dummyAvatar := m.defaultAvatars[randomIndex]
|
||||||
|
account.Avatar = dummyAvatar
|
||||||
|
for _, s := range statuses {
|
||||||
|
s.Account.Avatar = dummyAvatar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.HTML(http.StatusOK, "profile.tmpl", gin.H{
|
||||||
|
"instance": instance,
|
||||||
|
"account": account,
|
||||||
|
"statuses": statuses,
|
||||||
|
"stylesheets": []string{
|
||||||
|
"/assets/Fork-Awesome/css/fork-awesome.min.css",
|
||||||
|
"/assets/status.css",
|
||||||
|
"/assets/profile.css",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Module) returnAPRepresentation(ctx context.Context, c *gin.Context, username string, accept string) {
|
||||||
|
verifier, signed := c.Get(string(ap.ContextRequestingPublicKeyVerifier))
|
||||||
|
if signed {
|
||||||
|
ctx = context.WithValue(ctx, ap.ContextRequestingPublicKeyVerifier, verifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
signature, signed := c.Get(string(ap.ContextRequestingPublicKeySignature))
|
||||||
|
if signed {
|
||||||
|
ctx = context.WithValue(ctx, ap.ContextRequestingPublicKeySignature, signature)
|
||||||
|
}
|
||||||
|
|
||||||
|
user, errWithCode := m.processor.GetFediUser(ctx, username, c.Request.URL) // GetFediUser handles auth as well
|
||||||
|
if errWithCode != nil {
|
||||||
|
logrus.Infof(errWithCode.Error())
|
||||||
|
c.JSON(errWithCode.Code(), gin.H{"error": errWithCode.Safe()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
b, mErr := json.Marshal(user)
|
||||||
|
if mErr != nil {
|
||||||
|
err := fmt.Errorf("could not marshal json: %s", mErr)
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Data(http.StatusOK, accept, b)
|
||||||
|
}
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
@ -29,21 +30,21 @@
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
||||||
)
|
)
|
||||||
|
|
||||||
type statusLink struct {
|
|
||||||
User string `uri:"user" binding:"required"`
|
|
||||||
ID string `uri:"id" binding:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Module) threadTemplateHandler(c *gin.Context) {
|
func (m *Module) threadTemplateHandler(c *gin.Context) {
|
||||||
l := logrus.WithField("func", "threadTemplateGET")
|
l := logrus.WithField("func", "threadTemplateGET")
|
||||||
l.Trace("rendering thread template")
|
l.Trace("rendering thread template")
|
||||||
|
|
||||||
ctx := c.Request.Context()
|
ctx := c.Request.Context()
|
||||||
|
|
||||||
var uriParts statusLink
|
username := c.Param(usernameKey)
|
||||||
|
if username == "" {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": "no account username specified"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if err := c.ShouldBindUri(&uriParts); err != nil {
|
statusID := c.Param(statusIDKey)
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "status not found"})
|
if username == "" {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": "no status id specified"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,18 +63,18 @@ func (m *Module) threadTemplateHandler(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
status, err := m.processor.StatusGet(ctx, authed, uriParts.ID)
|
status, err := m.processor.StatusGet(ctx, authed, statusID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "status not found"})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "status not found"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if uriParts.User[:1] != "@" || uriParts.User[1:] != status.Account.Username {
|
if !strings.EqualFold(username, status.Account.Username) {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "status not found"})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "status not found"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
context, err := m.processor.StatusGetContext(ctx, authed, uriParts.ID)
|
context, err := m.processor.StatusGetContext(ctx, authed, statusID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "status not found"})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "status not found"})
|
||||||
return
|
return
|
||||||
|
|
|
@ -166,23 +166,24 @@ section.login form button {
|
||||||
}
|
}
|
||||||
|
|
||||||
section.error {
|
section.error {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
|
||||||
section.error span {
|
|
||||||
font-size: 2em;
|
|
||||||
}
|
|
||||||
section.error pre {
|
|
||||||
border: 1px solid #ff000080;
|
|
||||||
margin-left: 1em;
|
|
||||||
padding: 0 0.7em;
|
|
||||||
border-radius: 0.5em;
|
|
||||||
background-color: #ff000010;
|
|
||||||
font-size: 1.3em;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
section.error span {
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.error pre {
|
||||||
|
border: 1px solid #ff000080;
|
||||||
|
margin-left: 1em;
|
||||||
|
padding: 0 0.7em;
|
||||||
|
border-radius: 0.5em;
|
||||||
|
background-color: #ff000010;
|
||||||
|
font-size: 1.3em;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
input, select, textarea {
|
input, select, textarea {
|
||||||
border: 1px solid #fafaff;
|
border: 1px solid #fafaff;
|
||||||
|
|
160
web/assets/default_avatars/GoToSocial_icon1.svg
Normal file
160
web/assets/default_avatars/GoToSocial_icon1.svg
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="1000px"
|
||||||
|
height="1000px"
|
||||||
|
viewBox="0 0 1000 1000"
|
||||||
|
version="1.1"
|
||||||
|
id="SVGRoot"
|
||||||
|
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||||
|
sodipodi:docname="GoToSocial_icon1.svg"
|
||||||
|
inkscape:export-xdpi="95.999992"
|
||||||
|
inkscape:export-ydpi="95.999992">
|
||||||
|
<defs
|
||||||
|
id="defs5117">
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5760"
|
||||||
|
is_visible="true" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5756"
|
||||||
|
is_visible="true" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5752"
|
||||||
|
is_visible="true" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5748"
|
||||||
|
is_visible="true" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.70710678"
|
||||||
|
inkscape:cx="460.72691"
|
||||||
|
inkscape:cy="522.20279"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer3"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1057"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5120">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="background"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
style="display:inline">
|
||||||
|
<rect
|
||||||
|
style="fill:#d0d0d0;fill-opacity:1;stroke:none;stroke-width:1.51092136;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||||
|
id="rect5876"
|
||||||
|
width="1000.0042"
|
||||||
|
height="1000"
|
||||||
|
x="0"
|
||||||
|
y="0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer3"
|
||||||
|
inkscape:label="sloth"
|
||||||
|
style="display:inline">
|
||||||
|
<g
|
||||||
|
id="g5890"
|
||||||
|
transform="translate(-10)">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ssscccs"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5762"
|
||||||
|
d="M 861.29285,497.07031 C 861.65556,665.3247 774.21642,807.40548 511.60027,807.86794 270.63622,808.29226 154.54309,691.2756 155.19024,504.19228 155.7289,348.47535 251.17288,227.4551 422.3176,205.3802 c -35.32036,-75.85452 52.24232,-96.94648 73.77615,-32.00508 13.73451,-37.63439 108.24345,-49.1716 62.21106,24.77055 147.95052,3.75658 302.58353,111.28061 302.98804,298.92464 z"
|
||||||
|
style="display:inline;fill:#767676;fill-opacity:1;stroke:none;stroke-width:2.57058167;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5780"
|
||||||
|
d="m 809.15213,517.31679 c -4.83374,150.52526 -109.85544,235.22815 -297.81171,235.31839 -179.6675,0.0863 -290.56109,-70.98245 -298.50223,-235.31839 -4.6366,-95.95095 54.62861,-181.84442 144.83016,-194.18834 80.92123,-11.07393 99.7402,21.01802 153.67207,21.01802 59.21658,0 83.64871,-35.09608 162.84221,-21.85479 87.78391,14.67763 137.90533,103.6017 134.9695,195.02511 z"
|
||||||
|
style="display:inline;fill:#e8e8e8;fill-opacity:1;stroke:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="scssscs"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5780-9"
|
||||||
|
d="m 809.15213,517.31679 c -1.32872,41.37724 -10.22787,77.78081 -26.33906,108.8204 -46.60931,-39.48031 -99.53509,-10.7281 -171.50115,-39.43334 -44.77145,-17.85808 -51.41659,-56.56453 -51.21999,-81.3542 0.54836,-69.14384 48.17003,-93.45758 95.53601,-97.60875 55.74677,-4.88566 124.5246,36.1482 151.01547,66.79433 2.11531,14.01083 2.97167,28.36512 2.50872,42.78156 z"
|
||||||
|
style="display:inline;fill:#a1a1a1;fill-opacity:1;stroke:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<ellipse
|
||||||
|
ry="50.575684"
|
||||||
|
rx="37.800804"
|
||||||
|
cy="502.64291"
|
||||||
|
cx="646.85773"
|
||||||
|
id="path5816"
|
||||||
|
style="fill:#767676;fill-opacity:1;stroke:none;stroke-width:1.51185882;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="scssscs"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5780-9-1"
|
||||||
|
d="m 212.51463,517.3246 c 1.32872,41.37724 10.22787,77.78081 26.33906,108.8204 46.60931,-39.48031 99.57415,-10.73591 171.54021,-39.44115 44.77145,-17.85808 51.41659,-56.56453 51.21999,-81.3542 -0.54836,-69.14384 -48.20909,-93.44977 -95.57507,-97.60094 -55.74677,-4.88566 -124.5246,36.1482 -151.01547,66.79433 -2.11531,14.01083 -2.97167,28.36512 -2.50872,42.78156 z"
|
||||||
|
style="display:inline;fill:#a1a1a1;fill-opacity:1;stroke:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<ellipse
|
||||||
|
transform="scale(-1,1)"
|
||||||
|
ry="50.575684"
|
||||||
|
rx="37.800804"
|
||||||
|
cy="502.64294"
|
||||||
|
cx="-374.84808"
|
||||||
|
id="path5816-0"
|
||||||
|
style="display:inline;fill:#767676;fill-opacity:1;stroke:none;stroke-width:1.51185882;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5862"
|
||||||
|
d="m 543.96613,556.96185 c 0,11.0622 -14.51648,20.02988 -32.42347,20.02988 -17.90698,0 -32.42347,-8.96769 -32.42347,-20.02988 0,-11.0622 14.14619,-15.58638 32.05318,-15.58638 17.90698,0 32.79376,4.52417 32.79376,15.58638 z"
|
||||||
|
style="display:inline;fill:#767676;fill-opacity:1;stroke:none;stroke-width:1.60515046;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5865"
|
||||||
|
d="m 552.00195,620.36132 c 7.06643,13.89391 -19.38375,21.24024 -40.2832,21.24024 -20.89945,0 -47.71708,-7.02219 -41.50391,-21.24024 5.71775,-13.08435 20.11619,0.73243 41.01563,0.73243 20.89944,0 34.43888,-13.1835 40.77148,-0.73243 z"
|
||||||
|
style="display:inline;fill:#767676;fill-opacity:1;stroke:none;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<ellipse
|
||||||
|
transform="rotate(-6.669407)"
|
||||||
|
ry="24.882849"
|
||||||
|
rx="19.511755"
|
||||||
|
cy="560.95673"
|
||||||
|
cx="600.24731"
|
||||||
|
id="path5818"
|
||||||
|
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.53898752;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<ellipse
|
||||||
|
transform="rotate(-6.6694071)"
|
||||||
|
ry="24.882849"
|
||||||
|
rx="19.511755"
|
||||||
|
cy="529.32086"
|
||||||
|
cx="329.69714"
|
||||||
|
id="path5818-8"
|
||||||
|
style="display:inline;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.53898752;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 7.9 KiB |
137
web/assets/default_avatars/GoToSocial_icon2.svg
Normal file
137
web/assets/default_avatars/GoToSocial_icon2.svg
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="1000px"
|
||||||
|
height="1000px"
|
||||||
|
viewBox="0 0 1000 1000"
|
||||||
|
version="1.1"
|
||||||
|
id="SVGRoot"
|
||||||
|
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||||
|
sodipodi:docname="GoToSocial_icon2.svg"
|
||||||
|
inkscape:export-xdpi="95.999992"
|
||||||
|
inkscape:export-ydpi="95.999992">
|
||||||
|
<defs
|
||||||
|
id="defs5117">
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5760"
|
||||||
|
is_visible="true" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5756"
|
||||||
|
is_visible="true" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5752"
|
||||||
|
is_visible="true" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5748"
|
||||||
|
is_visible="true" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.35355339"
|
||||||
|
inkscape:cx="497.76221"
|
||||||
|
inkscape:cy="575.69254"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer3"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1057"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5120">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="background"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
style="display:inline">
|
||||||
|
<rect
|
||||||
|
style="fill:#d0d0d0;fill-opacity:1;stroke:none;stroke-width:1.51092136;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||||
|
id="rect5876"
|
||||||
|
width="1000.0042"
|
||||||
|
height="1000"
|
||||||
|
x="0"
|
||||||
|
y="0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer3"
|
||||||
|
inkscape:label="sloth"
|
||||||
|
style="display:inline">
|
||||||
|
<g
|
||||||
|
id="g3978">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sccccccccccscssscsccs"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="rect5876-5"
|
||||||
|
d="M 230.01724,321.98276 C 349.98851,210.42521 448.21823,215.25781 531.04596,212.10691 c -43.53882,-55.72028 69.90321,-110.15948 114.22539,-8.84147 88.6448,-15.41997 77.60551,48.58211 55.52314,59.56776 116.1765,70.90805 150.01289,158.27624 164.97213,224.4903 78.29027,48.93425 33.19569,98.38368 21.79073,93.92084 57.78384,113.21004 8.74508,163.48051 -19.17636,145.16042 C 847.88417,891.22533 777.25,1000 777.25,1000 H 0 V 335 c -0.79197362,-2.0633 86.752294,193.09344 193.48008,463.67555 8.22828,-21.75326 15.34189,-32.85227 29.8481,-31.82047 12.36034,0.87917 27.76558,15.1443 13.3047,74.3212 0.95528,-0.34561 22.71708,-7.34064 29.09712,1.6646 12.30907,17.37387 -7.57175,23.95646 -1.82859,33.94605 6.04771,10.51933 23.2419,-4.11346 24.38025,-22.42448 0.95349,-15.33743 -7.68068,-33.34588 -31.29939,-31.7437 8.19555,-53.54698 -12.66475,-64.63281 -12.97883,-65.12097 -4.1124,-6.39167 -26.81347,-22.42708 -49.42662,1.72757 -15.70939,-47.21646 -51.98321,-128.67679 -77.05729,-192.68773 31.46671,-57.43102 24.70494,-162.9191 112.49771,-244.55486 z"
|
||||||
|
style="display:inline;fill:#777777;fill-opacity:1;stroke:none;stroke-width:1.51092136;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5899"
|
||||||
|
d="m 804.83231,554.45837 c 0,140.99987 -133.69246,255.30285 -298.61048,255.30285 -164.91801,0 -298.61047,-114.30298 -298.61047,-255.30285 0,-100.64813 59.92313,-198.68967 160.73026,-206.70182 60.18634,-4.78361 90.68629,22.30425 137.88021,22.81676 46.04207,0.5 70.12813,-25.6781 135.69855,-22.78348 115.9463,5.11848 162.91193,120.63643 162.91193,206.66854 z"
|
||||||
|
style="display:inline;fill:#e8e8e8;fill-opacity:1;stroke:none;stroke-width:1.63446391;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
style="display:inline;fill:#a1a1a1;fill-opacity:1;stroke:none;stroke-width:1.63446391;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||||
|
d="m 804.83231,554.45837 c 0,13.4968 -1.22499,26.74899 -3.58509,39.67972 -71.95206,24.77201 -204.63976,33.96213 -235.31322,-11.60451 -31.67182,-47.04972 13.47247,-156.40488 88.33815,-154.51226 68.45478,1.73055 101.55237,13.1539 132.47817,31.57199 12.36622,31.25081 18.08199,64.85216 18.08199,94.86506 z"
|
||||||
|
id="path5937"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="scsscs" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="scsscs"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5953"
|
||||||
|
d="m 207.65971,554.45837 c 0,13.4968 1.22499,26.74899 3.58509,39.67972 71.95206,24.77201 204.63976,33.96213 235.31322,-11.60451 31.67182,-47.04972 -13.47247,-156.40488 -88.33815,-154.51226 -68.45478,1.73055 -101.55237,13.1539 -132.47817,31.57199 -12.36622,31.25081 -18.08199,64.85216 -18.08199,94.86506 z"
|
||||||
|
style="display:inline;fill:#a1a1a1;fill-opacity:1;stroke:none;stroke-width:1.63446391;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5955"
|
||||||
|
d="m 540.5,587.08433 c 0,11.71361 -14.7746,21.20938 -33,21.20938 -18.2254,0 -33,-9.49577 -33,-21.20938 0,-11.71362 14.0675,-13.51846 32.29289,-13.51846 18.2254,0 33.70711,1.80484 33.70711,13.51846 z"
|
||||||
|
style="fill:#777777;fill-opacity:1;stroke:none;stroke-width:0.34833181;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<ellipse
|
||||||
|
ry="44.492474"
|
||||||
|
rx="35.992474"
|
||||||
|
cy="533"
|
||||||
|
cx="641.5"
|
||||||
|
id="path5939"
|
||||||
|
style="display:inline;fill:#777777;fill-opacity:1;stroke:none;stroke-width:0.34905314;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<ellipse
|
||||||
|
transform="scale(-1,1)"
|
||||||
|
style="display:inline;fill:#777777;fill-opacity:1;stroke:none;stroke-width:0.34905314;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||||
|
id="ellipse5951"
|
||||||
|
cx="-370.992"
|
||||||
|
cy="533"
|
||||||
|
rx="35.992474"
|
||||||
|
ry="44.492474" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 7.1 KiB |
137
web/assets/default_avatars/GoToSocial_icon3.svg
Normal file
137
web/assets/default_avatars/GoToSocial_icon3.svg
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="1000px"
|
||||||
|
height="1000px"
|
||||||
|
viewBox="0 0 1000 1000"
|
||||||
|
version="1.1"
|
||||||
|
id="SVGRoot"
|
||||||
|
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||||
|
sodipodi:docname="GoToSocial_icon3.svg"
|
||||||
|
inkscape:export-xdpi="96"
|
||||||
|
inkscape:export-ydpi="96">
|
||||||
|
<defs
|
||||||
|
id="defs5117">
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5760"
|
||||||
|
is_visible="true" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5756"
|
||||||
|
is_visible="true" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5752"
|
||||||
|
is_visible="true" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5748"
|
||||||
|
is_visible="true" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.5"
|
||||||
|
inkscape:cx="332.72586"
|
||||||
|
inkscape:cy="487.44283"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer3"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1057"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5120">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="background"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
style="display:inline">
|
||||||
|
<rect
|
||||||
|
style="fill:#dbe1ed;fill-opacity:1;stroke:none;stroke-width:1.51092136;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||||
|
id="rect5876"
|
||||||
|
width="1000.0042"
|
||||||
|
height="1000"
|
||||||
|
x="0"
|
||||||
|
y="0" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer3"
|
||||||
|
inkscape:label="sloth"
|
||||||
|
style="display:inline">
|
||||||
|
<g
|
||||||
|
id="g3968">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sccccccccccscssscsccs"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="rect5876-5"
|
||||||
|
d="M 230.01724,321.98276 C 349.98851,210.42521 448.21823,215.25781 531.04596,212.10691 c -43.53882,-55.72028 69.90321,-110.15948 114.22539,-8.84147 88.6448,-15.41997 77.60551,48.58211 55.52314,59.56776 116.1765,70.90805 150.01289,158.27624 164.97213,224.4903 78.29027,48.93425 33.19569,98.38368 21.79073,93.92084 57.78384,113.21004 8.74508,163.48051 -19.17636,145.16042 C 847.88417,891.22533 777.25,1000 777.25,1000 H 0 V 335 c -0.79197362,-2.0633 86.752294,193.09344 193.48008,463.67555 8.22828,-21.75326 15.34189,-32.85227 29.8481,-31.82047 12.36034,0.87917 27.76558,15.1443 13.3047,74.3212 0.95528,-0.34561 22.71708,-7.34064 29.09712,1.6646 12.30907,17.37387 -7.57175,23.95646 -1.82859,33.94605 6.04771,10.51933 23.2419,-4.11346 24.38025,-22.42448 0.95349,-15.33743 -7.68068,-33.34588 -31.29939,-31.7437 8.19555,-53.54698 -12.66475,-64.63281 -12.97883,-65.12097 -4.1124,-6.39167 -26.81347,-22.42708 -49.42662,1.72757 -15.70939,-47.21646 -51.98321,-128.67679 -77.05729,-192.68773 31.46671,-57.43102 24.70494,-162.9191 112.49771,-244.55486 z"
|
||||||
|
style="display:inline;fill:#8a9bab;fill-opacity:1;stroke:none;stroke-width:1.51092136;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5899"
|
||||||
|
d="m 804.83231,554.45837 c 0,140.99987 -133.69246,255.30285 -298.61048,255.30285 -164.91801,0 -298.61047,-114.30298 -298.61047,-255.30285 0,-100.64813 59.92313,-198.68967 160.73026,-206.70182 60.18634,-4.78361 90.68629,22.30425 137.88021,22.81676 46.04207,0.5 70.12813,-25.6781 135.69855,-22.78348 115.9463,5.11848 162.91193,120.63643 162.91193,206.66854 z"
|
||||||
|
style="display:inline;fill:#ecf1f5;fill-opacity:1;stroke:none;stroke-width:1.63446391;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
style="display:inline;fill:#b5becf;fill-opacity:1;stroke:none;stroke-width:1.63446391;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||||
|
d="m 804.83231,554.45837 c 0,13.4968 -1.22499,26.74899 -3.58509,39.67972 -71.95206,24.77201 -204.63976,33.96213 -235.31322,-11.60451 -31.67182,-47.04972 13.47247,-156.40488 88.33815,-154.51226 68.45478,1.73055 101.55237,13.1539 132.47817,31.57199 12.36622,31.25081 18.08199,64.85216 18.08199,94.86506 z"
|
||||||
|
id="path5937"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="scsscs" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="scsscs"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5953"
|
||||||
|
d="m 207.65971,554.45837 c 0,13.4968 1.22499,26.74899 3.58509,39.67972 71.95206,24.77201 204.63976,33.96213 235.31322,-11.60451 31.67182,-47.04972 -13.47247,-156.40488 -88.33815,-154.51226 -68.45478,1.73055 -101.55237,13.1539 -132.47817,31.57199 -12.36622,31.25081 -18.08199,64.85216 -18.08199,94.86506 z"
|
||||||
|
style="display:inline;fill:#b5becf;fill-opacity:1;stroke:none;stroke-width:1.63446391;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5955"
|
||||||
|
d="m 540.5,587.08433 c 0,11.71361 -14.7746,21.20938 -33,21.20938 -18.2254,0 -33,-9.49577 -33,-21.20938 0,-11.71362 14.0675,-13.51846 32.29289,-13.51846 18.2254,0 33.70711,1.80484 33.70711,13.51846 z"
|
||||||
|
style="fill:#7a7d82;fill-opacity:1;stroke:none;stroke-width:0.34833181;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<ellipse
|
||||||
|
ry="44.492474"
|
||||||
|
rx="35.992474"
|
||||||
|
cy="533"
|
||||||
|
cx="641.5"
|
||||||
|
id="path5939"
|
||||||
|
style="display:inline;fill:#7a7d82;fill-opacity:1;stroke:none;stroke-width:0.34905314;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<ellipse
|
||||||
|
transform="scale(-1,1)"
|
||||||
|
style="display:inline;fill:#7a7d82;fill-opacity:1;stroke:none;stroke-width:0.34905314;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||||
|
id="ellipse5951"
|
||||||
|
cx="-370.992"
|
||||||
|
cy="533"
|
||||||
|
rx="35.992474"
|
||||||
|
ry="44.492474" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 7.1 KiB |
152
web/assets/default_avatars/GoToSocial_icon4.svg
Normal file
152
web/assets/default_avatars/GoToSocial_icon4.svg
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="1000px"
|
||||||
|
height="1000px"
|
||||||
|
viewBox="0 0 1000 1000"
|
||||||
|
version="1.1"
|
||||||
|
id="SVGRoot"
|
||||||
|
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||||
|
sodipodi:docname="GoToSocial_icon4.svg"
|
||||||
|
inkscape:export-xdpi="96"
|
||||||
|
inkscape:export-ydpi="96">
|
||||||
|
<defs
|
||||||
|
id="defs5117">
|
||||||
|
<inkscape:path-effect
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect6023"
|
||||||
|
effect="spiro" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect6019"
|
||||||
|
is_visible="true" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5760"
|
||||||
|
is_visible="true" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5756"
|
||||||
|
is_visible="true" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5752"
|
||||||
|
is_visible="true" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5748"
|
||||||
|
is_visible="true" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.5"
|
||||||
|
inkscape:cx="-238.86957"
|
||||||
|
inkscape:cy="384.20002"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1057"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5120">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="background"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
style="display:inline">
|
||||||
|
<rect
|
||||||
|
style="fill:#e3ccbe;fill-opacity:1;stroke:none;stroke-width:1.95512283;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||||
|
id="rect6025"
|
||||||
|
width="1000"
|
||||||
|
height="1000"
|
||||||
|
x="-1000"
|
||||||
|
y="-1000"
|
||||||
|
transform="scale(-1)" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer3"
|
||||||
|
inkscape:label="sloth"
|
||||||
|
style="display:inline">
|
||||||
|
<g
|
||||||
|
id="g3958">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccssccccscccscscccccccc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="rect5876"
|
||||||
|
d="m 250.42136,685.9676 c 27.70546,-52.03568 68.96026,3.65306 45.50576,51.34931 31.74726,11.3972 32.63935,48.28596 10.44891,60.73784 -5.04807,2.83267 -8.35938,4.85246 -6.24616,9.92615 6.82828,16.39412 69.24558,-37.84791 12.03356,-75.57698 17.99005,-83.53997 -44.99856,-94.84265 -61.49124,-71.10901 C 197.50575,583.4007 147.54378,487.681 131.62217,450.28384 c 0.12558,-13.14689 10.55647,-15.91833 16.57496,-17.76346 -52.047785,-29.70807 -27.82707,-79.31533 17.95281,-96.29615 46.52036,-17.25548 75.09848,-100.71517 158.45465,-139.02174 -41.91643,-28.95924 12.41179,-76.2933 69.63812,-60.09295 49.56384,-86.701637 128.76235,-51.997593 106.48829,-6.82033 160.08649,-21.81784 193.18485,37.08464 252.21617,29.88994 126.67808,-15.43944 115.11456,62.82898 97.64128,88.84198 21.70268,16.70276 30.36519,23.60378 61.89934,36.01667 40.08455,15.77862 59.1052,72.49434 0.74775,112.50038 40.62846,38.95859 78.93877,96.58176 32.79494,114.2793 51.96757,64.16898 32.13903,145.87433 -6.38744,145.34448 8.59645,23.3003 -5.32539,71.52714 -35.88758,62.06313 C 884.05327,852.44822 817.94577,1000 817.94577,1000 H 0 V 142.98659 c 0,0 89.549546,320.73624 250.42136,542.98101 z"
|
||||||
|
style="display:inline;fill:#c89172;fill-opacity:1;stroke:none;stroke-width:1.51092136;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5899"
|
||||||
|
d="m 839.83231,465.22371 c 0,130.63606 -133.69246,236.53751 -298.61048,236.53751 -164.91801,0 -298.61047,-105.90145 -298.61047,-236.53751 0,-93.25027 59.92313,-184.08554 160.73026,-191.50878 60.18634,-4.432 90.68629,20.66484 137.88021,21.13968 46.04207,0.46325 70.12813,-23.7907 135.69855,-21.10884 115.9463,4.74226 162.91193,111.76938 162.91193,191.47794 z"
|
||||||
|
style="display:inline;fill:#f6e7e0;fill-opacity:0.98113209;stroke:none;stroke-width:1.57324922;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
style="display:inline;fill:#e3ccbe;fill-opacity:1;stroke:none;stroke-width:1.57324922;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||||
|
d="m 839.83231,465.22371 c 0,19.38025 -2.94239,38.21613 -8.4926,56.24262 -85.83868,33.0678 -208.68682,26.13484 -229.51106,-25.32493 -26.07758,-64.44157 31.43036,-103.22868 75.8166,-116.93012 51.17758,-15.79784 106.51724,0.003 150.63827,15.41887 7.86068,23.77511 11.54879,48.25697 11.54879,70.59356 z"
|
||||||
|
id="path6003"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="scsscs" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path6005"
|
||||||
|
d="m 636.34279,468.2557 c -0.9957,7.73624 0.22345,23.8871 13.0952,23.55507 15.73663,-0.40594 8.01751,-24.25641 28.62411,-24.0854 20.42062,0.16948 12.59412,24.3415 27.18325,24.95261 15.02273,0.62928 16.26485,-17.17918 14.71283,-25.30616 -4.39441,-23.01076 -22.45132,-32.32534 -42.07286,-32.70368 -21.39109,-0.41246 -38.86298,12.76845 -41.54253,33.58756 z"
|
||||||
|
style="fill:#c89172;fill-opacity:1;stroke:none;stroke-width:0.33399999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="scsscs"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path6008"
|
||||||
|
d="m 242.46966,465.22371 c 0,19.38025 2.94239,38.21613 8.4926,56.24262 85.83868,33.0678 208.68682,26.13484 229.51106,-25.32493 26.07758,-64.44157 -31.43036,-103.22868 -75.8166,-116.93012 -51.17758,-15.79784 -106.20788,0.1024 -150.32891,15.51831 -8.25843,23.68672 -11.85815,48.15753 -11.85815,70.49412 z"
|
||||||
|
style="display:inline;fill:#e3ccbe;fill-opacity:1;stroke:none;stroke-width:1.57324922;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
style="fill:#c89172;fill-opacity:1;stroke:none;stroke-width:0.33399999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||||
|
d="m 445.95918,468.2557 c 0.9957,7.73624 -0.22345,23.8871 -13.0952,23.55507 -15.73663,-0.40594 -8.01751,-24.25641 -28.62411,-24.0854 -20.42062,0.16948 -12.59412,24.3415 -27.18325,24.95261 -15.02273,0.62928 -16.26485,-17.17918 -14.71283,-25.30616 4.39441,-23.01076 22.45132,-32.32534 42.07286,-32.70368 21.39109,-0.41246 38.86298,12.76845 41.54253,33.58756 z"
|
||||||
|
id="path6010"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="sssssss" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path6014"
|
||||||
|
d="m 572.40294,496.00963 c 0,10.44653 -14.00878,18.91511 -31.28948,18.91511 -17.2807,0 -31.28947,-8.46858 -31.28947,-18.91511 1e-5,-10.44652 13.65522,-13.96535 30.93592,-13.96535 17.28069,0 31.64302,3.51883 31.64303,13.96535 z"
|
||||||
|
style="fill:#c89172;fill-opacity:1;stroke:none;stroke-width:0.33399999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
transform="matrix(-1,0,0,1,1088.0012,0)"
|
||||||
|
sodipodi:nodetypes="sssscsssscs"
|
||||||
|
inkscape:original-d="m 561.38128,582.67417 c 4.16766,-0.91767 12.20351,2.22573 11.70451,-3.19194 -0.49904,-5.41767 3.22694,-10.0569 -0.43934,-12.36091 -3.71867,-2.33693 -4.66037,-0.70889 -10.62868,-3.03033 -6.7415,-2.62217 -12.89085,-5.33173 -18.0383,-9.27773 -5.14745,3.946 -11.25574,6.65556 -17.99724,9.27773 -5.96831,2.32144 -6.91001,0.6934 -10.62868,3.03033 -3.66628,2.30401 0.0597,6.94324 -0.43934,12.36091 -0.499,5.41767 7.53685,2.27427 11.70451,3.19194 4.16767,0.91767 12.6047,-2.8973 17.27236,-5.97963 4.66766,3.08233 13.32253,6.8973 17.4902,5.97963 z"
|
||||||
|
inkscape:path-effect="#path-effect6019"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path6017"
|
||||||
|
d="m 561.38128,582.67417 c 2.08275,0.16617 4.19863,0.15523 6.23646,-0.30597 2.03783,-0.46119 4.00308,-1.39624 5.46805,-2.88597 1.62507,-1.65254 2.56385,-3.97206 2.49743,-6.2888 -0.0664,-2.31675 -1.15042,-4.59539 -2.93677,-6.07211 -1.43969,-1.19015 -3.25655,-1.83786 -5.08522,-2.21886 -1.82866,-0.38101 -3.69889,-0.51693 -5.54346,-0.81147 -6.78982,-1.08418 -13.20738,-4.38495 -18.0383,-9.27773 -4.81493,4.89182 -11.2195,8.19343 -17.99724,9.27773 -1.84447,0.29508 -3.7147,0.43095 -5.54339,0.8118 -1.82869,0.38084 -3.64567,1.02831 -5.08529,2.21853 -1.78611,1.47668 -2.86946,3.75542 -2.93562,6.07196 -0.0662,2.31655 0.87229,4.63564 2.49628,6.28895 1.46438,1.49081 3.42913,2.42785 5.46715,2.88979 2.03802,0.46195 4.15458,0.4723 6.23736,0.30215 6.13711,-0.50136 12.1389,-2.57916 17.27236,-5.97963 5.21036,3.40799 11.28399,5.48447 17.4902,5.97963 z"
|
||||||
|
style="fill:#c89172;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 9.8 KiB |
152
web/assets/default_avatars/GoToSocial_icon5.svg
Normal file
152
web/assets/default_avatars/GoToSocial_icon5.svg
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="1000px"
|
||||||
|
height="1000px"
|
||||||
|
viewBox="0 0 1000 1000"
|
||||||
|
version="1.1"
|
||||||
|
id="SVGRoot"
|
||||||
|
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||||
|
sodipodi:docname="GoToSocial_icon5.svg"
|
||||||
|
inkscape:export-xdpi="96"
|
||||||
|
inkscape:export-ydpi="96">
|
||||||
|
<defs
|
||||||
|
id="defs5117">
|
||||||
|
<inkscape:path-effect
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect6023"
|
||||||
|
effect="spiro" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect6019"
|
||||||
|
is_visible="true" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5760"
|
||||||
|
is_visible="true" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5756"
|
||||||
|
is_visible="true" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5752"
|
||||||
|
is_visible="true" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5748"
|
||||||
|
is_visible="true" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.5"
|
||||||
|
inkscape:cx="429.92366"
|
||||||
|
inkscape:cy="322.81254"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1057"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5120">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="background"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
style="display:inline">
|
||||||
|
<rect
|
||||||
|
style="fill:#dbe1ed;fill-opacity:1;stroke:none;stroke-width:1.95512283;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||||
|
id="rect6025"
|
||||||
|
width="1000"
|
||||||
|
height="1000"
|
||||||
|
x="0"
|
||||||
|
y="-1000"
|
||||||
|
transform="scale(1,-1)" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer3"
|
||||||
|
inkscape:label="sloth"
|
||||||
|
style="display:inline">
|
||||||
|
<g
|
||||||
|
id="g3356">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cccsssssscscccccccssscc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="rect5876"
|
||||||
|
d="m 874.87783,542.28384 c -26.11086,-42.88953 -41.80521,-83.16959 -54.18766,-152.89697 26.06687,-16.2006 24.83566,-45.46406 -15.39052,-66.46433 33.93989,-31.34323 19.98697,-65.52994 -14.72432,-74.60734 -17.82314,-4.66096 -47.16558,-7.88098 -57.36123,-10.85855 C 682.77372,222.7259 665.18888,198.90619 620.74191,184.15446 466.35494,132.9142 270.81297,170.61723 187.49013,275.95719 c -75.42408,95.35405 -76.23332,151.45419 -93.03896,234.27568 -3.607596,17.77894 -13.074363,43.57065 -18.984879,48.69769 -15.458276,13.40918 -34.278507,59.92672 20.246637,58.01857 -4.911621,26.63049 -16.202612,42.03875 -21.825893,56.4483 -17.846537,45.7314 11.791821,64.75835 49.726775,55.12543 -3.31228,29.06008 -3.80965,68.00974 41.7245,59.75469 -0.009,19.23781 7.68254,28.70603 16.36237,33.35477 C 190.37816,933.25823 216.37467,1000 216.37467,1000 H 1000 V 437.85011 c 0,0 -223.38954,219.6287 -348,370.63648 -12.36429,-39.94931 -41.10548,-27.13457 -47.02031,2.51737 -0.45414,2.27666 -3.24992,9.15209 -9.86438,8.83489 -5.83023,-0.2796 -6.27407,-11.31136 -2.97641,-22.14792 6.46074,-21.2309 39.80291,-48.85947 63.84617,-17.09603 45.93757,-54.017 128.43819,-141.91623 218.89276,-238.31106 z"
|
||||||
|
style="display:inline;fill:#8a9bab;fill-opacity:1;stroke:none;stroke-width:1.51092136;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5899"
|
||||||
|
d="m 164.41033,501.28694 c 0,134.96586 89.28037,248.33231 309.21473,247.20575 217.71706,-1.11521 307.80052,-112.23989 307.80052,-247.20575 0,-96.34096 -54.83816,-188.77266 -158.98644,-196.44194 -62.18116,-4.57889 -100.76307,28.42083 -149.52119,28.91141 -47.56808,0.4786 -79.52352,-31.65029 -147.26721,-28.87954 -119.78922,4.89943 -161.24041,114.05966 -161.24041,196.41007 z"
|
||||||
|
style="display:inline;fill:#ecf1f5;fill-opacity:1;stroke:none;stroke-width:1.62539303;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cscsssc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path6029"
|
||||||
|
d="m 167.12764,541.06247 c -1.8472,-12.95996 -2.88472,-26.24998 -2.88472,-39.77553 0,-22.09219 2.88362,-43.97881 8.58421,-64.68492 40.44162,-29.67651 108.08468,-52.00242 167.32555,-41.22117 35.02394,6.37401 90.30164,43.89694 76.99739,113.45676 -7.83112,40.94415 -61.06671,49.31438 -94.96833,50.10049 -38.95967,0.9034 -90.29699,-2.69765 -155.0541,-17.87563 z"
|
||||||
|
style="display:inline;fill:#abb7c5;fill-opacity:1;stroke:none;stroke-width:1.62539303;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path6005"
|
||||||
|
d="m 384.49599,483.06729 c 1.26483,9.82737 -0.28385,30.34383 -16.63487,29.92206 -19.99028,-0.51567 -10.18467,-30.81298 -36.36126,-30.59574 -25.94038,0.21528 -15.99836,30.92106 -34.53097,31.69735 -19.08341,0.79938 -20.66128,-21.82275 -18.68974,-32.14647 5.58223,-29.23062 28.51996,-41.06296 53.44527,-41.54356 27.17314,-0.52397 49.36773,16.21978 52.77157,42.66636 z"
|
||||||
|
style="fill:#797c81;fill-opacity:1;stroke:none;stroke-width:0.424281;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
style="display:inline;fill:#abb7c5;fill-opacity:1;stroke:none;stroke-width:1.62539303;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||||
|
d="m 778.67367,541.05856 c 1.8472,-12.95996 2.75191,-26.24607 2.75191,-39.77162 0,-22.09219 -2.88362,-43.97881 -8.58421,-64.68492 -40.44162,-29.67651 -108.08468,-52.00242 -167.32555,-41.22117 -35.02394,6.37401 -90.30164,43.89694 -76.99739,113.45676 7.83112,40.94415 61.06671,49.31438 94.96833,50.10049 38.95967,0.9034 90.4298,-2.70156 155.18691,-17.87954 z"
|
||||||
|
id="path6027"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cscsssc" />
|
||||||
|
<path
|
||||||
|
style="fill:#797c81;fill-opacity:1;stroke:none;stroke-width:0.424281;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||||
|
d="m 559.16559,483.06729 c -1.26484,9.82737 0.28385,30.34383 16.63486,29.92206 19.99028,-0.51567 10.18468,-30.81298 36.36127,-30.59574 25.94037,0.21528 15.99835,30.92106 34.53096,31.69735 19.08341,0.79938 20.66127,-21.82275 18.68974,-32.14647 -5.58223,-29.23062 -28.51996,-41.06296 -53.44525,-41.54356 -27.17316,-0.52397 -49.36774,16.21978 -52.77158,42.66636 z"
|
||||||
|
id="path6010"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="sssssss" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path6014"
|
||||||
|
d="m 439.99627,540.8714 c 0,10.79277 14.47309,19.54203 32.32654,19.54203 17.85345,0 32.32653,-8.74926 32.32653,-19.54203 -10e-6,-10.79276 -14.10781,-14.42822 -31.96127,-14.42822 -17.85343,0 -32.69179,3.63546 -32.6918,14.42822 z"
|
||||||
|
style="fill:#7a7d82;fill-opacity:1;stroke:none;stroke-width:0.34507009;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
transform="matrix(1.3299533,0,0,1.0420847,-252.3233,16.933424)"
|
||||||
|
sodipodi:nodetypes="sssscsssscs"
|
||||||
|
inkscape:original-d="m 561.38128,582.67417 c 4.16766,-0.91767 12.20351,2.22573 11.70451,-3.19194 -0.49904,-5.41767 3.22694,-10.0569 -0.43934,-12.36091 -3.71867,-2.33693 -4.66037,-0.70889 -10.62868,-3.03033 -6.7415,-2.62217 -12.89085,-5.33173 -18.0383,-9.27773 -5.14745,3.946 -11.25574,6.65556 -17.99724,9.27773 -5.96831,2.32144 -6.91001,0.6934 -10.62868,3.03033 -3.66628,2.30401 0.0597,6.94324 -0.43934,12.36091 -0.499,5.41767 7.53685,2.27427 11.70451,3.19194 4.16767,0.91767 12.6047,-2.8973 17.27236,-5.97963 4.66766,3.08233 13.32253,6.8973 17.4902,5.97963 z"
|
||||||
|
inkscape:path-effect="#path-effect6019"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path6017"
|
||||||
|
d="m 561.38128,582.67417 c 2.08275,0.16617 4.19863,0.15523 6.23646,-0.30597 2.03783,-0.46119 4.00308,-1.39624 5.46805,-2.88597 1.62507,-1.65254 2.56385,-3.97206 2.49743,-6.2888 -0.0664,-2.31675 -1.15042,-4.59539 -2.93677,-6.07211 -1.43969,-1.19015 -3.25655,-1.83786 -5.08522,-2.21886 -1.82866,-0.38101 -3.69889,-0.51693 -5.54346,-0.81147 -6.78982,-1.08418 -13.20738,-4.38495 -18.0383,-9.27773 -4.81493,4.89182 -11.2195,8.19343 -17.99724,9.27773 -1.84447,0.29508 -3.7147,0.43095 -5.54339,0.8118 -1.82869,0.38084 -3.64567,1.02831 -5.08529,2.21853 -1.78611,1.47668 -2.86946,3.75542 -2.93562,6.07196 -0.0662,2.31655 0.87229,4.63564 2.49628,6.28895 1.46438,1.49081 3.42913,2.42785 5.46715,2.88979 2.03802,0.46195 4.15458,0.4723 6.23736,0.30215 6.13711,-0.50136 12.1389,-2.57916 17.27236,-5.97963 5.21036,3.40799 11.28399,5.48447 17.4902,5.97963 z"
|
||||||
|
style="fill:#7a7d82;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 10 KiB |
160
web/assets/default_avatars/GoToSocial_icon6.svg
Normal file
160
web/assets/default_avatars/GoToSocial_icon6.svg
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="1000px"
|
||||||
|
height="1000px"
|
||||||
|
viewBox="0 0 1000 1000"
|
||||||
|
version="1.1"
|
||||||
|
id="SVGRoot"
|
||||||
|
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||||
|
sodipodi:docname="GoToSocial_icon6.svg"
|
||||||
|
inkscape:export-xdpi="96"
|
||||||
|
inkscape:export-ydpi="96">
|
||||||
|
<defs
|
||||||
|
id="defs5117">
|
||||||
|
<inkscape:path-effect
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect6113"
|
||||||
|
effect="spiro" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect6099"
|
||||||
|
is_visible="true" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
is_visible="true"
|
||||||
|
id="path-effect6023"
|
||||||
|
effect="spiro" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect6019"
|
||||||
|
is_visible="true" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5760"
|
||||||
|
is_visible="true" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5756"
|
||||||
|
is_visible="true" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5752"
|
||||||
|
is_visible="true" />
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect5748"
|
||||||
|
is_visible="true" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.35355339"
|
||||||
|
inkscape:cx="-343.35188"
|
||||||
|
inkscape:cy="451.98165"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1057"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5120">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="background"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
style="display:inline">
|
||||||
|
<rect
|
||||||
|
style="fill:#e3ccbe;fill-opacity:1;stroke:none;stroke-width:1.95512283;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||||
|
id="rect6025"
|
||||||
|
width="1000"
|
||||||
|
height="1000"
|
||||||
|
x="0"
|
||||||
|
y="-1000"
|
||||||
|
transform="scale(1,-1)" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer3"
|
||||||
|
inkscape:label="sloth"
|
||||||
|
style="display:inline">
|
||||||
|
<g
|
||||||
|
id="g3345">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssccsccssscccs"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path6057"
|
||||||
|
d="m 858.9826,509 c 0,21.30135 0.61819,51.5972 6.701,73.24153 7.01258,24.95272 16.3214,50.02921 6.75447,64.21164 -8.7497,12.97093 -21.25315,18.56008 -44.58836,14.66624 3.93369,101.42215 -77.47601,125.19748 -96.07496,88.79767 C 674.80251,788.46301 600.2861,811.26681 511.5,810.9826 c -93.0785,-0.29795 -169.41132,-24.34907 -226.58487,-64.56 -18.96636,55.61282 -89.53019,15.93142 -94.48786,-66.57373 -18.83753,13.90334 -40.21111,9.34959 -48.24161,-1.87396 -9.87886,-13.80685 -0.11866,-44.10059 6.46153,-66.65226 C 158.90467,576.16815 164.0174,526.56854 164.0174,509 c 0,-144.1474 114.89352,-263.91342 269.97979,-293.76458 -11.39947,-30.68702 33.19193,-42.65736 68.23504,-27.65736 51.70913,-51.5 126.88111,-8.44549 91.59407,29.31477 C 745.54432,249.30521 858.9826,367.38679 858.9826,509 Z"
|
||||||
|
style="display:inline;fill:#c89172;fill-opacity:1;stroke:none;stroke-width:1.56877995;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path5899"
|
||||||
|
d="m 221.40138,525.50517 c 0,127.7494 118.50857,234.80637 292.6814,233.98797 167.18781,-0.78557 291.3428,-106.23857 291.3428,-233.98797 0,-91.18972 -51.90603,-178.67921 -150.48563,-185.93843 -58.85641,-4.33406 -95.37539,26.90121 -141.52648,27.36556 -45.02467,0.45301 -75.27149,-29.95799 -139.39301,-27.33539 -113.38424,4.63746 -152.61908,107.96103 -152.61908,185.90826 z"
|
||||||
|
style="display:inline;fill:#f6e7e0;fill-opacity:0.99460916;stroke:none;stroke-width:1.53848529;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
style="display:inline;fill:#e3ccbe;fill-opacity:1;stroke:none;stroke-width:1.53848529;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||||
|
d="m 789.95211,601.79814 c 10.07014,-23.96206 15.47347,-49.64233 15.47347,-76.29297 0,-24.59922 -3.77719,-48.92918 -11.22886,-71.48757 -113.05163,-72.24038 -211.71014,-23.66044 -216.29587,55.37861 -0.92941,43.30708 14.85596,73.14738 66.59091,84.14256 40.60772,8.63033 109.03729,1.65487 145.46035,8.25937 z"
|
||||||
|
id="path6060"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="csccsc" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="sssss"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path6014"
|
||||||
|
d="m 489.46176,567.69891 c 0,9.26255 12.42107,16.77133 27.74324,16.77133 15.32216,0 27.74323,-7.50878 27.74323,-16.77133 -10e-6,-9.26255 -12.10759,-12.38257 -27.42976,-12.38257 -15.32215,0 -28.0567,3.12002 -28.05671,12.38257 z"
|
||||||
|
style="fill:#c89172;fill-opacity:1;stroke:none;stroke-width:0.29614559;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="aasaasa"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path6062"
|
||||||
|
d="m 708.01455,512.02942 c 3.98124,8.47407 4.66411,23.87376 -3.82321,27.82668 -15.14244,7.05251 -13.43948,-27.87381 -42.39106,-26.726 -27.91154,1.10657 -23.83539,31.91957 -38.41145,26.49209 -8.14703,-3.03359 -9.71336,-17.14283 -6.5565,-25.2429 6.70872,-17.21364 23.33215,-30.04549 46.55894,-30.06845 21.25806,-0.021 37.1774,11.87004 44.62328,27.71858 z"
|
||||||
|
style="display:inline;fill:#c89172;fill-opacity:1;stroke:none;stroke-width:1.49886632;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="csccsc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path6091"
|
||||||
|
d="m 236.44687,601.79814 c -10.07014,-23.96206 -15.47347,-49.64233 -15.47347,-76.29297 0,-24.59922 3.77719,-48.92918 11.22886,-71.48757 113.05163,-72.24038 211.71014,-23.66044 216.29587,55.37861 0.92941,43.30708 -14.85596,73.14738 -66.59091,84.14256 -40.60772,8.63033 -109.03729,1.65487 -145.46035,8.25937 z"
|
||||||
|
style="display:inline;fill:#e3ccbe;fill-opacity:1;stroke:none;stroke-width:1.53848529;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||||
|
<path
|
||||||
|
style="display:inline;fill:#c89172;fill-opacity:1;stroke:none;stroke-width:1.49886632;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||||
|
d="m 318.38443,512.02942 c -3.98124,8.47407 -4.66411,23.87376 3.82321,27.82668 15.14244,7.05251 13.43948,-27.87381 42.39106,-26.726 27.91154,1.10657 23.83539,31.91957 38.41145,26.49209 8.14703,-3.03359 9.71336,-17.14283 6.5565,-25.2429 -6.70872,-17.21364 -23.33215,-30.04549 -46.55894,-30.06845 -21.25806,-0.021 -37.1774,11.87004 -44.62328,27.71858 z"
|
||||||
|
id="path6093"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="aasaasa" />
|
||||||
|
<path
|
||||||
|
transform="matrix(0.96767168,0,0,1.0314138,16.012714,-19.869878)"
|
||||||
|
sodipodi:nodetypes="sscccsscs"
|
||||||
|
inkscape:original-d="m 581.94888,642.38075 c -0.11685,-5.42216 7.07007,-17.61775 2.82843,-16.79379 -4.24164,0.82396 -9.19339,2.47588 -16.26346,5.3033 -7.74,3.20278 -35.48656,-1.28199 -51.42842,-9.77919 -17.49196,7.64885 -42.65501,12.98197 -50.39501,9.77919 -7.07007,-2.82742 -12.02182,-4.47934 -16.26346,-5.3033 -4.24164,-0.82396 2.94528,11.37163 2.82843,16.79379 -0.11685,5.42215 41.7595,1.3486 63.7987,2.05671 22.03919,-0.70811 65.01164,3.36544 64.89479,-2.05671 z"
|
||||||
|
inkscape:path-effect="#path-effect6099"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path6097"
|
||||||
|
d="m 581.94888,642.38075 c 2.38253,-2.24081 4.60569,-4.83839 5.47508,-7.99146 0.4347,-1.57654 0.5088,-3.26889 0.081,-4.84729 -0.42785,-1.57841 -1.37681,-3.0332 -2.7276,-3.95504 -1.26545,-0.8636 -2.83258,-1.23063 -4.36364,-1.17554 -1.53106,0.0551 -3.02872,0.51417 -4.40643,1.1843 -2.75543,1.34027 -5.02124,3.48424 -7.49339,5.29454 -7.89483,5.7812 -18.22631,8.11406 -27.83929,6.28614 -9.61298,-1.82792 -18.36718,-7.78995 -23.58913,-16.06533 -5.088,8.13656 -13.65079,14.01754 -23.07148,15.84563 -9.42069,1.82809 -19.56159,-0.42342 -27.32353,-6.06644 -2.47705,-1.80085 -4.7434,-3.94147 -7.49681,-5.28222 -1.3767,-0.67037 -2.8729,-1.13084 -4.40308,-1.18819 -1.53017,-0.0574 -3.09706,0.30649 -4.36357,1.16711 -1.35354,0.91976 -2.30564,2.37417 -2.73564,3.95314 -0.43,1.57896 -0.35707,3.27272 0.0776,4.8504 0.86942,3.15535 3.097,5.75356 5.48643,7.99025 8.48113,7.93899 19.90111,12.66409 31.51218,13.0384 11.61107,0.37431 23.31167,-3.60544 32.28652,-10.98169 9.10954,7.53977 21.01716,11.61649 32.83628,11.24191 11.81911,-0.37458 23.44469,-5.19714 32.05851,-13.29862 z"
|
||||||
|
style="fill:#c89172;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 9.8 KiB |
90
web/assets/profile.css
Normal file
90
web/assets/profile.css
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
main {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerimage img {
|
||||||
|
width: 100%;
|
||||||
|
height: 15em;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile {
|
||||||
|
position: relative;
|
||||||
|
background: rgb(75, 84, 93);
|
||||||
|
padding: 2rem;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-around;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-bottom: 0.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile .basic {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1 1 25em;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile .basic a {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile .basic .avatar img {
|
||||||
|
height: 25em;
|
||||||
|
width: 25em;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile .basic .displayname {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
align-self: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile .detailed {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1 1 25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile .detailed h2 {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile .detailed .bio {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile .detailed .bio a {
|
||||||
|
color: #de8957;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accountstats {
|
||||||
|
position: relative;
|
||||||
|
background: rgb(75, 84, 93);
|
||||||
|
padding: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-bottom: 0.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accountstats .entry {
|
||||||
|
background: rgb(89, 99, 110);
|
||||||
|
padding: 0.5rem;
|
||||||
|
flex-grow: 1;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer + div {
|
||||||
|
/* something weird from the devstack.. */
|
||||||
|
display: none;
|
||||||
|
}
|
94
web/gotosocial-styling/templates/profile.css
Normal file
94
web/gotosocial-styling/templates/profile.css
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
main {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.headerimage {
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 15em;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile {
|
||||||
|
position: relative;
|
||||||
|
background: color($bg lightness(-3%));
|
||||||
|
padding: 2rem;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-around;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-bottom: 0.2rem;
|
||||||
|
|
||||||
|
.basic {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1 1 25em;
|
||||||
|
gap: 0.5rem;
|
||||||
|
|
||||||
|
a {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
img {
|
||||||
|
height: 25em;
|
||||||
|
width: 25em;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.displayname {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
align-self: start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.detailed {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1 1 25em;
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bio {
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: $acc1;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.accountstats {
|
||||||
|
position: relative;
|
||||||
|
background: color($bg lightness(-3%));
|
||||||
|
padding: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-bottom: 0.2rem;
|
||||||
|
|
||||||
|
.entry {
|
||||||
|
background: color($bg lightness(+3%));
|
||||||
|
padding: 0.5rem;
|
||||||
|
flex-grow: 1;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
footer + div {
|
||||||
|
/* something weird from the devstack.. */
|
||||||
|
display: none;
|
||||||
|
}
|
47
web/template/profile.tmpl
Normal file
47
web/template/profile.tmpl
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
{{ template "header.tmpl" .}}
|
||||||
|
<main>
|
||||||
|
{{ if .account.Header }}<a href="{{.account.Header}}" class="headerimage"><img src="{{.account.Header}}"></a>{{ end }}
|
||||||
|
<div class="profile">
|
||||||
|
<div class="basic">
|
||||||
|
<a href="{{.account.URL}}" class="displayname">{{if .account.DisplayName}}{{.account.DisplayName}}{{else}}{{.account.Username}}{{end}}</a>
|
||||||
|
<a href="{{.account.URL}}" class="username">@{{.account.Username}}</a>
|
||||||
|
<a href="{{.account.Avatar}}" class="avatar"><img src="{{.account.Avatar}}"></a>
|
||||||
|
</div>
|
||||||
|
<div class="detailed">
|
||||||
|
<h2>About @{{.account.Username}}</h2>
|
||||||
|
<div class="bio">
|
||||||
|
{{ if .account.Note }}{{ .account.Note | noescape }}{{else}}This GoToSocial user hasn't written a bio yet!{{end}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="accountstats">
|
||||||
|
<div class="entry">Joined {{.account.CreatedAt | timestampShort}}</div>
|
||||||
|
<div class="entry">Followed by {{.account.FollowersCount}}</div>
|
||||||
|
<div class="entry">Following {{.account.FollowingCount}}</div>
|
||||||
|
<div class="entry">Posted {{.account.StatusesCount}}</div>
|
||||||
|
</div>
|
||||||
|
<h2>Recent public posts by @{{.account.Username}}</h2>
|
||||||
|
<div class="thread">
|
||||||
|
{{range .statuses}}
|
||||||
|
<div class="toot expanded">
|
||||||
|
{{ template "status.tmpl" .}}
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<script>
|
||||||
|
Array.from(document.getElementsByClassName("spoiler-label")).forEach((label) => {
|
||||||
|
let checkbox = document.getElementById(label.htmlFor);
|
||||||
|
function update() {
|
||||||
|
if(checkbox.checked) {
|
||||||
|
label.innerHTML = "Show more";
|
||||||
|
} else {
|
||||||
|
label.innerHTML = "Show less";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
|
||||||
|
label.addEventListener("click", () => {setTimeout(update, 1)});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{{ template "footer.tmpl" .}}
|
Loading…
Reference in a new issue