standard-plugin-sdk 0.1.2

Write Standard Code plugins in Rust: wasm components against standard:plugin@2.0.0
Documentation
//! A sidebar card: the time since the viewer started and a bar of the
//! seconds. It repaints once a second and only while the card is visible.
//!
//! Manifest (`bundle/standard-plugin.json`):
//!
//! ```json
//! {
//!   "apiVersion": 2, "kind": "ui", "id": "clock-card", "version": "0.1.0",
//!   "module": "clock_card.wasm",
//!   "surfaces": [{ "id": "card", "anchor": "sidebar.card", "model": "cells", "height": 2 }],
//!   "grants": {}
//! }
//! ```
#![no_std]

use standard_plugin::prelude::*;

#[standard_plugin::ui]
struct ClockCard {
    card: Surface<Cells>,
    shown: Option<u64>,
}

impl UiPlugin for ClockCard {
    fn activate(_cx: &mut Context) -> Self {
        Self {
            card: Surface::new("card"),
            shown: None,
        }
    }

    fn frame(&mut self, frame: &Frame) {
        let second = frame.now_ms() / 1000;
        if self.shown != Some(second) {
            self.shown = Some(second);
            let (cols, _) = self.card.size();
            let time = format!(
                "{:02}:{:02}:{:02}",
                second / 3600 % 24,
                second / 60 % 60,
                second % 60
            );
            self.card.text(0, 0, &time, Style::fg(Colour::FG).bold());
            let fraction = (second % 60) as f32 / 60.0;
            let track = Style::fg(Colour::RECEDE_FG);
            self.card.bar(
                Area::new(0, 1, cols, 1),
                fraction,
                Style::fg(Colour::ACCENT),
                track,
            );
            // Publishes only the cells that changed.
            let _ = self.card.commit();
        }
        // The next second boundary: an idle viewer wakes once a second.
        frame.wake_at((second + 1) * 1000);
    }

    fn event(&mut self, event: Event, _cx: &mut Context) {
        if let Event::Resize { .. } = event {
            // The card has a new, empty buffer: repaint on the next frame.
            self.shown = None;
        }
    }
}