From ef2b02b799aecfd243260bd2892972a8040b4a7f Mon Sep 17 00:00:00 2001 From: Dan Anglin Date: Tue, 13 Aug 2024 18:30:46 +0100 Subject: [PATCH] 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. --- docs/manual.md | 11 +---- internal/executor/show.go | 16 ------- internal/printer/poll.go | 89 ------------------------------------- internal/printer/printer.go | 6 +-- internal/printer/status.go | 73 +++++++++++++++++++++++++++++- 5 files changed, 75 insertions(+), 120 deletions(-) diff --git a/docs/manual.md b/docs/manual.md index 48332f6..0ce4ca9 100644 --- a/docs/manual.md +++ b/docs/manual.md @@ -536,16 +536,7 @@ See [Create a status](#create-a-status). ### View a poll -Prints the poll information to the screen. - -``` -enbas show --type poll --poll-id 01J0CEEZBZ6E6AYQSJPHCQYBDA -``` - -| flag | type | required | description | default | -|------|------|----------|-------------|---------| -| `type` | string | true | The resource you want to view.
Here this should be `poll`. | | -| `poll-id` | string | true | The ID of the poll that you want to view. | | +You can view a poll from a status or timeline. ### Vote in a poll diff --git a/internal/executor/show.go b/internal/executor/show.go index fafc692..6a3fd64 100644 --- a/internal/executor/show.go +++ b/internal/executor/show.go @@ -28,7 +28,6 @@ func (s *ShowExecutor) Execute() error { resourceLiked: s.showLiked, resourceStarred: s.showLiked, resourceFollowRequest: s.showFollowRequests, - resourcePoll: s.showPoll, resourceMutedAccounts: s.showMutedAccounts, resourceMedia: s.showMedia, resourceMediaAttachment: s.showMediaAttachment, @@ -372,21 +371,6 @@ func (s *ShowExecutor) showFollowRequests(gtsClient *client.Client) error { 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 { muted, err := gtsClient.GetMutedAccounts(s.limit) if err != nil { diff --git a/internal/printer/poll.go b/internal/printer/poll.go index 16c99fe..1a3a646 100644 --- a/internal/printer/poll.go +++ b/internal/printer/poll.go @@ -1,91 +1,2 @@ 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 -} diff --git a/internal/printer/printer.go b/internal/printer/printer.go index 6ac2325..0ec5951 100644 --- a/internal/printer/printer.go +++ b/internal/printer/printer.go @@ -13,7 +13,7 @@ const ( noMediaDescription = "This media attachment has no description." symbolBullet = "\u2022" symbolPollMeter = "\u2501" - symbolSuccess = "\u2714" + symbolCheckMark = "\u2714" symbolFailure = "\u2717" symbolImage = "\uf03e" symbolLiked = "\uf51f" @@ -78,9 +78,9 @@ func NewPrinter( } 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 { - success = symbolSuccess + success = symbolCheckMark } printToStdout(success + " " + text + "\n") diff --git a/internal/printer/status.go b/internal/printer/status.go index 38ae7a7..8095407 100644 --- a/internal/printer/status.go +++ b/internal/printer/status.go @@ -1,6 +1,7 @@ package printer import ( + "math" "strconv" "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 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 @@ -120,7 +122,7 @@ func (p Printer) statusList(list model.StatusList) string { builder.WriteString("\n" + p.convertHTMLToText(content, true)) if poll != nil { - builder.WriteString(p.pollOptions(*poll)) + builder.WriteString(p.pollDetails(*poll)) } for _, media := range mediaAttachments { @@ -172,3 +174,70 @@ func (p Printer) statusList(list model.StatusList) 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 +}