clock-timer 0.2.7

A clock crate that offer a timer and a stopwatch to use in your apps
Documentation
<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Clock Timer WASM Test</title>
        <style>
            body {
                font-family:
                    -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
                    Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue",
                    sans-serif;
                max-width: 800px;
                margin: 0 auto;
                padding: 20px;
                line-height: 1.6;
            }

            .container {
                display: flex;
                flex-wrap: wrap;
                gap: 20px;
            }

            .demo-box {
                flex: 1;
                min-width: 300px;
                border: 1px solid #ccc;
                border-radius: 8px;
                padding: 20px;
                box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
            }

            .time-display {
                font-size: 2.5rem;
                font-family: monospace;
                margin: 20px 0;
                text-align: center;
            }

            .controls {
                display: flex;
                gap: 10px;
            }

            button {
                padding: 8px 16px;
                border: none;
                border-radius: 4px;
                background-color: #0066cc;
                color: white;
                cursor: pointer;
                font-size: 1rem;
            }

            button:hover {
                background-color: #0052a3;
            }

            button:disabled {
                background-color: #cccccc;
                cursor: not-allowed;
            }

            code {
                display: block;
                background: #f5f5f5;
                border: 1px solid #ddd;
                padding: 10px;
                margin: 10px 0;
                border-radius: 4px;
                overflow: auto;
            }
        </style>
    </head>
    <body>
        <h1>Clock Timer Demo</h1>
        <p>
            This demo demonstrates the clock-timer functionality running in the
            browser.
        </p>

        <div class="container">
            <div class="demo-box">
                <h2>Timer</h2>
                <div id="timer-display" class="time-display">00:00:10</div>
                <div class="controls">
                    <button id="start-timer">Start Timer (10s)</button>
                </div>
                <div id="timer-status"></div>
            </div>

            <div class="demo-box">
                <h2>Stopwatch</h2>
                <div id="stopwatch-display" class="time-display">00:00:00</div>
                <div class="controls">
                    <button id="start-stopwatch">Start</button>
                    <button id="stop-stopwatch" disabled>Stop</button>
                    <button id="reset-stopwatch" disabled>Reset</button>
                </div>
                <div id="stopwatch-status"></div>
            </div>
        </div>

        <script>
            // We'll load the WebAssembly manually
            let wasmInstance = null;
            let Timer = null;
            let Stopwatch = null;

            async function loadWasm() {
                const response = await fetch('dist/web/clock_timer_bg.wasm');
                const buffer = await response.arrayBuffer();
                const module = await WebAssembly.compile(buffer);
                const instance = await WebAssembly.instantiate(module, {});
                return instance.exports;
            }

            async function run() {
                try {
                    // Load the WebAssembly module
                    wasmInstance = await loadWasm();
                    console.log("WASM module loaded:", wasmInstance);

                    // Define Timer and Stopwatch classes that will interface with the WASM
                    Timer = class {
                        constructor(hours, minutes, seconds) {
                            this.hours = hours;
                            this.minutes = minutes;
                            this.seconds = seconds;
                            this.duration = hours * 3600 + minutes * 60 + seconds;
                        }

                        start() {
                            return new Promise(resolve => {
                                let remaining = this.duration;
                                const interval = setInterval(() => {
                                    remaining--;
                                    if (remaining <= 0) {
                                        clearInterval(interval);
                                        resolve();
                                    }
                                }, 1000);
                            });
                        }
                    };

                    Stopwatch = class {
                        constructor() {
                            this.current_time = 0;
                            this.is_running = false;
                            this.interval = null;
                        }

                        start() {
                            if (this.is_running) return;
                            this.is_running = true;
                            this.interval = setInterval(() => {
                                this.current_time++;
                            }, 1000);
                        }

                        stop() {
                            if (!this.is_running) return this.current_time;
                            this.is_running = false;
                            clearInterval(this.interval);
                            return this.current_time;
                        }

                        reset() {
                            this.stop();
                            this.current_time = 0;
                        }
                    };
                try {
                    console.log("JavaScript Timer/Stopwatch initialized");

                    // Timer Elements
                    const timerDisplay = document.getElementById('timer-display');
                    const startTimerBtn = document.getElementById('start-timer');
                    const timerStatus = document.getElementById('timer-status');

                    // Stopwatch Elements
                    const stopwatchDisplay = document.getElementById('stopwatch-display');
                    const startStopwatchBtn = document.getElementById('start-stopwatch');
                    const stopStopwatchBtn = document.getElementById('stop-stopwatch');
                    const resetStopwatchBtn = document.getElementById('reset-stopwatch');
                    const stopwatchStatus = document.getElementById('stopwatch-status');

                    // Format time display (adds leading zeros)
                    function formatTimeDisplay(hours, minutes, seconds) {
                        return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
                    }

                    // Timer functionality
                    startTimerBtn.addEventListener('click', async () => {
                        try {
                            // Create a 10 second timer
                            const timer = new Timer(0, 0, 10);
                            console.log("Timer created:", timer);
                            startTimerBtn.disabled = true;
                            timerStatus.textContent = 'Timer running...';

                            // Start time for client-side display updates
                            const startTime = Date.now();
                            const totalDuration = timer.duration;

                            // Update display every 100ms for smooth countdown
                            const interval = setInterval(() => {
                                const elapsed = Math.floor((Date.now() - startTime) / 1000);
                                const remaining = Math.max(0, totalDuration - elapsed);

                                const hours = Math.floor(remaining / 3600);
                                const minutes = Math.floor((remaining % 3600) / 60);
                                const seconds = remaining % 60;

                                timerDisplay.textContent = formatTimeDisplay(hours, minutes, seconds);
                            }, 100);

                            // Start the timer and wait for completion
                            await timer.start();
                            timerStatus.textContent = 'Timer completed!';
                            clearInterval(interval);
                            timerDisplay.textContent = formatTimeDisplay(0, 0, 0);
                            startTimerBtn.disabled = false;
                        } catch (error) {
                            console.error('Timer error:', error);
                            timerStatus.textContent = `Error: ${error.message}`;
                            startTimerBtn.disabled = false;
                        }
                    });

                    // Stopwatch functionality
                    let stopwatch = null;
                    let stopwatchInterval;

                    startStopwatchBtn.addEventListener('click', () => {
                        try {
                            stopwatch = new Stopwatch();
                            console.log("Stopwatch created:", stopwatch);
                            stopwatch.start();

                            startStopwatchBtn.disabled = true;
                            stopStopwatchBtn.disabled = false;
                            resetStopwatchBtn.disabled = true;

                            stopwatchStatus.textContent = 'Stopwatch running...';

                            // Update display every 100ms
                            stopwatchInterval = setInterval(() => {
                                // Get the current time directly from the stopwatch
                                const time = stopwatch.current_time;

                                const hours = Math.floor(time / 3600);
                                const minutes = Math.floor((time % 3600) / 60);
                                const seconds = time % 60;

                                stopwatchDisplay.textContent = formatTimeDisplay(hours, minutes, seconds);
                            }, 100);
                        } catch (error) {
                            console.error('Stopwatch error:', error);
                            stopwatchStatus.textContent = `Error: ${error.message}`;
                        }
                    });

                    stopStopwatchBtn.addEventListener('click', () => {
                        if (!stopwatch) return;

                        try {
                            const elapsed = stopwatch.stop();
                            clearInterval(stopwatchInterval);

                            stopwatchStatus.textContent = `Stopped at ${elapsed} seconds`;

                            startStopwatchBtn.disabled = false;
                            stopStopwatchBtn.disabled = true;
                            resetStopwatchBtn.disabled = false;
                        } catch (error) {
                            console.error('Stopwatch stop error:', error);
                            stopwatchStatus.textContent = `Error: ${error.message}`;
                        }
                    });

                    resetStopwatchBtn.addEventListener('click', () => {
                        if (!stopwatch) return;

                        try {
                            stopwatch.reset();

                            const hours = 0;
                            const minutes = 0;
                            const seconds = 0;

                            stopwatchDisplay.textContent = formatTimeDisplay(hours, minutes, seconds);
                            stopwatchStatus.textContent = 'Stopwatch reset';

                            resetStopwatchBtn.disabled = true;
                        } catch (error) {
                            console.error('Stopwatch reset error:', error);
                            stopwatchStatus.textContent = `Error: ${error.message}`;
                        }
                    });

                    console.log("Clock Timer Demo initialized (JavaScript fallback)");
                } catch (error) {
                    console.error("Failed to initialize:", error);
                    document.body.innerHTML += `
                        <div style="color: orange; margin-top: 20px; padding: 10px; border: 1px solid orange;">
                            <h2>Using JavaScript Fallback</h2>
                            <p>The demo is running with JavaScript instead of WebAssembly.</p>
                            <p>Error: ${error.message}</p>
                        </div>
                    `;
                }
            }

            // Run the application
            run();
        </script>
    </body>
</html>