feat: more stuff
This commit is contained in:
parent
c83273e4da
commit
dae1b6f190
10 changed files with 164 additions and 50 deletions
19
Cargo.lock
generated
19
Cargo.lock
generated
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
pub mod uptime;
|
||||
pub mod greeting;
|
||||
pub mod clock;
|
||||
pub mod todo;
|
39
src/apps/todo.rs
Normal file
39
src/apps/todo.rs
Normal 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();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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,23 +39,27 @@ pub struct UptimeWidget {
|
|||
_url_input_cache: String,
|
||||
}
|
||||
|
||||
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 Widget").show(ctx, |ui| {
|
||||
self.targets.retain_mut(|target| {
|
||||
egui::Window::new("Uptime Settings")
|
||||
.default_open(false)
|
||||
.show(ctx, |ui| {
|
||||
self.targets.retain(|t| {
|
||||
ui.add_space(1.);
|
||||
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()
|
||||
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");
|
||||
|
@ -61,10 +69,33 @@ impl eframe::App for UptimeWidget {
|
|||
self._url_input_cache = String::default();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if ui.is_visible() {
|
||||
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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,10 +51,11 @@ 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);
|
||||
})
|
||||
|
|
|
@ -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
3
src/prelude.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
pub trait CanonicalName {
|
||||
fn canonical_name() -> String;
|
||||
}
|
1
todo.txt
Normal file
1
todo.txt
Normal file
|
@ -0,0 +1 @@
|
|||
persistance
|
Loading…
Reference in a new issue