Add reading list progress percent
This commit is contained in:
@@ -29,6 +29,9 @@ pub enum DomainError {
|
||||
#[error("download progress {received_bytes} exceeds total {total_bytes}")]
|
||||
InvalidDownloadProgress { received_bytes: u64, total_bytes: u64 },
|
||||
|
||||
#[error("invalid reading progress percent: {value}")]
|
||||
InvalidReadingProgressPercent { value: String },
|
||||
|
||||
#[error("invalid plugin manifest: {reason}")]
|
||||
InvalidPluginManifest { reason: String },
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ pub use plugin::{
|
||||
};
|
||||
pub use privacy::HistoryRecordingPolicy;
|
||||
pub use profile::{Profile, ProfileKind, ProfileSyncPolicy};
|
||||
pub use reading_list::{ReadingListEntry, ReadingProgress};
|
||||
pub use reading_list::{ReadingListEntry, ReadingProgress, ReadingProgressPercent};
|
||||
pub use search::SearchEngine;
|
||||
pub use site_permission::{
|
||||
SiteOrigin, SitePermissionAuditAction, SitePermissionAuditEvent, SitePermissionDecision,
|
||||
|
||||
@@ -2,25 +2,44 @@ use std::time::SystemTime;
|
||||
|
||||
use crate::{DomainError, ProfileId, ReadingListId, SpaceId, UrlText};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct ReadingProgressPercent(u8);
|
||||
|
||||
impl ReadingProgressPercent {
|
||||
pub fn new(value: u8) -> Result<Self, DomainError> {
|
||||
if !(1..=99).contains(&value) {
|
||||
return Err(DomainError::InvalidReadingProgressPercent { value: value.to_string() });
|
||||
}
|
||||
Ok(Self(value))
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn value(self) -> u8 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum ReadingProgress {
|
||||
Unread,
|
||||
InProgress(ReadingProgressPercent),
|
||||
Finished,
|
||||
}
|
||||
|
||||
impl ReadingProgress {
|
||||
#[must_use]
|
||||
pub fn label(self) -> &'static str {
|
||||
pub fn label(self) -> String {
|
||||
match self {
|
||||
Self::Unread => "Unread",
|
||||
Self::Finished => "Read",
|
||||
Self::Unread => "Unread".to_string(),
|
||||
Self::InProgress(percent) => format!("{}% read", percent.value()),
|
||||
Self::Finished => "Read".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn action_label(self) -> &'static str {
|
||||
match self {
|
||||
Self::Unread => "Mark Read",
|
||||
Self::Unread | Self::InProgress(_) => "Mark Read",
|
||||
Self::Finished => "Mark Unread",
|
||||
}
|
||||
}
|
||||
@@ -28,7 +47,7 @@ impl ReadingProgress {
|
||||
#[must_use]
|
||||
pub fn toggled(self) -> Self {
|
||||
match self {
|
||||
Self::Unread => Self::Finished,
|
||||
Self::Unread | Self::InProgress(_) => Self::Finished,
|
||||
Self::Finished => Self::Unread,
|
||||
}
|
||||
}
|
||||
@@ -118,3 +137,30 @@ fn non_empty_text(field: &'static str, value: String) -> Result<String, DomainEr
|
||||
}
|
||||
Ok(trimmed.to_string())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{ReadingProgress, ReadingProgressPercent};
|
||||
use crate::DomainError;
|
||||
|
||||
#[test]
|
||||
fn reading_progress_percent_accepts_partial_progress() -> Result<(), DomainError> {
|
||||
let percent = ReadingProgressPercent::new(42)?;
|
||||
|
||||
assert_eq!(percent.value(), 42);
|
||||
assert_eq!(ReadingProgress::InProgress(percent).label(), "42% read");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reading_progress_percent_rejects_terminal_values() {
|
||||
assert_eq!(
|
||||
ReadingProgressPercent::new(0),
|
||||
Err(DomainError::InvalidReadingProgressPercent { value: "0".to_string() })
|
||||
);
|
||||
assert_eq!(
|
||||
ReadingProgressPercent::new(100),
|
||||
Err(DomainError::InvalidReadingProgressPercent { value: "100".to_string() })
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user