use std::{ collections::{BTreeMap, BTreeSet}, path::PathBuf, }; pub use gotcha_gitea::{ HistoryCommit, HomeData, IssueDetails, IssueEditorData, MilestoneDetails, Page, PullDetails, civil_from_days, days_from_civil, parse_api_date, }; use serde::{Deserialize, Serialize}; #[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)] #[serde(rename_all = "lowercase")] pub enum AppearanceMode { Light, Dark, #[default] #[serde(other)] Auto, } impl AppearanceMode { pub fn index(self) -> i32 { match self { Self::Auto => 0, Self::Light => 1, Self::Dark => 2, } } pub fn from_index(index: i32) -> Option { match index { 0 => Some(Self::Auto), 1 => Some(Self::Light), 2 => Some(Self::Dark), _ => None, } } } #[derive(Clone, Deserialize, Serialize)] pub struct Server { pub name: String, pub url: String, #[serde(default)] pub provider: gotcha_gitea::Provider, #[serde(default)] pub credential_account: String, #[serde(skip)] pub token: String, } #[derive(Clone, Deserialize, Serialize)] pub struct Preferences { #[serde(skip)] pub path: PathBuf, #[serde(default)] pub servers: Vec, #[serde(default)] pub favorites: BTreeSet, #[serde(default)] pub last_server: Option, #[serde(default = "open_status")] pub issue_status: String, #[serde(default)] pub issue_filters: BTreeMap, #[serde(default = "open_status")] pub pull_status: String, #[serde(default)] pub pull_filters: BTreeMap, #[serde(default)] pub appearance: AppearanceMode, #[serde(default)] pub notifications_enabled: bool, #[serde(default)] pub notification_cursors: BTreeMap, } impl Default for Preferences { fn default() -> Self { Self { path: PathBuf::new(), servers: Vec::new(), favorites: BTreeSet::new(), last_server: None, issue_status: open_status(), issue_filters: BTreeMap::new(), pull_status: open_status(), pull_filters: BTreeMap::new(), appearance: AppearanceMode::default(), notifications_enabled: false, notification_cursors: BTreeMap::new(), } } } #[derive(Clone, Default, Deserialize, Eq, PartialEq, Serialize)] pub struct IssueFilter { #[serde(default)] pub milestone: String, #[serde(default)] pub labels: BTreeSet, #[serde(skip)] pub search_text: String, } impl IssueFilter { pub fn is_active(&self, status: &str) -> bool { status != "open" || self != &Self::default() } } #[derive(Clone, Default, Deserialize, Eq, PartialEq, Serialize)] pub struct PullFilter { #[serde(default)] pub milestone: String, #[serde(skip)] pub search_text: String, } impl PullFilter { pub fn is_active(&self, status: &str) -> bool { status != "open" || self != &Self::default() } } #[derive(Clone)] pub struct RepositoryData { pub owner: String, pub name: String, pub description: String, pub language: String, pub open_issues: i64, pub updated: String, pub default_branch: String, } #[derive(Default)] pub struct State { pub preferences: Preferences, pub active_server: Option, pub repositories: Vec, } pub struct IssueDraft { pub title: String, pub body: String, pub label_ids: Vec, pub milestone_id: Option, pub due_date: Option, pub closed: bool, } pub struct MilestoneDraft { pub title: String, pub description: String, pub due_date: Option, pub closed: bool, } pub fn open_status() -> String { "open".into() } #[cfg(test)] mod tests { use super::*; #[test] fn issue_filter_default_state_is_owned_by_rust() { assert!(!IssueFilter::default().is_active("open")); assert!(IssueFilter::default().is_active("closed")); assert!( IssueFilter { milestone: "v1".into(), ..Default::default() } .is_active("open") ); assert!(!PullFilter::default().is_active("open")); assert!(PullFilter::default().is_active("closed")); assert!( PullFilter { milestone: "v1".into(), ..Default::default() } .is_active("open") ); assert!( IssueFilter { search_text: "needle".into(), ..Default::default() } .is_active("open") ); assert!( PullFilter { search_text: "needle".into(), ..Default::default() } .is_active("open") ); } #[test] fn search_text_is_session_only() { let issue = IssueFilter { search_text: "needle".into(), ..Default::default() }; let pull = PullFilter { search_text: "needle".into(), ..Default::default() }; assert!(!serde_json::to_string(&issue).unwrap().contains("needle")); assert!(!serde_json::to_string(&pull).unwrap().contains("needle")); assert_eq!( serde_json::from_str::(r#"{"milestone":"v1"}"#) .unwrap() .search_text, "" ); } }