client: Create stopwatch frontend

Create the frontend for the stopwatch which does not yet communicate
with the server.
This commit is contained in:
finga 2022-09-17 21:53:39 +02:00
parent 0d0f26d6c0
commit b12b8765a9
3 changed files with 99 additions and 8 deletions

14
Cargo.lock generated
View file

@ -247,6 +247,8 @@ name = "client"
version = "0.1.0"
dependencies = [
"console_error_panic_hook",
"gloo-timers",
"instant",
"log",
"wasm-logger",
"yew",
@ -550,6 +552,18 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "iri-string"
version = "0.4.1"

View file

@ -14,3 +14,5 @@ yew = "0.19"
console_error_panic_hook = "0.1"
log = "0.4"
wasm-logger = "0.2"
gloo-timers = "0.2"
instant = { version = "0.1", features = [ "wasm-bindgen" ] }

View file

@ -1,13 +1,88 @@
use gloo_timers::callback::Interval;
use instant::Instant;
use yew::prelude::*;
#[function_component(LockWatch)]
fn lock_watch() -> Html {
html! {
<section class="section">
<div class="container">
<h1 class="title">{ "LockWatch" }</h1>
</div>
</section>
enum Msg {
Start,
Stop,
UpdateDuration,
}
struct LockWatch {
duration: Option<Instant>,
duration_handle: Option<Interval>,
}
impl LockWatch {
fn get_duration(&self) -> String {
self.duration.map_or_else(
|| "00:00:00.000".to_string(),
|instant| {
let elapsed = instant.elapsed();
format!(
"{:02}:{:02}:{:02}.{:03}",
elapsed.as_secs() / 60 / 60,
(elapsed.as_secs() / 60) % 60,
elapsed.as_secs() % 60,
elapsed.as_millis() % 1_000
)
},
)
}
}
impl Component for LockWatch {
type Message = Msg;
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self {
duration: None,
duration_handle: None,
}
}
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
Msg::Start => {
self.duration = Some(Instant::now());
self.duration_handle = {
let link = ctx.link().clone();
Some(Interval::new(1, move || {
link.send_message(Msg::UpdateDuration);
}))
};
}
Msg::Stop => self.duration_handle = None,
Msg::UpdateDuration => {}
}
true
}
fn view(&self, ctx: &Context<Self>) -> Html {
html! {
<section class="section">
<div class="container">
<h1 class="title">{ "LockWatch" }</h1>
<div class="block is-size-1">
{ &self.get_duration() }
</div>
<div class="block">
if self.duration_handle.is_some() {
<button class="button is-danger" onclick={ctx.link().callback(|_| Msg::Stop)}>{ "Stop" }</button>
} else {
if self.duration.is_some() {
<button class="button" disabled=true>{ "Start" }</button>
} else {
<button class="button is-primary" onclick={ctx.link().callback(|_| Msg::Start)}>{ "Start" }</button>
}
}
</div>
</div>
</section>
}
}
}