feat: more stuff

This commit is contained in:
Strix 2024-03-05 18:17:01 +01:00
parent c83273e4da
commit dae1b6f190
No known key found for this signature in database
GPG key ID: 5F35B3B8537287A7
10 changed files with 164 additions and 50 deletions

19
Cargo.lock generated
View file

@ -554,6 +554,9 @@ name = "bitflags"
version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
dependencies = [
"serde",
]
[[package]]
name = "block"
@ -936,9 +939,12 @@ version = "0.1.0"
dependencies = [
"chrono",
"eframe",
"egui",
"egui_extras",
"env_logger",
"reqwest",
"serde",
"serde_json",
]
[[package]]
@ -1047,6 +1053,7 @@ dependencies = [
"epaint",
"log",
"nohash-hasher",
"ron",
"serde",
]
@ -2740,6 +2747,18 @@ dependencies = [
"winreg",
]
[[package]]
name = "ron"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94"
dependencies = [
"base64",
"bitflags 2.4.2",
"serde",
"serde_derive",
]
[[package]]
name = "rustc-demangle"
version = "0.1.23"

View file

@ -8,6 +8,7 @@ publish = false
[dependencies]
chrono = "0.4.34"
egui = { version = "0.26.2", features = ["persistence"] }
eframe = { version = "0.26.2", features = [
"default",
"__screenshot", # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO
@ -21,3 +22,5 @@ env_logger = { version = "0.11.2", default-features = false, features = [
"humantime",
] }
reqwest = { version = "0.11.24", features = ["blocking"] }
serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.114"

View file

@ -6,13 +6,24 @@ use eframe::{
App,
};
use crate::prelude::CanonicalName;
#[derive(Default)]
pub struct ClockWidget;
impl CanonicalName for ClockWidget {
fn canonical_name() -> String {
"Clock".into()
}
}
impl App for ClockWidget {
fn update(&mut self, ctx: &eframe::egui::Context, frame: &mut eframe::Frame) {
Window::new("Clock")
.title_bar(false)
.resizable(false)
.movable(true)
.open(&mut true)
.show(ctx, |ui| {
ui.label(
RichText::new(Local::now().format("%H:%M:%S").to_string())

View file

@ -1,3 +1,4 @@
pub mod uptime;
pub mod greeting;
pub mod clock;
pub mod clock;
pub mod todo;

39
src/apps/todo.rs Normal file
View file

@ -0,0 +1,39 @@
use eframe::WindowBuilder;
use egui::{Key, Window};
use crate::prelude::CanonicalName;
#[derive(Default)]
pub struct TodoWidget {
todos: Vec<(String, bool)>,
_goal_input_cache: String,
}
impl CanonicalName for TodoWidget {
fn canonical_name() -> String {
"Todos".into()
}
}
impl eframe::App for TodoWidget {
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
Window::new("Todos").show(ctx, |ui| {
self.todos.sort_by_key(|a| !a.1);
self.todos.retain_mut(|t| {
ui.horizontal(|ui| {
ui.checkbox(&mut t.1, t.0.clone());
!ui.button("remove").clicked()
})
.inner
});
ui.horizontal(|ui| {
ui.text_edit_singleline(&mut self._goal_input_cache);
if ctx.input(|i| i.key_pressed(Key::Enter)) || ui.button("add").clicked() {
self.todos.push((self._goal_input_cache.clone(), false));
self._goal_input_cache = String::default();
}
});
});
}
}

View file

@ -1,13 +1,17 @@
use eframe::egui::{Color32, Context, Label, Response, Ui, Widget};
use chrono::Local;
use eframe::egui::{Color32, Context, Label, Response, RichText, Ui, Widget};
use eframe::{egui, Frame};
use reqwest::Url;
use serde::{Deserialize, Serialize};
use std::default;
use std::ops::Sub;
use std::str::FromStr;
use std::time::{Duration, Instant};
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
use crate::prelude::CanonicalName;
#[derive(Serialize, Deserialize)]
pub struct MonitorTarget {
url: String,
last_update: Instant,
last_update: u128,
last_status: bool,
}
@ -16,14 +20,14 @@ impl MonitorTarget {
MonitorTarget {
url: url.into(),
last_status: false,
last_update: Instant::now().sub(Duration::new(30, 0)),
last_update: Local::now().timestamp_millis() as u128,
}
}
pub fn check(&mut self) -> bool {
if self.last_update.elapsed().as_secs() > 30 {
if (Local::now().timestamp_millis() as u128 - self.last_update) > 30 {
self.last_status = reqwest::blocking::get(self.url.as_str()).is_ok();
self.last_update = Instant::now();
self.last_update = Local::now().timestamp_millis() as u128;
}
self.last_status
}
@ -35,36 +39,63 @@ pub struct UptimeWidget {
_url_input_cache: String,
}
impl eframe::App for UptimeWidget {
fn update(&mut self, ctx: &Context, frame: &mut Frame) {
egui::Window::new("Uptime Widget").show(ctx, |ui| {
self.targets.retain_mut(|target| {
ui.horizontal(|ui| {
ui.label(target.url.clone());
ui.label({
if target.check() {
format!("OK ({}s ago)", target.last_update.elapsed().as_secs())
} else {
format!("FAIL ({}s ago)", target.last_update.elapsed().as_secs())
}
});
!ui.button("x").clicked()
})
.inner
});
ui.horizontal(|ui| {
ui.text_edit_singleline(&mut self._url_input_cache)
.on_hover_text("URL to add");
if ui.button("Add URL").clicked() {
self.targets
.push(MonitorTarget::new(self._url_input_cache.clone()));
self._url_input_cache = String::default();
}
});
if ui.is_visible() {
ctx.request_repaint();
}
});
impl CanonicalName for UptimeWidget {
fn canonical_name() -> String {
"Uptimes".into()
}
}
impl eframe::App for UptimeWidget {
fn update(&mut self, ctx: &Context, frame: &mut Frame) {
egui::Window::new("Uptime Settings")
.default_open(false)
.show(ctx, |ui| {
self.targets.retain(|t| {
ui.add_space(1.);
ui.horizontal(|ui| {
ui.style_mut().visuals.extreme_bg_color = Color32::DARK_GRAY;
ui.label(t.url.clone());
!ui.button("remove").clicked()
})
.inner
});
ui.add_space(2.);
ui.horizontal(|ui| {
ui.text_edit_singleline(&mut self._url_input_cache)
.on_hover_text("URL to add");
if ui.button("Add URL").clicked() {
self.targets
.push(MonitorTarget::new(self._url_input_cache.clone()));
self._url_input_cache = String::default();
}
});
});
self.targets.iter_mut().for_each(|t| {
egui::Window::new(t.url.clone())
.title_bar(false)
.movable(true)
.resizable(true)
.show(ctx, |ui| {
ui.vertical_centered(|ui| {
ui.label(t.url.clone());
ui.label({
if ctx.is_using_pointer() {
RichText::new("...")
} else if t.check() {
RichText::new("Up").color(Color32::LIGHT_GREEN)
} else {
RichText::new("Down")
.color(Color32::LIGHT_RED)
.strong()
}.size(32.)
});
});
});
});
if self.targets.len() > 0 {
ctx.request_repaint();
}
}
}

View file

@ -2,11 +2,14 @@ use std::collections::HashMap;
use crate::apps::clock::ClockWidget;
use crate::apps::greeting::Greeting;
use crate::apps::todo::TodoWidget;
use crate::apps::uptime::UptimeWidget;
use crate::prelude::CanonicalName;
use eframe::egui::accesskit::Role::Window;
use eframe::egui::panel::Side;
use eframe::egui::{CentralPanel, Id, SidePanel};
use eframe::{egui, App};
use serde::{Deserialize, Serialize};
#[derive(Default)]
pub struct Dashboard {
@ -29,16 +32,16 @@ impl Dashboard {
}
macro_rules! register_app {
($dash:ident, $ui:ident, $name:literal, $app:expr) => {
let button = $ui.button($name);
($dash:ident, $ui:ident, $app:tt) => {
let button = $ui.button($app::canonical_name());
if button.clicked() {
if $dash.has_app($name) {
$dash.remove_app($name);
if $dash.has_app($app::canonical_name()) {
$dash.remove_app($app::canonical_name());
} else {
$dash.add_app($name, Box::new($app));
$dash.add_app($app::canonical_name(), Box::new($app::default()));
}
}
if $dash.has_app($name) {
if $dash.has_app($app::canonical_name()) {
button.highlight();
}
};
@ -48,12 +51,13 @@ impl eframe::App for Dashboard {
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
SidePanel::new(Side::Left, Id::new("side_panel")).show(ctx, |ui| {
ui.heading("Apps");
register_app!(self, ui, "Clock", ClockWidget);
register_app!(self, ui, "Uptime Widget", UptimeWidget::default());
register_app!(self, ui, ClockWidget);
register_app!(self, ui, UptimeWidget);
register_app!(self, ui, TodoWidget);
});
CentralPanel::default().show(ctx, |ui| {});
CentralPanel::default().show(ctx, |_| {});
self.apps.iter_mut().for_each(|(_, app)| {
app.update(ctx, frame);
})
}
}
}

View file

@ -7,9 +7,11 @@ use dashboard::Dashboard;
use eframe::egui;
use std::ops::Sub;
use std::time::{Duration, Instant};
use crate::prelude::CanonicalName;
mod apps;
mod dashboard;
pub mod prelude;
fn main() -> Result<(), eframe::Error> {
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).

3
src/prelude.rs Normal file
View file

@ -0,0 +1,3 @@
pub trait CanonicalName {
fn canonical_name() -> String;
}

1
todo.txt Normal file
View file

@ -0,0 +1 @@
persistance