| 684 |
684 |
|
}
|
| 685 |
685 |
|
|
| 686 |
686 |
|
impl RowPart {
|
| 687 |
|
- |
/// Whether the part stays hidden until the row is hovered or focused.
|
| 688 |
|
- |
///
|
| 689 |
|
- |
/// Behaviour of the part, not app policy: Balanced Breakfast and goingson
|
| 690 |
|
- |
/// grew the same hover-reveal on their actions independently and neither
|
| 691 |
|
- |
/// applies it to anything else.
|
| 692 |
|
- |
///
|
| 693 |
|
- |
/// A renderer with no hover shows it always. That is a renderer decision
|
| 694 |
|
- |
/// and this returning `true` does not forbid it.
|
| 695 |
|
- |
#[must_use]
|
| 696 |
|
- |
pub const fn revealed_on_hover(self) -> bool {
|
| 697 |
|
- |
matches!(self, Self::Actions)
|
| 698 |
|
- |
}
|
| 699 |
|
- |
|
| 700 |
687 |
|
/// The content intent the part takes.
|
| 701 |
688 |
|
#[must_use]
|
| 702 |
689 |
|
pub const fn intent(self) -> &'static str {
|
| 1064 |
1051 |
|
pub value: &'a str,
|
| 1065 |
1052 |
|
/// What it counts. The caption under the value.
|
| 1066 |
1053 |
|
pub caption: &'a str,
|
|
1054 |
+ |
/// How the value has moved, if the app is tracking that.
|
|
1055 |
+ |
///
|
|
1056 |
+ |
/// Added 0.13.0. Text, for [`value`](Self::value)'s reason: only the app
|
|
1057 |
+ |
/// knows whether a move reads as `+12.5%`, `+3` or `2x`, and a renderer
|
|
1058 |
+ |
/// handed a number would have to guess.
|
|
1059 |
+ |
///
|
|
1060 |
+ |
/// This is what [`tone`](Self::tone) was for and had no consumer of. The MNW
|
|
1061 |
+ |
/// server has four screens whose stat card is a label, a value and a delta,
|
|
1062 |
+ |
/// and the delta is the toned part: the figure itself is an ordinary fact
|
|
1063 |
+ |
/// and it is the movement that reads as good or bad. Without this the delta
|
|
1064 |
+ |
/// has to be folded into the caption, which loses the tone and reads as a
|
|
1065 |
+ |
/// longer caption rather than as a second, smaller line.
|
|
1066 |
+ |
pub change: Option<&'a str>,
|
| 1067 |
1067 |
|
/// What the figure means right now. [`Tone::Neutral`] is an ordinary fact.
|
|
1068 |
+ |
///
|
|
1069 |
+ |
/// Applies to [`change`](Self::change) where there is one, since that is the
|
|
1070 |
+ |
/// part that carries the judgement, and to the value where there is not.
|
| 1068 |
1071 |
|
pub tone: Tone,
|
| 1069 |
1072 |
|
}
|
| 1070 |
1073 |
|
|
| 1075 |
1078 |
|
Self {
|
| 1076 |
1079 |
|
value,
|
| 1077 |
1080 |
|
caption,
|
|
1081 |
+ |
change: None,
|
| 1078 |
1082 |
|
tone: Tone::Neutral,
|
| 1079 |
1083 |
|
}
|
| 1080 |
1084 |
|
}
|
| 1081 |
1085 |
|
|
|
1086 |
+ |
/// How the value has moved.
|
|
1087 |
+ |
#[must_use]
|
|
1088 |
+ |
pub const fn change(mut self, change: &'a str) -> Self {
|
|
1089 |
+ |
self.change = Some(change);
|
|
1090 |
+ |
self
|
|
1091 |
+ |
}
|
|
1092 |
+ |
|
| 1082 |
1093 |
|
/// What the figure means.
|
| 1083 |
1094 |
|
#[must_use]
|
| 1084 |
1095 |
|
pub const fn tone(mut self, tone: Tone) -> Self {
|
| 1708 |
1719 |
|
assert_eq!(Figure::new("17", "Total").tone, Tone::Neutral);
|
| 1709 |
1720 |
|
}
|
| 1710 |
1721 |
|
|
|
1722 |
+ |
#[test]
|
|
1723 |
+ |
fn a_figures_change_is_the_toned_part_and_is_absent_by_default() {
|
|
1724 |
+ |
// 0.13.0. The MNW server's stat card is a label, a value and a delta,
|
|
1725 |
+ |
// across four screens, and the delta is what reads as good or bad. Tone
|
|
1726 |
+ |
// had no consumer before this: the figure itself is an ordinary fact.
|
|
1727 |
+ |
let views = Figure::new("1,204", "Views")
|
|
1728 |
+ |
.change("+12.5%")
|
|
1729 |
+ |
.tone(Tone::Success);
|
|
1730 |
+ |
assert_eq!(views.change, Some("+12.5%"));
|
|
1731 |
+ |
assert_eq!(views.tone, Tone::Success);
|
|
1732 |
+ |
|
|
1733 |
+ |
// A figure with nothing to compare against says so by having no change,
|
|
1734 |
+ |
// rather than by carrying an empty string a renderer has to test for.
|
|
1735 |
+ |
assert_eq!(Figure::new("3.1%", "Conversion").change, None);
|
|
1736 |
+ |
}
|
|
1737 |
+ |
|
| 1711 |
1738 |
|
#[test]
|
| 1712 |
1739 |
|
fn a_figures_value_is_text_because_only_the_app_knows_what_it_is() {
|
| 1713 |
1740 |
|
// "84%", "12/30", "3d". A figure is whatever the app computed, already
|
| 1723 |
1750 |
|
// The meter carries the tone, so a part-level intent underneath would
|
| 1724 |
1751 |
|
// fight it. Same answer `Tokens` needed, for the same reason.
|
| 1725 |
1752 |
|
assert_eq!(RowPart::Proportion.intent(), RowPart::Tokens.intent());
|
| 1726 |
|
- |
assert!(!RowPart::Proportion.revealed_on_hover());
|
| 1727 |
1753 |
|
}
|
| 1728 |
1754 |
|
|
| 1729 |
1755 |
|
#[test]
|
| 1989 |
2015 |
|
}
|
| 1990 |
2016 |
|
|
| 1991 |
2017 |
|
#[test]
|
| 1992 |
|
- |
fn only_the_actions_part_hides_until_hovered() {
|
| 1993 |
|
- |
for p in [
|
| 1994 |
|
- |
RowPart::Primary,
|
| 1995 |
|
- |
RowPart::Secondary,
|
| 1996 |
|
- |
RowPart::Meta,
|
| 1997 |
|
- |
RowPart::Tokens,
|
| 1998 |
|
- |
] {
|
| 1999 |
|
- |
assert!(!p.revealed_on_hover(), "{p:?} should always be visible");
|
| 2000 |
|
- |
}
|
| 2001 |
|
- |
assert!(RowPart::Actions.revealed_on_hover());
|
| 2002 |
|
- |
// Emphasis falls off down the row, and never rises again.
|
|
2018 |
+ |
fn emphasis_falls_off_down_the_row() {
|
|
2019 |
+ |
// `revealed_on_hover` was asserted here until 0.13.0 retired it. It said
|
|
2020 |
+ |
// a row's actions stay hidden until hover, which stopped being true when
|
|
2021 |
+ |
// makeover-webview 0.23.0 showed them at rest, and nothing had consumed
|
|
2022 |
+ |
// it for a release either way.
|
| 2003 |
2023 |
|
assert_eq!(RowPart::Primary.intent(), "content");
|
| 2004 |
2024 |
|
assert_eq!(RowPart::Secondary.intent(), "content-secondary");
|
| 2005 |
2025 |
|
assert_eq!(RowPart::Meta.intent(), "content-muted");
|