Skip to content

Commit

Permalink
Add dark mode
Browse files Browse the repository at this point in the history
  • Loading branch information
treiher committed Jun 23, 2024
1 parent 5ed4d17 commit a001008
Show file tree
Hide file tree
Showing 17 changed files with 194 additions and 33 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Tracking of trained muscles
- Dark mode
- Descriptions of measuring points on body fat page
- Archiving of routines

Expand Down
2 changes: 1 addition & 1 deletion frontend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ serde = "1.0"
serde_json = "1.0"
slice-group-by = "0.3"
wasm-bindgen = "=0.2.80"
web-sys = { version = "0.3", features = ["AudioContext", "AudioDestinationNode", "AudioNode", "AudioParam", "GainNode", "Notification", "NotificationOptions", "NotificationPermission", "OscillatorNode", "ScrollBehavior", "ScrollIntoViewOptions", "ScrollLogicalPosition", "ScrollToOptions", "ServiceWorker", "ServiceWorkerContainer"] }
web-sys = { version = "0.3", features = ["AudioContext", "AudioDestinationNode", "AudioNode", "AudioParam", "GainNode", "MediaQueryList", "Notification", "NotificationOptions", "NotificationPermission", "OscillatorNode", "ScrollBehavior", "ScrollIntoViewOptions", "ScrollLogicalPosition", "ScrollToOptions", "ServiceWorker", "ServiceWorkerContainer", "Window"] }

[dev-dependencies]
assert_approx_eq = "1.1.0"
Expand Down
14 changes: 7 additions & 7 deletions frontend/assets/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,11 @@ input[type=number] {

// Field Set

$fieldset-background-color: bulma.$scheme-main !default;
$fieldset-border-color: bulma.$border !default;
$fieldset-color: bulma.$text-strong !default;
$fieldset-background-color: var(--bulma-scheme-main);
$fieldset-border-color: var(--bulma-border);
$fieldset-color: var(--bulma-text-strong);
$fieldset-padding: 1.5em;
$fieldset-radius: bulma.$radius !default;
$fieldset-radius: var(--bulma-radius);

.fieldset {
background-color: $fieldset-background-color;
Expand All @@ -140,9 +140,9 @@ div.is-calendar {
direction: ltr;
tr {
td {
color: bulma.$white;
background-color: bulma.$grey-lighter;
border: 1px solid bulma.$white;
color: var(--bulma-scheme-main);
background-color: var(--bulma-border);
border: 1px solid var(--bulma-scheme-main);
text-align: center;
div {
width: 10pt;
Expand Down
64 changes: 46 additions & 18 deletions frontend/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,12 @@ pub fn view_dialog<Ms>(
C!["modal-content"],
div![
C!["message"],
C!["has-background-white"],
C![format!("is-{color}")],
C!["mx-2"],
div![
C!["message-body"],
C!["has-text-dark"],
C!["has-text-text-bold"],
C!["has-background-scheme-main"],
div![C!["title"], C![format!("has-text-{color}")], title],
content
]
Expand Down Expand Up @@ -185,7 +185,13 @@ pub fn view_delete_confirmation_dialog<Ms>(
C!["is-grouped-centered"],
div![
C!["control"],
button![C!["button"], C!["is-light"], cancel_event, "No"]
button![
C!["button"],
C!["is-light"],
C!["is-soft"],
cancel_event,
"No"
]
],
div![
C!["control"],
Expand Down Expand Up @@ -470,7 +476,12 @@ pub fn automatic_icon<Ms>() -> Node<Ms> {
St::LineHeight => "1.5em",
},
i![C!["fas fa-circle fa-stack-1x"]],
i![C!["fas fa-a fa-inverse fa-stack-1x"]]
i![
style! {
St::Color => "var(--bulma-scheme-main)",
},
C!["fas fa-a fa-inverse fa-stack-1x"]
]
]
}

Expand Down Expand Up @@ -547,7 +558,7 @@ pub fn view_calendar<Ms>(entries: Vec<(NaiveDate, usize, f64)>, interval: &Inter
}
} else if *date < interval.first || *date > interval.last {
style! {
St::BackgroundColor => "#FFFFFF"
St::BackgroundColor => "var(--bulma-scheme-main)"
}
} else {
style! {}
Expand Down Expand Up @@ -620,6 +631,7 @@ pub fn plot_line_chart(
x_max: NaiveDate,
y_min_opt: Option<f32>,
y_max_opt: Option<f32>,
theme: &data::Theme,
) -> Result<String, Box<dyn std::error::Error>> {
let (y_min, y_max, y_margin) = determine_y_bounds(
data.iter()
Expand All @@ -633,8 +645,9 @@ pub fn plot_line_chart(

{
let root = SVGBackend::with_string(&mut result, (chart_width(), 200)).into_drawing_area();
let (color, background_color) = colors(theme);

root.fill(&WHITE)?;
root.fill(&background_color)?;

let mut chart_builder = ChartBuilder::on(&root);
chart_builder
Expand All @@ -651,8 +664,9 @@ pub fn plot_line_chart(
.configure_mesh()
.disable_x_mesh()
.set_all_tick_mark_size(3u32)
.axis_style(BLACK.mix(0.3))
.light_line_style(WHITE.mix(0.0))
.axis_style(color.mix(0.3))
.light_line_style(color.mix(0.0))
.label_style(&color)
.x_labels(2)
.y_labels(6)
.draw()?;
Expand Down Expand Up @@ -685,6 +699,7 @@ pub fn plot_dual_line_chart(
secondary_data: &[(Vec<(NaiveDate, f32)>, usize)],
x_min: NaiveDate,
x_max: NaiveDate,
theme: &data::Theme,
) -> Result<String, Box<dyn std::error::Error>> {
let (y1_min, y1_max, y1_margin) = determine_y_bounds(
data.iter()
Expand All @@ -706,8 +721,9 @@ pub fn plot_dual_line_chart(

{
let root = SVGBackend::with_string(&mut result, (chart_width(), 200)).into_drawing_area();
let (color, background_color) = colors(theme);

root.fill(&WHITE)?;
root.fill(&background_color)?;

let mut chart = ChartBuilder::on(&root)
.margin(10f32)
Expand All @@ -721,16 +737,17 @@ pub fn plot_dual_line_chart(
.configure_mesh()
.disable_x_mesh()
.set_all_tick_mark_size(3u32)
.axis_style(BLACK.mix(0.3))
.light_line_style(WHITE.mix(0.0))
.axis_style(color.mix(0.3))
.light_line_style(background_color.mix(0.0))
.label_style(&color)
.x_labels(2)
.y_labels(6)
.draw()?;

chart
.configure_secondary_axes()
.set_all_tick_mark_size(3u32)
.axis_style(BLACK.mix(0.3))
.axis_style(color.mix(0.3))
.draw()?;

for (series, color_idx) in secondary_data {
Expand Down Expand Up @@ -780,6 +797,7 @@ pub fn plot_bar_chart(
x_max: NaiveDate,
y_min_opt: Option<f32>,
y_max_opt: Option<f32>,
theme: &data::Theme,
) -> Result<String, Box<dyn std::error::Error>> {
let (y1_min, y1_max, _) = determine_y_bounds(
data.iter()
Expand All @@ -802,8 +820,9 @@ pub fn plot_bar_chart(

{
let root = SVGBackend::with_string(&mut result, (chart_width(), 200)).into_drawing_area();
let (color, background_color) = colors(theme);

root.fill(&WHITE)?;
root.fill(&background_color)?;

let mut chart = ChartBuilder::on(&root)
.margin(10f32)
Expand All @@ -820,16 +839,17 @@ pub fn plot_bar_chart(
.configure_mesh()
.disable_x_mesh()
.set_all_tick_mark_size(3u32)
.axis_style(BLACK.mix(0.3))
.light_line_style(WHITE.mix(0.0))
.axis_style(color.mix(0.3))
.light_line_style(background_color.mix(0.0))
.label_style(&color)
.x_labels(2)
.y_labels(6)
.draw()?;

chart
.configure_secondary_axes()
.set_all_tick_mark_size(3u32)
.axis_style(BLACK.mix(0.3))
.axis_style(color.mix(0.3))
.draw()?;

for (series, color_idx) in data {
Expand Down Expand Up @@ -867,6 +887,14 @@ pub fn plot_bar_chart(
Ok(result)
}

fn colors(theme: &data::Theme) -> (RGBColor, RGBColor) {
let dark = RGBColor(20, 22, 26);
match theme {
data::Theme::System | data::Theme::Light => (dark, WHITE),
data::Theme::Dark => (WHITE, dark),
}
}

fn determine_y_bounds(
y: Vec<f32>,
y_min_opt: Option<f32>,
Expand Down Expand Up @@ -1018,7 +1046,7 @@ where
span![
C!["tag"],
C!["is-hoverable"],
C![if *enabled { "is-link" } else { "is-light" }],
IF![*enabled => C!["is-link"]],
ev(Ev::Click, {
let index = *i;
let filter_changed = filter_changed.clone();
Expand Down Expand Up @@ -1106,7 +1134,7 @@ where
} else if sets > 0.0 {
groups[2].push((name, description, sets_str, vec!["is-light", "is-link"]));
} else {
groups[3].push((name, description, sets_str, vec!["is-light"]));
groups[3].push((name, description, sets_str, vec![]));
}
}
groups
Expand Down
44 changes: 44 additions & 0 deletions frontend/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const STORAGE_KEY_ONGOING_TRAINING_SESSION: &str = "ongoing training session";
pub fn init(url: Url, _orders: &mut impl Orders<Msg>) -> Model {
let settings = gloo_storage::LocalStorage::get(STORAGE_KEY_SETTINGS).unwrap_or(Settings {
beep_volume: 80,
theme: Theme::Light,
automatic_metronome: false,
notifications: false,
});
Expand Down Expand Up @@ -114,6 +115,36 @@ impl Model {
let dates = self.training_sessions.values().map(|t| t.date);
dates.clone().min().unwrap_or_default()..=dates.max().unwrap_or_default()
}

pub fn theme(&self) -> &Theme {
match self.settings.theme {
Theme::System => {
if let Some(window) = web_sys::window() {
if let Ok(prefers_dark_scheme) =
window.match_media("(prefers-color-scheme: dark)")
{
if let Some(media_query_list) = prefers_dark_scheme {
if media_query_list.matches() {
&Theme::Dark
} else {
&Theme::Light
}
} else {
error!("failed to determine preferred color scheme");
&Theme::Light
}
} else {
error!("failed to match media to determine preferred color scheme");
&Theme::Light
}
} else {
error!("failed to access window to determine preferred color scheme");
&Theme::Light
}
}
Theme::Light | Theme::Dark => &self.settings.theme,
}
}
}

fn sort_routines_by_last_use(
Expand Down Expand Up @@ -396,10 +427,18 @@ pub enum TrainingSessionElement {
#[derive(serde::Serialize, serde::Deserialize)]
pub struct Settings {
pub beep_volume: u8,
pub theme: Theme,
pub automatic_metronome: bool,
pub notifications: bool,
}

#[derive(serde::Serialize, serde::Deserialize, Clone, PartialEq)]
pub enum Theme {
System,
Light,
Dark,
}

#[derive(serde::Serialize, serde::Deserialize, Clone)]
pub struct OngoingTrainingSession {
pub training_session_id: u32,
Expand Down Expand Up @@ -1059,6 +1098,7 @@ pub enum Msg {
TrainingSessionDeleted(Result<u32, String>),

SetBeepVolume(u8),
SetTheme(Theme),
SetAutomaticMetronome(bool),
SetNotifications(bool),

Expand Down Expand Up @@ -1919,6 +1959,10 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
local_storage_set(STORAGE_KEY_SETTINGS, &model.settings, &mut model.errors);
orders.notify(Event::BeepVolumeChanged);
}
Msg::SetTheme(theme) => {
model.settings.theme = theme;
local_storage_set(STORAGE_KEY_SETTINGS, &model.settings, &mut model.errors);
}
Msg::SetAutomaticMetronome(value) => {
model.settings.automatic_metronome = value;
local_storage_set(STORAGE_KEY_SETTINGS, &model.settings, &mut model.errors);
Expand Down
Loading

0 comments on commit a001008

Please sign in to comment.