123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- #![allow(dead_code, unused)]
- use dioxus::desktop::use_window;
- use dioxus::prelude::*;
- use std::{
- process::exit,
- time::{Duration, Instant},
- };
- use tokio::time::sleep;
- fn main() {
- dioxus::LaunchBuilder::desktop().launch(app);
- }
- struct WindowPreferences {
- always_on_top: bool,
- with_decorations: bool,
- exiting: Option<Instant>,
- }
- impl Default for WindowPreferences {
- fn default() -> Self {
- Self {
- with_decorations: true,
- always_on_top: false,
- exiting: None,
- }
- }
- }
- impl WindowPreferences {
- fn new() -> Self {
- Self::default()
- }
- }
- #[derive(Default)]
- struct Timer {
- hours: u8,
- minutes: u8,
- seconds: u8,
- started_at: Option<Instant>,
- }
- impl Timer {
- fn new() -> Self {
- Self::default()
- }
- fn duration(&self) -> Duration {
- Duration::from_secs(
- (self.hours as u64 * 60 + self.minutes as u64) * 60 + self.seconds as u64,
- )
- }
- }
- const UPD_FREQ: Duration = Duration::from_millis(100);
- fn exit_button(
- delay: Duration,
- label: fn(Signal<Option<Instant>>, Duration) -> Option<VNode>,
- ) -> Element {
- let mut trigger: Signal<Option<Instant>> = use_signal(|| None);
- use_future(move || async move {
- loop {
- sleep(UPD_FREQ).await;
- if let Some(true) = trigger.read().map(|e| e.elapsed() > delay) {
- exit(0);
- }
- }
- });
- let stuff: Option<VNode> = rsx! {
- button {
- onmouseup: move |_| {
- trigger.set(None);
- },
- onmousedown: move |_| {
- trigger.set(Some(Instant::now()));
- },
- width: 100,
- {label(trigger, delay)}
- }
- };
- stuff
- }
- fn app() -> Element {
- let mut timer = use_signal(Timer::new);
- let mut window_preferences = use_signal(WindowPreferences::new);
- use_future(move || async move {
- loop {
- sleep(UPD_FREQ).await;
- timer.with_mut(|t| {
- if let Some(started_at) = t.started_at {
- if t.duration().saturating_sub(started_at.elapsed()) == Duration::ZERO {
- t.started_at = None;
- }
- }
- });
- }
- });
- rsx! {
- div {
- {
- let millis = timer
- .with(|t| {
- t.duration()
- .saturating_sub(
- t.started_at.map(|x| x.elapsed()).unwrap_or(Duration::ZERO),
- )
- .as_millis()
- });
- format!(
- "{:02}:{:02}:{:02}.{:01}",
- millis / 1000 / 3600 % 3600,
- millis / 1000 / 60 % 60,
- millis / 1000 % 60,
- millis / 100 % 10,
- )
- }
- }
- div {
- input {
- r#type: "number",
- min: 0,
- max: 99,
- value: format!("{:02}", timer.read().hours),
- oninput: move |e| {
- timer.write().hours = e.value().parse().unwrap_or(0);
- },
- }
- input {
- r#type: "number",
- min: 0,
- max: 59,
- value: format!("{:02}", timer.read().minutes),
- oninput: move |e| {
- timer.write().minutes = e.value().parse().unwrap_or(0);
- },
- }
- input {
- r#type: "number",
- min: 0,
- max: 59,
- value: format!("{:02}", timer.read().seconds),
- oninput: move |e| {
- timer.write().seconds = e.value().parse().unwrap_or(0);
- },
- }
- }
- button {
- id: "start_stop",
- onclick: move |_| {
- timer
- .with_mut(|t| {
- t.started_at = if t.started_at.is_none() {
- Some(Instant::now())
- } else {
- None
- }
- })
- },
- {timer.with(|t| if t.started_at.is_none() { "Start" } else { "Stop" })}
- }
- div { id: "app",
- button {
- onclick: move |_| {
- let decorations = window_preferences.read().with_decorations;
- use_window().set_decorations(!decorations);
- window_preferences.write().with_decorations = !decorations;
- },
- {
- format!(
- "with decorations{}",
- if window_preferences.read().with_decorations { " ✓" } else { "" },
- )
- }
- }
- button {
- onclick: move |_| {
- window_preferences
- .with_mut(|wp| {
- use_window().set_always_on_top(!wp.always_on_top);
- wp.always_on_top = !wp.always_on_top;
- })
- },
- width: 100,
- {
- format!(
- "always on top{}",
- if window_preferences.read().always_on_top { " ✓" } else { "" },
- )
- }
- }
- }
- {
- exit_button(
- Duration::from_secs(3),
- |trigger, delay| {
- rsx! {
- {
- format!(
- "{:0.1?}",
- trigger
- .read()
- .map(|inst| (delay.as_secs_f32() - inst.elapsed().as_secs_f32())),
- )
- }
- }
- },
- )
- }
- }
- }
|