Add support for displaying polls
Doesn't look the prettiest, but it's there!
This commit is contained in:
parent
a0b3970747
commit
6fc967c05a
@ -417,6 +417,40 @@ form.search {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Polls */
|
||||||
|
|
||||||
|
.poll {
|
||||||
|
font-size: 14px;
|
||||||
|
margin: 0 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.poll ul {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.poll li {
|
||||||
|
padding: 4px 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.poll .poll-percentage {
|
||||||
|
display: inline-block;
|
||||||
|
width: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.poll .poll-bar {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 6px;
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: #9baec8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.poll .poll-footer {
|
||||||
|
color: #aaa;
|
||||||
|
display: block;
|
||||||
|
padding: 10px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Spoiler */
|
/* Spoiler */
|
||||||
|
|
||||||
.spoiled input[type=checkbox] {
|
.spoiled input[type=checkbox] {
|
||||||
|
@ -21,6 +21,9 @@ module Mastodon.Decoder
|
|||||||
, searchResultsDecoder
|
, searchResultsDecoder
|
||||||
, statusDecoder
|
, statusDecoder
|
||||||
, webSocketEventDecoder
|
, webSocketEventDecoder
|
||||||
|
, pollIdDecoder
|
||||||
|
, pollOptionDecoder
|
||||||
|
, pollDecoder
|
||||||
)
|
)
|
||||||
|
|
||||||
import Json.Decode as Decode
|
import Json.Decode as Decode
|
||||||
@ -253,6 +256,28 @@ idDecoder =
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
pollIdDecoder : Decode.Decoder PollId
|
||||||
|
pollIdDecoder =
|
||||||
|
idDecoder |> Decode.map PollId
|
||||||
|
|
||||||
|
|
||||||
|
pollOptionDecoder : Decode.Decoder PollOption
|
||||||
|
pollOptionDecoder =
|
||||||
|
Pipe.decode PollOption
|
||||||
|
|> Pipe.required "title" Decode.string
|
||||||
|
|> Pipe.required "votes_count" Decode.int
|
||||||
|
|
||||||
|
|
||||||
|
pollDecoder : Decode.Decoder Poll
|
||||||
|
pollDecoder =
|
||||||
|
Pipe.decode Poll
|
||||||
|
|> Pipe.required "id" pollIdDecoder
|
||||||
|
|> Pipe.required "expired" Decode.bool
|
||||||
|
|> Pipe.required "voted" Decode.bool
|
||||||
|
|> Pipe.required "votes_count" Decode.int
|
||||||
|
|> Pipe.required "options" (Decode.list pollOptionDecoder)
|
||||||
|
|
||||||
|
|
||||||
statusIdDecoder : Decode.Decoder StatusId
|
statusIdDecoder : Decode.Decoder StatusId
|
||||||
statusIdDecoder =
|
statusIdDecoder =
|
||||||
idDecoder |> Decode.map StatusId
|
idDecoder |> Decode.map StatusId
|
||||||
@ -281,6 +306,13 @@ statusDecoder =
|
|||||||
|> Pipe.required "uri" Decode.string
|
|> Pipe.required "uri" Decode.string
|
||||||
|> Pipe.required "url" (Decode.nullable Decode.string)
|
|> Pipe.required "url" (Decode.nullable Decode.string)
|
||||||
|> Pipe.required "visibility" Decode.string
|
|> Pipe.required "visibility" Decode.string
|
||||||
|
|> Pipe.optional "poll" pollDecoder
|
||||||
|
{ id = PollId("")
|
||||||
|
, expired = False
|
||||||
|
, votes_count = -1
|
||||||
|
, voted = False
|
||||||
|
, options = []
|
||||||
|
}
|
||||||
|> Pipe.optional "pinned" Decode.bool False -- Not a real value, used to show pinned indicator
|
|> Pipe.optional "pinned" Decode.bool False -- Not a real value, used to show pinned indicator
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,6 +20,9 @@ module Mastodon.Model
|
|||||||
, Reblog(..)
|
, Reblog(..)
|
||||||
, Relationship
|
, Relationship
|
||||||
, Tag
|
, Tag
|
||||||
|
, PollId(..)
|
||||||
|
, PollOption
|
||||||
|
, Poll
|
||||||
, SearchResults
|
, SearchResults
|
||||||
, Source
|
, Source
|
||||||
, Status
|
, Status
|
||||||
@ -239,6 +242,25 @@ type alias Hashtag =
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type PollId
|
||||||
|
= PollId String
|
||||||
|
|
||||||
|
|
||||||
|
type alias PollOption =
|
||||||
|
{ title : String
|
||||||
|
, votes_count : Int
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type alias Poll =
|
||||||
|
{ id : PollId
|
||||||
|
, expired : Bool
|
||||||
|
, voted : Bool
|
||||||
|
, votes_count : Int
|
||||||
|
, options : List PollOption
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
type alias SearchResults =
|
type alias SearchResults =
|
||||||
{ accounts : List Account
|
{ accounts : List Account
|
||||||
, statuses : List Status
|
, statuses : List Status
|
||||||
@ -277,6 +299,7 @@ type alias Status =
|
|||||||
, uri : String
|
, uri : String
|
||||||
, url : Maybe String
|
, url : Maybe String
|
||||||
, visibility : String
|
, visibility : String
|
||||||
|
, poll : Poll
|
||||||
, pinned : Bool -- Not a real value, used to show pinned indicator
|
, pinned : Bool -- Not a real value, used to show pinned indicator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,6 +86,47 @@ attachmentListView context { media_attachments, sensitive } =
|
|||||||
List.map (keyedEntry attachments) attachments
|
List.map (keyedEntry attachments) attachments
|
||||||
|
|
||||||
|
|
||||||
|
pollView : Status -> Html Msg
|
||||||
|
pollView status =
|
||||||
|
let
|
||||||
|
pollStatus poll =
|
||||||
|
if poll.voted then
|
||||||
|
text "Voted"
|
||||||
|
else if poll.expired then
|
||||||
|
text "Expired"
|
||||||
|
else
|
||||||
|
text "Not voted"
|
||||||
|
optionPercentage option =
|
||||||
|
100*option.votes_count//status.poll.votes_count
|
||||||
|
optionPercentageText option =
|
||||||
|
span [ class "poll-percentage" ]
|
||||||
|
[ text <| (toString (optionPercentage option))++"%"
|
||||||
|
]
|
||||||
|
optionBar option =
|
||||||
|
span
|
||||||
|
[ class "poll-bar"
|
||||||
|
, style [("width", toString (optionPercentage option)++"%")]
|
||||||
|
] []
|
||||||
|
optionEntry option =
|
||||||
|
li []
|
||||||
|
[ optionPercentageText option
|
||||||
|
, text option.title
|
||||||
|
, optionBar option
|
||||||
|
]
|
||||||
|
in
|
||||||
|
if status.poll.id == PollId("") then
|
||||||
|
text ""
|
||||||
|
else
|
||||||
|
div [ class "poll" ]
|
||||||
|
[ ul [] <|
|
||||||
|
List.map optionEntry status.poll.options
|
||||||
|
, span [ class "poll-footer" ]
|
||||||
|
[ text <| (toString status.poll.votes_count)++" votes"
|
||||||
|
, text " • "
|
||||||
|
, pollStatus status.poll ]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
statusActionsView : Status -> CurrentUser -> Bool -> Html Msg
|
statusActionsView : Status -> CurrentUser -> Bool -> Html Msg
|
||||||
statusActionsView status currentUser showApp =
|
statusActionsView status currentUser showApp =
|
||||||
let
|
let
|
||||||
@ -156,6 +197,7 @@ statusContentView context status =
|
|||||||
"" ->
|
"" ->
|
||||||
div [ class "status-text" ]
|
div [ class "status-text" ]
|
||||||
[ div [] <| formatContent status.content status.mentions
|
[ div [] <| formatContent status.content status.mentions
|
||||||
|
, pollView status
|
||||||
, attachmentListView context status
|
, attachmentListView context status
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -172,6 +214,7 @@ statusContentView context status =
|
|||||||
, label [ onClickWithStop NoOp, for statusId ] [ text "Reveal content" ]
|
, label [ onClickWithStop NoOp, for statusId ] [ text "Reveal content" ]
|
||||||
, div [ class "spoiled-content" ]
|
, div [ class "spoiled-content" ]
|
||||||
[ div [] <| formatContent status.content status.mentions
|
[ div [] <| formatContent status.content status.mentions
|
||||||
|
, pollView status
|
||||||
, attachmentListView context status
|
, attachmentListView context status
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
Loading…
Reference in New Issue
Block a user