mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-07-08 14:05:10 +02:00
feat(bar): add changing icons based on the time
This commit adds a little Easter egg on the time widget. Use the `changing_icon` setting to enable this feature. Based on the current time, the widget will use different icons to indicate certain activities of the day. 00:00 MOON 06:00 ALARM 06:01 BREAD 06:30 BARBELL 08:00 COFFEE 08:30 CLOCK 12:00 HAMBURGER 12:30 CLOCK_AFTERNOON 18:00 FORK_KNIFE 18:30 MOON_STARS
This commit is contained in:
Generated
+1
@@ -2729,6 +2729,7 @@ dependencies = [
|
|||||||
"image",
|
"image",
|
||||||
"komorebi-client",
|
"komorebi-client",
|
||||||
"komorebi-themes",
|
"komorebi-themes",
|
||||||
|
"lazy_static",
|
||||||
"netdev",
|
"netdev",
|
||||||
"num",
|
"num",
|
||||||
"num-derive",
|
"num-derive",
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ egui-phosphor = "0.9"
|
|||||||
font-loader = "0.11"
|
font-loader = "0.11"
|
||||||
hotwatch = { workspace = true }
|
hotwatch = { workspace = true }
|
||||||
image = "0.25"
|
image = "0.25"
|
||||||
|
lazy_static = { workspace = true }
|
||||||
netdev = "0.32"
|
netdev = "0.32"
|
||||||
num = "0.4"
|
num = "0.4"
|
||||||
num-derive = "0.4"
|
num-derive = "0.4"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use crate::config::LabelPrefix;
|
|||||||
use crate::render::RenderConfig;
|
use crate::render::RenderConfig;
|
||||||
use crate::selected_frame::SelectableFrame;
|
use crate::selected_frame::SelectableFrame;
|
||||||
use crate::widget::BarWidget;
|
use crate::widget::BarWidget;
|
||||||
|
use chrono::Local;
|
||||||
use chrono_tz::Tz;
|
use chrono_tz::Tz;
|
||||||
use eframe::egui::text::LayoutJob;
|
use eframe::egui::text::LayoutJob;
|
||||||
use eframe::egui::Align;
|
use eframe::egui::Align;
|
||||||
@@ -39,7 +40,7 @@ impl CustomModifiers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get the strftime value of modifier
|
// get the strftime value of modifier
|
||||||
let formatted_modifier = chrono::Local::now().format(modifier).to_string();
|
let formatted_modifier = Local::now().format(modifier).to_string();
|
||||||
|
|
||||||
// find the gotten value in the original output
|
// find the gotten value in the original output
|
||||||
if let Some(pos) = modified_output.find(&formatted_modifier) {
|
if let Some(pos) = modified_output.find(&formatted_modifier) {
|
||||||
@@ -143,7 +144,7 @@ impl Date {
|
|||||||
fn output(&mut self) -> String {
|
fn output(&mut self) -> String {
|
||||||
let formatted = match &self.timezone {
|
let formatted = match &self.timezone {
|
||||||
Some(timezone) => match timezone.parse::<Tz>() {
|
Some(timezone) => match timezone.parse::<Tz>() {
|
||||||
Ok(tz) => chrono::Local::now()
|
Ok(tz) => Local::now()
|
||||||
.with_timezone(&tz)
|
.with_timezone(&tz)
|
||||||
.format(&self.format.fmt_string())
|
.format(&self.format.fmt_string())
|
||||||
.to_string()
|
.to_string()
|
||||||
@@ -151,7 +152,7 @@ impl Date {
|
|||||||
.to_string(),
|
.to_string(),
|
||||||
Err(_) => format!("Invalid timezone: {}", timezone),
|
Err(_) => format!("Invalid timezone: {}", timezone),
|
||||||
},
|
},
|
||||||
None => chrono::Local::now()
|
None => Local::now()
|
||||||
.format(&self.format.fmt_string())
|
.format(&self.format.fmt_string())
|
||||||
.to_string()
|
.to_string()
|
||||||
.trim()
|
.trim()
|
||||||
|
|||||||
+104
-24
@@ -3,6 +3,8 @@ use crate::config::LabelPrefix;
|
|||||||
use crate::render::RenderConfig;
|
use crate::render::RenderConfig;
|
||||||
use crate::selected_frame::SelectableFrame;
|
use crate::selected_frame::SelectableFrame;
|
||||||
use crate::widget::BarWidget;
|
use crate::widget::BarWidget;
|
||||||
|
use chrono::Local;
|
||||||
|
use chrono::NaiveTime;
|
||||||
use chrono_tz::Tz;
|
use chrono_tz::Tz;
|
||||||
use eframe::egui::text::LayoutJob;
|
use eframe::egui::text::LayoutJob;
|
||||||
use eframe::egui::Align;
|
use eframe::egui::Align;
|
||||||
@@ -15,9 +17,57 @@ use eframe::egui::TextFormat;
|
|||||||
use eframe::egui::Ui;
|
use eframe::egui::Ui;
|
||||||
use eframe::egui::Vec2;
|
use eframe::egui::Vec2;
|
||||||
use eframe::epaint::StrokeKind;
|
use eframe::epaint::StrokeKind;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref TIME_RANGES: Vec<(&'static str, NaiveTime)> = {
|
||||||
|
vec![
|
||||||
|
(
|
||||||
|
egui_phosphor::regular::MOON,
|
||||||
|
NaiveTime::from_hms_opt(0, 0, 0).expect("invalid"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
egui_phosphor::regular::ALARM,
|
||||||
|
NaiveTime::from_hms_opt(6, 0, 0).expect("invalid"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
egui_phosphor::regular::BREAD,
|
||||||
|
NaiveTime::from_hms_opt(6, 1, 0).expect("invalid"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
egui_phosphor::regular::BARBELL,
|
||||||
|
NaiveTime::from_hms_opt(6, 30, 0).expect("invalid"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
egui_phosphor::regular::COFFEE,
|
||||||
|
NaiveTime::from_hms_opt(8, 0, 0).expect("invalid"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
egui_phosphor::regular::CLOCK,
|
||||||
|
NaiveTime::from_hms_opt(8, 30, 0).expect("invalid"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
egui_phosphor::regular::HAMBURGER,
|
||||||
|
NaiveTime::from_hms_opt(12, 0, 0).expect("invalid"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
egui_phosphor::regular::CLOCK_AFTERNOON,
|
||||||
|
NaiveTime::from_hms_opt(12, 30, 0).expect("invalid"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
egui_phosphor::regular::FORK_KNIFE,
|
||||||
|
NaiveTime::from_hms_opt(18, 0, 0).expect("invalid"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
egui_phosphor::regular::MOON_STARS,
|
||||||
|
NaiveTime::from_hms_opt(18, 30, 0).expect("invalid"),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||||
pub struct TimeConfig {
|
pub struct TimeConfig {
|
||||||
@@ -40,6 +90,8 @@ pub struct TimeConfig {
|
|||||||
///}
|
///}
|
||||||
/// ```
|
/// ```
|
||||||
pub timezone: Option<String>,
|
pub timezone: Option<String>,
|
||||||
|
/// Change the icon depending on the time. The default icon is used between 8:30 and 12:00. (default: false)
|
||||||
|
pub changing_icon: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<TimeConfig> for Time {
|
impl From<TimeConfig> for Time {
|
||||||
@@ -49,6 +101,7 @@ impl From<TimeConfig> for Time {
|
|||||||
format: value.format,
|
format: value.format,
|
||||||
label_prefix: value.label_prefix.unwrap_or(LabelPrefix::Icon),
|
label_prefix: value.label_prefix.unwrap_or(LabelPrefix::Icon),
|
||||||
timezone: value.timezone,
|
timezone: value.timezone,
|
||||||
|
changing_icon: value.changing_icon.unwrap_or_default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,26 +157,55 @@ pub struct Time {
|
|||||||
pub format: TimeFormat,
|
pub format: TimeFormat,
|
||||||
label_prefix: LabelPrefix,
|
label_prefix: LabelPrefix,
|
||||||
timezone: Option<String>,
|
timezone: Option<String>,
|
||||||
|
changing_icon: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Time {
|
impl Time {
|
||||||
fn output(&mut self) -> String {
|
fn output(&mut self) -> (String, String) {
|
||||||
match &self.timezone {
|
let (formatted, current_time) = match &self.timezone {
|
||||||
Some(timezone) => match timezone.parse::<Tz>() {
|
Some(timezone) => match timezone.parse::<Tz>() {
|
||||||
Ok(tz) => chrono::Local::now()
|
Ok(tz) => {
|
||||||
.with_timezone(&tz)
|
let dt = Local::now().with_timezone(&tz);
|
||||||
.format(&self.format.fmt_string())
|
(
|
||||||
.to_string()
|
dt.format(&self.format.fmt_string())
|
||||||
.trim()
|
.to_string()
|
||||||
.to_string(),
|
.trim()
|
||||||
Err(_) => format!("Invalid timezone: {}", timezone),
|
.to_string(),
|
||||||
|
Some(dt.time()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Err(_) => (format!("Invalid timezone: {:?}", timezone), None),
|
||||||
},
|
},
|
||||||
None => chrono::Local::now()
|
None => {
|
||||||
.format(&self.format.fmt_string())
|
let dt = Local::now();
|
||||||
.to_string()
|
(
|
||||||
.trim()
|
dt.format(&self.format.fmt_string())
|
||||||
.to_string(),
|
.to_string()
|
||||||
|
.trim()
|
||||||
|
.to_string(),
|
||||||
|
Some(dt.time()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if current_time.is_none() {
|
||||||
|
return (
|
||||||
|
formatted,
|
||||||
|
egui_phosphor::regular::WARNING_CIRCLE.to_string(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let current_range = match &self.changing_icon {
|
||||||
|
true => TIME_RANGES
|
||||||
|
.iter()
|
||||||
|
.rev()
|
||||||
|
.find(|&(_, start)| current_time.unwrap() > *start)
|
||||||
|
.cloned(),
|
||||||
|
false => None,
|
||||||
|
}
|
||||||
|
.unwrap_or((egui_phosphor::regular::CLOCK, NaiveTime::default()));
|
||||||
|
|
||||||
|
(formatted, current_range.0.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint_binary_circle(
|
fn paint_binary_circle(
|
||||||
@@ -306,15 +388,13 @@ impl BarWidget for Time {
|
|||||||
fn render(&mut self, ctx: &Context, ui: &mut Ui, config: &mut RenderConfig) {
|
fn render(&mut self, ctx: &Context, ui: &mut Ui, config: &mut RenderConfig) {
|
||||||
if self.enable {
|
if self.enable {
|
||||||
let mut output = self.output();
|
let mut output = self.output();
|
||||||
if !output.is_empty() {
|
if !output.0.is_empty() {
|
||||||
let use_binary_circle = output.starts_with('c');
|
let use_binary_circle = output.0.starts_with('c');
|
||||||
let use_binary_rectangle = output.starts_with('r');
|
let use_binary_rectangle = output.0.starts_with('r');
|
||||||
|
|
||||||
let mut layout_job = LayoutJob::simple(
|
let mut layout_job = LayoutJob::simple(
|
||||||
match self.label_prefix {
|
match self.label_prefix {
|
||||||
LabelPrefix::Icon | LabelPrefix::IconAndText => {
|
LabelPrefix::Icon | LabelPrefix::IconAndText => output.1,
|
||||||
egui_phosphor::regular::CLOCK.to_string()
|
|
||||||
}
|
|
||||||
LabelPrefix::None | LabelPrefix::Text => String::new(),
|
LabelPrefix::None | LabelPrefix::Text => String::new(),
|
||||||
},
|
},
|
||||||
config.icon_font_id.clone(),
|
config.icon_font_id.clone(),
|
||||||
@@ -323,12 +403,12 @@ impl BarWidget for Time {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if let LabelPrefix::Text | LabelPrefix::IconAndText = self.label_prefix {
|
if let LabelPrefix::Text | LabelPrefix::IconAndText = self.label_prefix {
|
||||||
output.insert_str(0, "TIME: ");
|
output.0.insert_str(0, "TIME: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
if !use_binary_circle && !use_binary_rectangle {
|
if !use_binary_circle && !use_binary_rectangle {
|
||||||
layout_job.append(
|
layout_job.append(
|
||||||
&output,
|
&output.0,
|
||||||
10.0,
|
10.0,
|
||||||
TextFormat {
|
TextFormat {
|
||||||
font_id: config.text_font_id.clone(),
|
font_id: config.text_font_id.clone(),
|
||||||
@@ -351,9 +431,9 @@ impl BarWidget for Time {
|
|||||||
|
|
||||||
if use_binary_circle || use_binary_rectangle {
|
if use_binary_circle || use_binary_rectangle {
|
||||||
let ordered_output = if is_reversed {
|
let ordered_output = if is_reversed {
|
||||||
output.chars().rev().collect()
|
output.0.chars().rev().collect()
|
||||||
} else {
|
} else {
|
||||||
output
|
output.0
|
||||||
};
|
};
|
||||||
|
|
||||||
for (section_index, section) in
|
for (section_index, section) in
|
||||||
|
|||||||
@@ -896,6 +896,10 @@
|
|||||||
"format"
|
"format"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"changing_icon": {
|
||||||
|
"description": "Change the icon depending on the time. The default icon is used between 8:30 and 12:00. (default: false)",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"enable": {
|
"enable": {
|
||||||
"description": "Enable the Time widget",
|
"description": "Enable the Time widget",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
@@ -2302,6 +2306,10 @@
|
|||||||
"format"
|
"format"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"changing_icon": {
|
||||||
|
"description": "Change the icon depending on the time. The default icon is used between 8:30 and 12:00. (default: false)",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"enable": {
|
"enable": {
|
||||||
"description": "Enable the Time widget",
|
"description": "Enable the Time widget",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
@@ -3641,6 +3649,10 @@
|
|||||||
"format"
|
"format"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"changing_icon": {
|
||||||
|
"description": "Change the icon depending on the time. The default icon is used between 8:30 and 12:00. (default: false)",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
"enable": {
|
"enable": {
|
||||||
"description": "Enable the Time widget",
|
"description": "Enable the Time widget",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
|||||||
Reference in New Issue
Block a user