diff options
Diffstat (limited to 'internal')
-rw-r--r-- | internal/api/model/poll.go | 21 | ||||
-rw-r--r-- | internal/api/model/status.go | 11 | ||||
-rw-r--r-- | internal/router/template.go | 5 | ||||
-rw-r--r-- | internal/typeutils/internaltofrontend.go | 57 |
4 files changed, 89 insertions, 5 deletions
diff --git a/internal/api/model/poll.go b/internal/api/model/poll.go index a9842e7a9..7eddb66ef 100644 --- a/internal/api/model/poll.go +++ b/internal/api/model/poll.go @@ -17,6 +17,8 @@ package model +import "github.com/superseriousbusiness/gotosocial/internal/language" + // Poll represents a poll attached to a status. // // swagger:model poll @@ -104,3 +106,22 @@ type PollVoteRequest struct { // indices. Can be strings or integers. ChoicesI []interface{} `json:"choices"` } + +// WebPollOption models a template-ready poll option entry. +// +// swagger:ignore +type WebPollOption struct { + PollOption + + // Emojis contained on parent poll. + Emojis []Emoji + + // LanguageTag of parent status. + LanguageTag *language.Language + + // Share of total votes as a percentage. + VoteShare float32 + + // String-formatted version of VoteShare. + VoteShareStr string +} diff --git a/internal/api/model/status.go b/internal/api/model/status.go index 1efae9cfc..5c54bfe96 100644 --- a/internal/api/model/status.go +++ b/internal/api/model/status.go @@ -105,8 +105,17 @@ type Status struct { // (used only internally for templating etc). // Template-ready language tag + string, based - // on *status.Language. Nil for non-web statuses + // on *status.Language. Nil for non-web statuses. + // + // swagger:ignore LanguageTag *language.Language `json:"-"` + + // Template-ready poll options with vote shares + // calculated as a percentage of total votes. + // Nil for non-web statuses. + // + // swagger:ignore + WebPollOptions []WebPollOption `json:"-"` } /* diff --git a/internal/router/template.go b/internal/router/template.go index d8b5b5edd..804f532bd 100644 --- a/internal/router/template.go +++ b/internal/router/template.go @@ -168,6 +168,10 @@ func acctInstance(acct string) string { return "" } +func increment(i int) int { + return i + 1 +} + func LoadTemplateFunctions(engine *gin.Engine) { engine.SetFuncMap(template.FuncMap{ "escape": escape, @@ -180,5 +184,6 @@ func LoadTemplateFunctions(engine *gin.Engine) { "timestampPrecise": timestampPrecise, "emojify": emojify, "acctInstance": acctInstance, + "increment": increment, }) } diff --git a/internal/typeutils/internaltofrontend.go b/internal/typeutils/internaltofrontend.go index 8138ee7b4..0668d44bb 100644 --- a/internal/typeutils/internaltofrontend.go +++ b/internal/typeutils/internaltofrontend.go @@ -678,6 +678,48 @@ func (c *Converter) StatusToWebStatus( } } + if poll := webStatus.Poll; poll != nil { + // Calculate vote share of each poll option and + // format them for easier template consumption. + totalVotes := poll.VotesCount + + webPollOptions := make([]apimodel.WebPollOption, len(poll.Options)) + for i, option := range poll.Options { + var voteShare float32 + if totalVotes != 0 && + option.VotesCount != 0 { + voteShare = (float32(option.VotesCount) / float32(totalVotes)) * 100 + } + + // Format to two decimal points and ditch any + // trailing zeroes. + // + // We want to be precise enough that eg., "1.54%" + // is distinct from "1.68%" in polls with loads + // of votes. + // + // However, if we've got eg., a two-option poll + // in which each option has half the votes, then + // "50%" looks better than "50.00%". + // + // By the same token, it's pointless to show + // "0.00%" or "100.00%". + voteShareStr := fmt.Sprintf("%.2f", voteShare) + voteShareStr = strings.TrimSuffix(voteShareStr, ".00") + + webPollOption := apimodel.WebPollOption{ + PollOption: option, + Emojis: webStatus.Emojis, + LanguageTag: webStatus.LanguageTag, + VoteShare: voteShare, + VoteShareStr: voteShareStr, + } + webPollOptions[i] = webPollOption + } + + webStatus.WebPollOptions = webPollOptions + } + return webStatus, nil } @@ -1456,10 +1498,17 @@ func (c *Converter) PollToAPIPoll(ctx context.Context, requester *gtsmodel.Accou expiresAt = util.FormatISO8601(poll.ExpiresAt) } - // TODO: emojis used in poll options. - // For now init to empty slice to serialize as `[]`. - // In future inherit from parent status. - emojis = make([]apimodel.Emoji, 0) + // Try to inherit emojis + // from parent status. + if pStatus := poll.Status; pStatus != nil { + var err error + emojis, err = c.convertEmojisToAPIEmojis(ctx, pStatus.Emojis, pStatus.EmojiIDs) + if err != nil { + // Fall back to empty slice. + log.Errorf(ctx, "error converting emojis from parent status: %v", err) + emojis = make([]apimodel.Emoji, 0) + } + } return &apimodel.Poll{ ID: poll.ID, |