Add reading list progress percent

This commit is contained in:
2026-05-08 06:43:38 -04:00
parent 8dd610fec3
commit bae3c7789f
8 changed files with 169 additions and 15 deletions
+3
View File
@@ -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 },
+1 -1
View File
@@ -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,
+51 -5
View File
@@ -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() })
);
}
}