fix(polls): apply suggestions and fix id parsing

This commit is contained in:
Ondřej Pešek 2023-04-01 14:26:04 +02:00
parent 8bed342a6d
commit 75af984154
2 changed files with 29 additions and 21 deletions

View File

@ -104,12 +104,12 @@ pub struct Poll {
impl Poll { impl Poll {
pub fn parse(poll_data: &Value) -> Option<Self> { pub fn parse(poll_data: &Value) -> Option<Self> {
if poll_data.as_object().is_none() { return None }; poll_data.as_object()?;
let total_vote_count = poll_data["total_vote_count"].as_u64()?; let total_vote_count = poll_data["total_vote_count"].as_u64()?;
// voting_end_timestamp is in the format of milliseconds // voting_end_timestamp is in the format of milliseconds
let voting_end_timestamp = time(poll_data["voting_end_timestamp"].as_f64()? / 1000.0); let voting_end_timestamp = time(poll_data["voting_end_timestamp"].as_f64()? / 1000.0);
let poll_options = PollOption::parse(&poll_data["options"]); let poll_options = PollOption::parse(&poll_data["options"])?;
Some(Self { Some(Self {
poll_options, poll_options,
@ -119,36 +119,38 @@ impl Poll {
} }
pub fn most_votes(&self) -> u64 { pub fn most_votes(&self) -> u64 {
self.poll_options.iter().map(|o| o.vote_count).max().unwrap_or(0) self.poll_options.iter().map(|o| o.vote_count).flatten().max().unwrap_or(0)
} }
} }
pub struct PollOption { pub struct PollOption {
pub id: u64, pub id: u64,
pub text: String, pub text: String,
pub vote_count: u64 pub vote_count: Option<u64>
} }
impl PollOption { impl PollOption {
pub fn parse(options: &Value) -> Vec<Self> { pub fn parse(options: &Value) -> Option<Vec<Self>> {
options Some(options
.as_array() .as_array()?
.unwrap_or(&Vec::new())
.iter() .iter()
.map(|option| { .map(|option| {
// For each poll option // For each poll option
let id = option["id"].as_u64().unwrap_or_default();
let text = option["text"].as_str().unwrap_or_default().to_owned(); // we can't just use as_u64() because "id": String("...") and serde would parse it as None
let vote_count = option["vote_count"].as_u64().unwrap_or_default(); let id = option["id"].as_str()?.parse::<u64>().ok()?;
let text = option["text"].as_str()?.to_owned();
let vote_count = option["vote_count"].as_u64();
// Construct PollOption items // Construct PollOption items
Self { Some(Self {
id, id,
text, text,
vote_count vote_count
} })
}) })
.collect::<Vec<Self>>() .flatten()
.collect::<Vec<Self>>())
} }
} }

View File

@ -315,14 +315,20 @@
<span>{{ poll.voting_end_timestamp.0 }}</span> <span>{{ poll.voting_end_timestamp.0 }}</span>
{% for option in poll.poll_options %} {% for option in poll.poll_options %}
<div class="poll_option"> <div class="poll_option">
{# Posts without vote_count (all open polls) will show up as having 0 votes. {# Posts without vote_count (all open polls) will show up without votes.
This is an issue with Reddit API, it doesn't work on Old Reddit either. #} This is an issue with Reddit API, it doesn't work on Old Reddit either. #}
{% if option.vote_count == widest %} {% match option.vote_count %}
<div class="poll_chart most_voted" style="width: 100%"></div> {% when Some with (vote_count) %}
{% else %} {% if vote_count.eq(widest) || widest == 0 %}
<div class="poll_chart" style="width: {{ (option.vote_count * 100) / widest }}%"></div> <div class="poll_chart most_voted" style="width: 100%"></div>
{% endif %} {% else %}
<span>{{ option.vote_count }}</span> <div class="poll_chart" style="width: {{ (vote_count * 100) / widest }}%"></div>
{% endif %}
<span>{{ vote_count }}</span>
{% when None %}
<div class="poll_chart most_voted" style="width: 100%"></div>
<span></span>
{% endmatch %}
<span>{{ option.text }}</span> <span>{{ option.text }}</span>
</div> </div>
{% endfor %} {% endfor %}