diff --git a/crates/ely_app/src/shell/chrome/home/hero.rs b/crates/ely_app/src/shell/chrome/home/hero.rs index 1ef6d91..d7f9a66 100644 --- a/crates/ely_app/src/shell/chrome/home/hero.rs +++ b/crates/ely_app/src/shell/chrome/home/hero.rs @@ -12,21 +12,28 @@ use crate::shell::chrome::SERIF_FAMILY; use super::style::{ ARROW_CHIP_BG, PILL_BG, PILL_BG_HOVER, SEARCH_BG, card_shadow, soft_shadow, }; +use super::time::DayPhase; -pub(crate) fn render_hero(greeting: String, cx: &mut Context) -> AnyElement { +pub(crate) fn render_hero( + greeting: String, + phase: DayPhase, + cx: &mut Context, +) -> AnyElement { div() .flex() .flex_col() .items_center() .gap(px(14.0)) - .child(render_greeting_row(greeting)) + .child(render_greeting_row(greeting, phase)) .child(render_serif_headline()) .child(render_search_bar(cx)) .child(render_suggestion_pills(cx)) .into_any_element() } -fn render_greeting_row(text: String) -> AnyElement { +fn render_greeting_row(text: String, phase: DayPhase) -> AnyElement { + let (icon, color) = phase_glyph(phase); + div() .flex() .items_center() @@ -35,13 +42,25 @@ fn render_greeting_row(text: String) -> AnyElement { .text_color(rgb(colors::INK_3)) .child( div() - .text_color(rgb(colors::ACCENT_LIGHT)) - .child(IconName::Sun), + .text_color(rgb(color)) + .child(icon), ) .child(text) .into_any_element() } +/// Pair the greeting glyph to the time of day. Morning gets the warm +/// horizon orange the design uses for the Sunrise icon (#e89a6e); afternoon +/// keeps the same Sun glyph in a higher-key amber; evening swaps to the +/// Moon in the cool slate-violet that bookends the wallpaper themes. +fn phase_glyph(phase: DayPhase) -> (IconName, u32) { + match phase { + DayPhase::Morning => (IconName::Sun, 0xe89a6e), + DayPhase::Afternoon => (IconName::Sun, 0xf5b563), + DayPhase::Evening => (IconName::Moon, 0x7c6cf7), + } +} + fn render_serif_headline() -> AnyElement { div() .font_family(SERIF_FAMILY) @@ -117,11 +136,11 @@ fn render_suggestion_pills(cx: &mut Context) -> AnyElement { |shell, window, cx| shell.cycle_to_next_space(window, cx), )) .child(render_pill( - "pill-open-history", - IconName::Undo2, - "Open History", + "pill-open-notion", + IconName::BookOpen, + "Open Notion", cx, - |shell, window, cx| shell.open_internal_tab("ely://history", window, cx), + |shell, window, cx| shell.open_internal_tab("https://www.notion.so", window, cx), )) .into_any_element() } diff --git a/crates/ely_app/src/shell/chrome/home/mod.rs b/crates/ely_app/src/shell/chrome/home/mod.rs index dde4dba..8a0d2a3 100644 --- a/crates/ely_app/src/shell/chrome/home/mod.rs +++ b/crates/ely_app/src/shell/chrome/home/mod.rs @@ -17,7 +17,9 @@ pub(crate) fn render_home_page( snapshot: &BrowserSnapshot, cx: &mut Context, ) -> AnyElement { - let greeting = time::greeting_for_now(SystemTime::now(), &snapshot.active_profile_name); + let now = SystemTime::now(); + let greeting = time::greeting_for_now(now, &snapshot.active_profile_name); + let phase = time::day_phase_for(now); div() .flex_1() @@ -31,7 +33,7 @@ pub(crate) fn render_home_page( .pb(px(28.0)) .flex() .flex_col() - .child(hero::render_hero(greeting, cx)) + .child(hero::render_hero(greeting, phase, cx)) .child(div().mt(px(48.0)).child(favorites::render_favorites_grid(snapshot, cx))) .child(div().mt(px(16.0)).child(recap::render_recap(snapshot, cx))), ) diff --git a/crates/ely_app/src/shell/chrome/home/time.rs b/crates/ely_app/src/shell/chrome/home/time.rs index adf602e..0b49f5d 100644 --- a/crates/ely_app/src/shell/chrome/home/time.rs +++ b/crates/ely_app/src/shell/chrome/home/time.rs @@ -1,15 +1,43 @@ use std::time::{SystemTime, UNIX_EPOCH}; -pub(crate) fn greeting_for_now(now: SystemTime, name: &str) -> String { - let phase = match now.duration_since(UNIX_EPOCH) { - Ok(duration) => { - let local_seconds = duration.as_secs() as i64; - let day_seconds = local_seconds.rem_euclid(86_400); - let hour = (day_seconds / 3_600) as u32; - day_phase(hour) +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub(crate) enum DayPhase { + Morning, + Afternoon, + Evening, +} + +impl DayPhase { + fn as_str(self) -> &'static str { + match self { + DayPhase::Morning => "morning", + DayPhase::Afternoon => "afternoon", + DayPhase::Evening => "evening", } - Err(_) => "today", + } +} + +pub(crate) fn day_phase_for(now: SystemTime) -> DayPhase { + let hour = match now.duration_since(UNIX_EPOCH) { + Ok(duration) => { + let day_seconds = (duration.as_secs() as i64).rem_euclid(86_400); + (day_seconds / 3_600) as u32 + } + Err(_) => 12, }; + day_phase_from_hour(hour) +} + +pub(crate) fn day_phase_from_hour(hour_utc: u32) -> DayPhase { + match hour_utc { + 5..=11 => DayPhase::Morning, + 12..=17 => DayPhase::Afternoon, + _ => DayPhase::Evening, + } +} + +pub(crate) fn greeting_for_now(now: SystemTime, name: &str) -> String { + let phase = day_phase_for(now).as_str(); if name.is_empty() { format!("Good {phase}") @@ -18,13 +46,6 @@ pub(crate) fn greeting_for_now(now: SystemTime, name: &str) -> String { } } -pub(crate) fn day_phase(hour_utc: u32) -> &'static str { - match hour_utc { - 5..=11 => "morning", - 12..=17 => "afternoon", - _ => "evening", - } -} pub(crate) fn relative_time_label(now: SystemTime, then: SystemTime) -> String { let elapsed = match now.duration_since(then) { @@ -53,22 +74,22 @@ pub(crate) fn relative_time_label(now: SystemTime, then: SystemTime) -> String { #[cfg(test)] mod tests { - use super::{day_phase, greeting_for_now, relative_time_label}; + use super::{DayPhase, day_phase_from_hour, greeting_for_now, relative_time_label}; use std::time::{Duration, UNIX_EPOCH}; #[test] fn day_phase_assigns_morning_to_seven_am() { - assert_eq!(day_phase(7), "morning"); + assert_eq!(day_phase_from_hour(7), DayPhase::Morning); } #[test] fn day_phase_assigns_afternoon_to_one_pm() { - assert_eq!(day_phase(13), "afternoon"); + assert_eq!(day_phase_from_hour(13), DayPhase::Afternoon); } #[test] fn day_phase_assigns_evening_to_eleven_pm() { - assert_eq!(day_phase(23), "evening"); + assert_eq!(day_phase_from_hour(23), DayPhase::Evening); } #[test]