diff --git a/src/app/update/mod.rs b/src/app/update/mod.rs index 6bab75c96..34ebe8e8d 100644 --- a/src/app/update/mod.rs +++ b/src/app/update/mod.rs @@ -2730,12 +2730,17 @@ impl OpenCADStudio { Task::none() } Message::PatronsFetched(Ok(names)) => { - self.patrons = names; + // Merge the hand-maintained supporters and rank everyone by + // amount (also sorts the web list, which arrives unsorted). + self.patrons = crate::patreon::merge_manual(names); + Task::none() + } + // No token / offline: still show any hand-maintained supporters + // (Start page shows a "Support on Patreon" prompt when empty). + Message::PatronsFetched(Err(_)) => { + self.patrons = crate::patreon::merge_manual(Vec::new()); Task::none() } - // No token / offline: leave the list empty (Start page shows a - // "Support on Patreon" prompt instead). - Message::PatronsFetched(Err(_)) => Task::none(), Message::PluginReleasesFetched(repo, Ok(tags)) => { if let Some(first) = tags.first() { self.repo_selected_tag diff --git a/src/patreon.rs b/src/patreon.rs index d2d425d6e..01eba0a61 100644 --- a/src/patreon.rs +++ b/src/patreon.rs @@ -7,6 +7,34 @@ //! can still be extracted from a shipped binary, so it should be a //! campaign-scoped token with the minimum needed access. +/// Supporters who donated outside Patreon (direct transfer, crypto, one-off +/// gifts, …), maintained by hand here. They are merged with the fetched patrons +/// and ranked together by amount, so the combined Start-page list is ordered by +/// pledge regardless of where the donation came from. +/// +/// To add a supporter, add a `("Display name", cents)` line below. The amount is +/// in **cents**: a $25 donation is `2500`, €10 is `1000`. +const MANUAL_SUPPORTERS: &[(&str, i64)] = &[ + ("Stefano", 6000), // $60 +]; + +/// Append the hand-maintained [`MANUAL_SUPPORTERS`] to `patrons` and sort the +/// combined list by amount (highest first, then alphabetically). Both the +/// native and web boot paths funnel their fetched list through here, so the +/// manual entries — and the ranking — are identical on every platform, and the +/// list is still sorted (and still shows the manual entries) even when the +/// fetch returns nothing because the app is offline or has no Patreon token. +pub fn merge_manual(mut patrons: Vec<(String, i64)>) -> Vec<(String, i64)> { + for &(name, cents) in MANUAL_SUPPORTERS { + let name = name.trim(); + if !name.is_empty() { + patrons.push((name.to_string(), cents)); + } + } + patrons.sort_by(|a, b| b.1.cmp(&a.1).then_with(|| a.0.cmp(&b.0))); + patrons +} + #[cfg(not(target_arch = "wasm32"))] const UA: &str = concat!("OpenCADStudio/", env!("CARGO_PKG_VERSION"));