checkpoint:

- BREAKING: user can no longer view a poll directly from the poll ID.
- Added more poll details in status view.
- Poll now shows the user's vote in status/timeline view.
This commit is contained in:
Dan Anglin 2024-08-13 18:30:46 +01:00
parent b77bbaa6e0
commit ef2b02b799
Signed by: dananglin
GPG key ID: 0C1D44CFBEE68638
5 changed files with 75 additions and 120 deletions

View file

@ -536,16 +536,7 @@ See [Create a status](#create-a-status).
### View a poll ### View a poll
Prints the poll information to the screen. You can view a poll from a status or timeline.
```
enbas show --type poll --poll-id 01J0CEEZBZ6E6AYQSJPHCQYBDA
```
| flag | type | required | description | default |
|------|------|----------|-------------|---------|
| `type` | string | true | The resource you want to view.<br>Here this should be `poll`. | |
| `poll-id` | string | true | The ID of the poll that you want to view. | |
### Vote in a poll ### Vote in a poll

View file

@ -28,7 +28,6 @@ func (s *ShowExecutor) Execute() error {
resourceLiked: s.showLiked, resourceLiked: s.showLiked,
resourceStarred: s.showLiked, resourceStarred: s.showLiked,
resourceFollowRequest: s.showFollowRequests, resourceFollowRequest: s.showFollowRequests,
resourcePoll: s.showPoll,
resourceMutedAccounts: s.showMutedAccounts, resourceMutedAccounts: s.showMutedAccounts,
resourceMedia: s.showMedia, resourceMedia: s.showMedia,
resourceMediaAttachment: s.showMediaAttachment, resourceMediaAttachment: s.showMediaAttachment,
@ -372,21 +371,6 @@ func (s *ShowExecutor) showFollowRequests(gtsClient *client.Client) error {
return nil return nil
} }
func (s *ShowExecutor) showPoll(gtsClient *client.Client) error {
if s.pollID == "" {
return FlagNotSetError{flagText: flagPollID}
}
poll, err := gtsClient.GetPoll(s.pollID)
if err != nil {
return fmt.Errorf("unable to retrieve the poll: %w", err)
}
s.printer.PrintPoll(poll)
return nil
}
func (s *ShowExecutor) showMutedAccounts(gtsClient *client.Client) error { func (s *ShowExecutor) showMutedAccounts(gtsClient *client.Client) error {
muted, err := gtsClient.GetMutedAccounts(s.limit) muted, err := gtsClient.GetMutedAccounts(s.limit)
if err != nil { if err != nil {

View file

@ -1,91 +1,2 @@
package printer package printer
import (
"math"
"strconv"
"strings"
"codeflow.dananglin.me.uk/apollo/enbas/internal/model"
)
func (p Printer) PrintPoll(poll model.Poll) {
var builder strings.Builder
builder.WriteString("\n" + p.headerFormat("POLL ID:"))
builder.WriteString("\n" + poll.ID)
builder.WriteString("\n\n" + p.headerFormat("OPTIONS:"))
builder.WriteString(p.pollOptions(poll))
builder.WriteString("\n\n" + p.headerFormat("MULTIPLE CHOICES ALLOWED:"))
builder.WriteString("\n" + strconv.FormatBool(poll.Multiple))
builder.WriteString("\n\n" + p.headerFormat("YOU VOTED:"))
builder.WriteString("\n" + strconv.FormatBool(poll.Voted))
if len(poll.OwnVotes) > 0 {
builder.WriteString("\n\n" + p.headerFormat("YOUR VOTES:"))
for _, vote := range poll.OwnVotes {
builder.WriteString("\n" + "[" + strconv.Itoa(vote) + "] " + poll.Options[vote].Title)
}
}
builder.WriteString("\n\n" + p.headerFormat("EXPIRED:"))
builder.WriteString("\n" + strconv.FormatBool(poll.Expired))
builder.WriteString("\n\n")
p.print(builder.String())
}
func (p Printer) pollOptions(poll model.Poll) string {
var builder strings.Builder
for ind, option := range poll.Options {
var (
votage float64
percentage int
)
if poll.VotesCount == 0 {
percentage = 0
} else {
votage = float64(option.VotesCount) / float64(poll.VotesCount)
percentage = int(math.Floor(100 * votage))
}
builder.WriteString("\n\n" + "[" + strconv.Itoa(ind) + "] " + option.Title)
builder.WriteString(p.pollMeter(votage))
builder.WriteString("\n" + strconv.Itoa(option.VotesCount) + " votes " + "(" + strconv.Itoa(percentage) + "%)")
}
builder.WriteString("\n\n" + p.fieldFormat("Total votes:") + " " + strconv.Itoa(poll.VotesCount))
builder.WriteString("\n" + p.fieldFormat("Poll ID:") + " " + poll.ID)
builder.WriteString("\n" + p.fieldFormat("Poll is open until:") + " " + p.formatDateTime(poll.ExpiredAt))
return builder.String()
}
func (p Printer) pollMeter(votage float64) string {
numVoteBlocks := int(math.Floor(float64(p.lineWrapCharacterLimit) * votage))
numBackgroundBlocks := p.lineWrapCharacterLimit - numVoteBlocks
voteBlockColor := p.theme.boldgreen
backgroundBlockColor := p.theme.grey
if p.noColor {
voteBlockColor = p.theme.reset
if numVoteBlocks == 0 {
numVoteBlocks = 1
}
}
meter := "\n" + voteBlockColor + strings.Repeat(symbolPollMeter, numVoteBlocks) + p.theme.reset
if !p.noColor {
meter += backgroundBlockColor + strings.Repeat(symbolPollMeter, numBackgroundBlocks) + p.theme.reset
}
return meter
}

View file

@ -13,7 +13,7 @@ const (
noMediaDescription = "This media attachment has no description." noMediaDescription = "This media attachment has no description."
symbolBullet = "\u2022" symbolBullet = "\u2022"
symbolPollMeter = "\u2501" symbolPollMeter = "\u2501"
symbolSuccess = "\u2714" symbolCheckMark = "\u2714"
symbolFailure = "\u2717" symbolFailure = "\u2717"
symbolImage = "\uf03e" symbolImage = "\uf03e"
symbolLiked = "\uf51f" symbolLiked = "\uf51f"
@ -78,9 +78,9 @@ func NewPrinter(
} }
func (p Printer) PrintSuccess(text string) { func (p Printer) PrintSuccess(text string) {
success := p.theme.boldgreen + symbolSuccess + p.theme.reset success := p.theme.boldgreen + symbolCheckMark + p.theme.reset
if p.noColor { if p.noColor {
success = symbolSuccess success = symbolCheckMark
} }
printToStdout(success + " " + text + "\n") printToStdout(success + " " + text + "\n")

View file

@ -1,6 +1,7 @@
package printer package printer
import ( import (
"math"
"strconv" "strconv"
"strings" "strings"
@ -41,7 +42,8 @@ func (p Printer) PrintStatus(status model.Status) {
// If a poll exists in a status, write the contents to the builder. // If a poll exists in a status, write the contents to the builder.
if status.Poll != nil { if status.Poll != nil {
builder.WriteString(p.pollOptions(*status.Poll)) builder.WriteString("\n\n" + p.headerFormat("POLL DETAILS:"))
builder.WriteString(p.pollDetails(*status.Poll))
} }
// Status creation time // Status creation time
@ -120,7 +122,7 @@ func (p Printer) statusList(list model.StatusList) string {
builder.WriteString("\n" + p.convertHTMLToText(content, true)) builder.WriteString("\n" + p.convertHTMLToText(content, true))
if poll != nil { if poll != nil {
builder.WriteString(p.pollOptions(*poll)) builder.WriteString(p.pollDetails(*poll))
} }
for _, media := range mediaAttachments { for _, media := range mediaAttachments {
@ -172,3 +174,70 @@ func (p Printer) statusList(list model.StatusList) string {
return builder.String() return builder.String()
} }
func (p Printer) pollDetails(poll model.Poll) string {
var builder strings.Builder
for ind, option := range poll.Options {
var (
votage float64
percentage int
)
if poll.VotesCount == 0 {
percentage = 0
} else {
votage = float64(option.VotesCount) / float64(poll.VotesCount)
percentage = int(math.Floor(100 * votage))
}
optionTitle := "\n\n" + "[" + strconv.Itoa(ind) + "] " + option.Title
for _, vote := range poll.OwnVotes {
if ind == vote {
optionTitle += " " + symbolCheckMark
break
}
}
builder.WriteString(optionTitle)
builder.WriteString(p.pollMeter(votage))
builder.WriteString("\n" + strconv.Itoa(option.VotesCount) + " votes " + "(" + strconv.Itoa(percentage) + "%)")
}
pollStatusField := "Poll is open until: "
if poll.Expired {
pollStatusField = "Poll was closed on: "
}
builder.WriteString("\n\n" + p.fieldFormat(pollStatusField) + p.formatDateTime(poll.ExpiredAt))
builder.WriteString("\n" + p.fieldFormat("Total votes: ") + strconv.Itoa(poll.VotesCount))
builder.WriteString("\n" + p.fieldFormat("Multiple choices allowed: ") + strconv.FormatBool(poll.Multiple))
return builder.String()
}
func (p Printer) pollMeter(votage float64) string {
numVoteBlocks := int(math.Floor(float64(p.lineWrapCharacterLimit) * votage))
numBackgroundBlocks := p.lineWrapCharacterLimit - numVoteBlocks
voteBlockColour := p.theme.boldgreen
backgroundBlockColor := p.theme.grey
if p.noColor {
voteBlockColour = p.theme.reset
if numVoteBlocks == 0 {
numVoteBlocks = 1
}
}
meter := "\n" + voteBlockColour + strings.Repeat(symbolPollMeter, numVoteBlocks) + p.theme.reset
if !p.noColor {
meter += backgroundBlockColor + strings.Repeat(symbolPollMeter, numBackgroundBlocks) + p.theme.reset
}
return meter
}