fixed codex AI slop
This commit is contained in:
@@ -10,6 +10,7 @@ This is a learning project. The assistant is a guide, not an implementer.
|
||||
- If asked to implement code, the assistant should refuse and provide a clear plan the developer can execute.
|
||||
- If asked about a file, function, module, or crate, the assistant must read the current code first before answering.
|
||||
- Reviews and guidance must be based strictly on the current file contents, not earlier snapshots.
|
||||
- Before each technical answer, the assistant must re-open the relevant files/outputs and verify against current on-disk state, never relying on memory from earlier turns.
|
||||
|
||||
## Project Structure & Module Organization
|
||||
This repository is a Tauri app with a TypeScript frontend and Rust backend.
|
||||
|
||||
@@ -1,26 +1,36 @@
|
||||
import { invokeCommand } from "../../shared/tauri/invoke";
|
||||
import type { CountdownCommand, CountdownSnapshotDto } from "./types";
|
||||
import {invokeCommand} from "../../shared/tauri/invoke";
|
||||
import type {CountdownCommand, CountdownSnapshot, CountdownSnapshotDto, Duration} from "./types";
|
||||
import {millisToDuration} from "./helper.ts";
|
||||
|
||||
export async function fetchCountdownSnapshot(): Promise<CountdownSnapshotDto> {
|
||||
return invokeCommand<CountdownSnapshotDto>("countdown_snapshot");
|
||||
export async function fetchCountdownSnapshot(): Promise<CountdownSnapshot> {
|
||||
let temp = await invokeCommand<CountdownSnapshotDto>("countdown_snapshot");
|
||||
let duration: Duration = millisToDuration(temp.duration);
|
||||
return {
|
||||
id: temp.id,
|
||||
label: temp.label,
|
||||
duration: duration,
|
||||
state: temp.state,
|
||||
start_epoch_ms: temp.start_epoch_ms ? new Date(temp.start_epoch_ms) : null,
|
||||
target_epoch_ms: temp.target_epoch_ms ? new Date(temp.target_epoch_ms) : null,
|
||||
};
|
||||
}
|
||||
|
||||
async function invokeCountdownCommand(command: CountdownCommand): Promise<void> {
|
||||
await invokeCommand<void>(command);
|
||||
await invokeCommand<void>(command);
|
||||
}
|
||||
|
||||
export async function startCountdown(): Promise<void> {
|
||||
await invokeCountdownCommand("countdown_start");
|
||||
await invokeCountdownCommand("countdown_start");
|
||||
}
|
||||
|
||||
export async function pauseCountdown(): Promise<void> {
|
||||
await invokeCountdownCommand("countdown_pause");
|
||||
await invokeCountdownCommand("countdown_pause");
|
||||
}
|
||||
|
||||
export async function resumeCountdown(): Promise<void> {
|
||||
await invokeCountdownCommand("countdown_resume");
|
||||
await invokeCountdownCommand("countdown_resume");
|
||||
}
|
||||
|
||||
export async function resetCountdown(): Promise<void> {
|
||||
await invokeCountdownCommand("countdown_reset");
|
||||
await invokeCountdownCommand("countdown_reset");
|
||||
}
|
||||
|
||||
14
src/features/countdown/helper.ts
Normal file
14
src/features/countdown/helper.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import {Duration} from "./types.ts";
|
||||
|
||||
export function millisToDuration(millis: number): Duration {
|
||||
return {
|
||||
hours: Math.floor(millis / 3600000),
|
||||
minutes: Math.floor((millis % 3600000) / 60000),
|
||||
seconds: Math.floor((millis % 60000) / 1000),
|
||||
millis: millis % 1000,
|
||||
}
|
||||
}
|
||||
|
||||
export function formatDuration(duration: Duration): string {
|
||||
return `${duration.hours.toString().padStart(2, '0')}:${duration.minutes.toString().padStart(2, '0')}:${duration.seconds.toString().padStart(2, '0')}.${duration.millis.toString().padStart(3, '0')}`;
|
||||
}
|
||||
@@ -1,21 +1,32 @@
|
||||
export type CountdownState = "Idle" | "Running" | "Paused" | "Finished";
|
||||
|
||||
export type CountdownDuration = {
|
||||
secs: number;
|
||||
nanos: number;
|
||||
};
|
||||
export type Duration = {
|
||||
hours: number;
|
||||
minutes: number;
|
||||
seconds: number;
|
||||
millis: number;
|
||||
}
|
||||
|
||||
export type CountdownSnapshotDto = {
|
||||
id: number;
|
||||
label: string;
|
||||
duration: CountdownDuration;
|
||||
state: CountdownState;
|
||||
start_epoch_ms: number | null;
|
||||
target_epoch_ms: number | null;
|
||||
id: number;
|
||||
label: string;
|
||||
duration: number;
|
||||
state: CountdownState;
|
||||
start_epoch_ms: number | null;
|
||||
target_epoch_ms: number | null;
|
||||
};
|
||||
|
||||
export type CountdownSnapshot = {
|
||||
id: number;
|
||||
label: string;
|
||||
duration: Duration;
|
||||
state: CountdownState;
|
||||
start_epoch_ms: Date | null;
|
||||
target_epoch_ms: Date | null;
|
||||
}
|
||||
|
||||
export type CountdownCommand =
|
||||
| "countdown_start"
|
||||
| "countdown_pause"
|
||||
| "countdown_resume"
|
||||
| "countdown_reset";
|
||||
| "countdown_start"
|
||||
| "countdown_pause"
|
||||
| "countdown_resume"
|
||||
| "countdown_reset";
|
||||
|
||||
@@ -1,77 +1,77 @@
|
||||
import { formatDuration } from "../../shared/time/format";
|
||||
import type { CountdownSnapshotDto } from "./types";
|
||||
import {formatDuration} from "./helper.ts";
|
||||
import {CountdownSnapshot} from "./types.ts";
|
||||
|
||||
export type CountdownView = {
|
||||
onStart: (handler: () => void) => void;
|
||||
onPause: (handler: () => void) => void;
|
||||
onResume: (handler: () => void) => void;
|
||||
onReset: (handler: () => void) => void;
|
||||
onRefresh: (handler: () => void) => void;
|
||||
setSnapshot: (snapshot: CountdownSnapshotDto) => void;
|
||||
setError: (message: string) => void;
|
||||
onStart: (handler: () => void) => void;
|
||||
onPause: (handler: () => void) => void;
|
||||
onResume: (handler: () => void) => void;
|
||||
onReset: (handler: () => void) => void;
|
||||
onRefresh: (handler: () => void) => void;
|
||||
setSnapshot: (snapshot: CountdownSnapshot) => void;
|
||||
setError: (message: string) => void;
|
||||
};
|
||||
|
||||
function makeButton(label: string): HTMLButtonElement {
|
||||
const button = document.createElement("button");
|
||||
button.type = "button";
|
||||
button.textContent = label;
|
||||
return button;
|
||||
const button = document.createElement("button");
|
||||
button.type = "button";
|
||||
button.textContent = label;
|
||||
return button;
|
||||
}
|
||||
|
||||
export function createCountdownView(container: HTMLElement): CountdownView {
|
||||
const panel = document.createElement("section");
|
||||
panel.className = "countdown-panel";
|
||||
const panel = document.createElement("section");
|
||||
panel.className = "countdown-panel";
|
||||
|
||||
const title = document.createElement("h2");
|
||||
title.textContent = "Countdown Controls";
|
||||
const title = document.createElement("h2");
|
||||
title.textContent = "Countdown Controls";
|
||||
|
||||
const actions = document.createElement("div");
|
||||
actions.className = "countdown-actions";
|
||||
const actions = document.createElement("div");
|
||||
actions.className = "countdown-actions";
|
||||
|
||||
const startButton = makeButton("Start");
|
||||
const pauseButton = makeButton("Pause");
|
||||
const resumeButton = makeButton("Resume");
|
||||
const resetButton = makeButton("Reset");
|
||||
const refreshButton = makeButton("Refresh");
|
||||
const startButton = makeButton("Start");
|
||||
const pauseButton = makeButton("Pause");
|
||||
const resumeButton = makeButton("Resume");
|
||||
const resetButton = makeButton("Reset");
|
||||
const refreshButton = makeButton("Refresh");
|
||||
|
||||
actions.append(startButton, pauseButton, resumeButton, resetButton, refreshButton);
|
||||
actions.append(startButton, pauseButton, resumeButton, resetButton, refreshButton);
|
||||
|
||||
const summary = document.createElement("p");
|
||||
summary.className = "countdown-summary";
|
||||
summary.textContent = "Waiting for snapshot...";
|
||||
const summary = document.createElement("p");
|
||||
summary.className = "countdown-summary";
|
||||
summary.textContent = "Waiting for snapshot...";
|
||||
|
||||
const error = document.createElement("p");
|
||||
error.className = "countdown-error";
|
||||
const error = document.createElement("p");
|
||||
error.className = "countdown-error";
|
||||
|
||||
const snapshot = document.createElement("pre");
|
||||
snapshot.className = "countdown-snapshot";
|
||||
const snapshot = document.createElement("pre");
|
||||
snapshot.className = "countdown-snapshot";
|
||||
|
||||
panel.append(title, actions, summary, error, snapshot);
|
||||
container.appendChild(panel);
|
||||
panel.append(title, actions, summary, error, snapshot);
|
||||
container.appendChild(panel);
|
||||
|
||||
return {
|
||||
onStart(handler) {
|
||||
startButton.addEventListener("click", handler);
|
||||
},
|
||||
onPause(handler) {
|
||||
pauseButton.addEventListener("click", handler);
|
||||
},
|
||||
onResume(handler) {
|
||||
resumeButton.addEventListener("click", handler);
|
||||
},
|
||||
onReset(handler) {
|
||||
resetButton.addEventListener("click", handler);
|
||||
},
|
||||
onRefresh(handler) {
|
||||
refreshButton.addEventListener("click", handler);
|
||||
},
|
||||
setSnapshot(value) {
|
||||
error.textContent = "";
|
||||
summary.textContent = `State: ${value.state} | Remaining: ${formatDuration(value.duration)}`;
|
||||
snapshot.textContent = JSON.stringify(value, null, 2);
|
||||
},
|
||||
setError(message) {
|
||||
error.textContent = message;
|
||||
},
|
||||
};
|
||||
return {
|
||||
onStart(handler) {
|
||||
startButton.addEventListener("click", handler);
|
||||
},
|
||||
onPause(handler) {
|
||||
pauseButton.addEventListener("click", handler);
|
||||
},
|
||||
onResume(handler) {
|
||||
resumeButton.addEventListener("click", handler);
|
||||
},
|
||||
onReset(handler) {
|
||||
resetButton.addEventListener("click", handler);
|
||||
},
|
||||
onRefresh(handler) {
|
||||
refreshButton.addEventListener("click", handler);
|
||||
},
|
||||
setSnapshot(value) {
|
||||
error.textContent = "";
|
||||
summary.textContent = `State: ${value.state} | Remaining: ${formatDuration(value.duration)}`;
|
||||
snapshot.textContent = JSON.stringify(value, null, 2);
|
||||
},
|
||||
setError(message) {
|
||||
error.textContent = message;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
type DurationLike = {
|
||||
secs?: number;
|
||||
nanos?: number;
|
||||
};
|
||||
|
||||
export function formatDuration(value: DurationLike): string {
|
||||
const totalSeconds = Math.max(0, Math.floor(value.secs ?? 0));
|
||||
const hours = Math.floor(totalSeconds / 3600)
|
||||
.toString()
|
||||
.padStart(2, "0");
|
||||
const minutes = Math.floor((totalSeconds % 3600) / 60)
|
||||
.toString()
|
||||
.padStart(2, "0");
|
||||
const seconds = (totalSeconds % 60).toString().padStart(2, "0");
|
||||
|
||||
return `${hours}:${minutes}:${seconds}`;
|
||||
}
|
||||
Reference in New Issue
Block a user