mirror of
https://github.com/jhbruhn/respira.git
synced 2026-01-27 10:23:41 +00:00
Compare commits
No commits in common. "main" and "v0.11.0" have entirely different histories.
13 changed files with 38 additions and 345 deletions
39
.beads/.gitignore
vendored
39
.beads/.gitignore
vendored
|
|
@ -1,39 +0,0 @@
|
||||||
# SQLite databases
|
|
||||||
*.db
|
|
||||||
*.db?*
|
|
||||||
*.db-journal
|
|
||||||
*.db-wal
|
|
||||||
*.db-shm
|
|
||||||
|
|
||||||
# Daemon runtime files
|
|
||||||
daemon.lock
|
|
||||||
daemon.log
|
|
||||||
daemon.pid
|
|
||||||
bd.sock
|
|
||||||
sync-state.json
|
|
||||||
last-touched
|
|
||||||
|
|
||||||
# Local version tracking (prevents upgrade notification spam after git ops)
|
|
||||||
.local_version
|
|
||||||
|
|
||||||
# Legacy database files
|
|
||||||
db.sqlite
|
|
||||||
bd.db
|
|
||||||
|
|
||||||
# Worktree redirect file (contains relative path to main repo's .beads/)
|
|
||||||
# Must not be committed as paths would be wrong in other clones
|
|
||||||
redirect
|
|
||||||
|
|
||||||
# Merge artifacts (temporary files from 3-way merge)
|
|
||||||
beads.base.jsonl
|
|
||||||
beads.base.meta.json
|
|
||||||
beads.left.jsonl
|
|
||||||
beads.left.meta.json
|
|
||||||
beads.right.jsonl
|
|
||||||
beads.right.meta.json
|
|
||||||
|
|
||||||
# NOTE: Do NOT add negation patterns (e.g., !issues.jsonl) here.
|
|
||||||
# They would override fork protection in .git/info/exclude, allowing
|
|
||||||
# contributors to accidentally commit upstream issue databases.
|
|
||||||
# The JSONL files (issues.jsonl, interactions.jsonl) and config files
|
|
||||||
# are tracked by git by default since no pattern above ignores them.
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
# Beads - AI-Native Issue Tracking
|
|
||||||
|
|
||||||
Welcome to Beads! This repository uses **Beads** for issue tracking - a modern, AI-native tool designed to live directly in your codebase alongside your code.
|
|
||||||
|
|
||||||
## What is Beads?
|
|
||||||
|
|
||||||
Beads is issue tracking that lives in your repo, making it perfect for AI coding agents and developers who want their issues close to their code. No web UI required - everything works through the CLI and integrates seamlessly with git.
|
|
||||||
|
|
||||||
**Learn more:** [github.com/steveyegge/beads](https://github.com/steveyegge/beads)
|
|
||||||
|
|
||||||
## Quick Start
|
|
||||||
|
|
||||||
### Essential Commands
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Create new issues
|
|
||||||
bd create "Add user authentication"
|
|
||||||
|
|
||||||
# View all issues
|
|
||||||
bd list
|
|
||||||
|
|
||||||
# View issue details
|
|
||||||
bd show <issue-id>
|
|
||||||
|
|
||||||
# Update issue status
|
|
||||||
bd update <issue-id> --status in_progress
|
|
||||||
bd update <issue-id> --status done
|
|
||||||
|
|
||||||
# Sync with git remote
|
|
||||||
bd sync
|
|
||||||
```
|
|
||||||
|
|
||||||
### Working with Issues
|
|
||||||
|
|
||||||
Issues in Beads are:
|
|
||||||
- **Git-native**: Stored in `.beads/issues.jsonl` and synced like code
|
|
||||||
- **AI-friendly**: CLI-first design works perfectly with AI coding agents
|
|
||||||
- **Branch-aware**: Issues can follow your branch workflow
|
|
||||||
- **Always in sync**: Auto-syncs with your commits
|
|
||||||
|
|
||||||
## Why Beads?
|
|
||||||
|
|
||||||
✨ **AI-Native Design**
|
|
||||||
- Built specifically for AI-assisted development workflows
|
|
||||||
- CLI-first interface works seamlessly with AI coding agents
|
|
||||||
- No context switching to web UIs
|
|
||||||
|
|
||||||
🚀 **Developer Focused**
|
|
||||||
- Issues live in your repo, right next to your code
|
|
||||||
- Works offline, syncs when you push
|
|
||||||
- Fast, lightweight, and stays out of your way
|
|
||||||
|
|
||||||
🔧 **Git Integration**
|
|
||||||
- Automatic sync with git commits
|
|
||||||
- Branch-aware issue tracking
|
|
||||||
- Intelligent JSONL merge resolution
|
|
||||||
|
|
||||||
## Get Started with Beads
|
|
||||||
|
|
||||||
Try Beads in your own projects:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Install Beads
|
|
||||||
curl -sSL https://raw.githubusercontent.com/steveyegge/beads/main/scripts/install.sh | bash
|
|
||||||
|
|
||||||
# Initialize in your repo
|
|
||||||
bd init
|
|
||||||
|
|
||||||
# Create your first issue
|
|
||||||
bd create "Try out Beads"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Learn More
|
|
||||||
|
|
||||||
- **Documentation**: [github.com/steveyegge/beads/docs](https://github.com/steveyegge/beads/tree/main/docs)
|
|
||||||
- **Quick Start Guide**: Run `bd quickstart`
|
|
||||||
- **Examples**: [github.com/steveyegge/beads/examples](https://github.com/steveyegge/beads/tree/main/examples)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*Beads: Issue tracking that moves at the speed of thought* ⚡
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
# Beads Configuration File
|
|
||||||
# This file configures default behavior for all bd commands in this repository
|
|
||||||
# All settings can also be set via environment variables (BD_* prefix)
|
|
||||||
# or overridden with command-line flags
|
|
||||||
|
|
||||||
# Issue prefix for this repository (used by bd init)
|
|
||||||
# If not set, bd init will auto-detect from directory name
|
|
||||||
# Example: issue-prefix: "myproject" creates issues like "myproject-1", "myproject-2", etc.
|
|
||||||
# issue-prefix: ""
|
|
||||||
|
|
||||||
# Use no-db mode: load from JSONL, no SQLite, write back after each command
|
|
||||||
# When true, bd will use .beads/issues.jsonl as the source of truth
|
|
||||||
# instead of SQLite database
|
|
||||||
# no-db: false
|
|
||||||
|
|
||||||
# Disable daemon for RPC communication (forces direct database access)
|
|
||||||
# no-daemon: false
|
|
||||||
|
|
||||||
# Disable auto-flush of database to JSONL after mutations
|
|
||||||
# no-auto-flush: false
|
|
||||||
|
|
||||||
# Disable auto-import from JSONL when it's newer than database
|
|
||||||
# no-auto-import: false
|
|
||||||
|
|
||||||
# Enable JSON output by default
|
|
||||||
# json: false
|
|
||||||
|
|
||||||
# Default actor for audit trails (overridden by BD_ACTOR or --actor)
|
|
||||||
# actor: ""
|
|
||||||
|
|
||||||
# Path to database (overridden by BEADS_DB or --db)
|
|
||||||
# db: ""
|
|
||||||
|
|
||||||
# Auto-start daemon if not running (can also use BEADS_AUTO_START_DAEMON)
|
|
||||||
# auto-start-daemon: true
|
|
||||||
|
|
||||||
# Debounce interval for auto-flush (can also use BEADS_FLUSH_DEBOUNCE)
|
|
||||||
# flush-debounce: "5s"
|
|
||||||
|
|
||||||
# Git branch for beads commits (bd sync will commit to this branch)
|
|
||||||
# IMPORTANT: Set this for team projects so all clones use the same sync branch.
|
|
||||||
# This setting persists across clones (unlike database config which is gitignored).
|
|
||||||
# Can also use BEADS_SYNC_BRANCH env var for local override.
|
|
||||||
# If not set, bd sync will require you to run 'bd config set sync.branch <branch>'.
|
|
||||||
sync-branch: "beads-sync"
|
|
||||||
|
|
||||||
# Multi-repo configuration (experimental - bd-307)
|
|
||||||
# Allows hydrating from multiple repositories and routing writes to the correct JSONL
|
|
||||||
# repos:
|
|
||||||
# primary: "." # Primary repo (where this database lives)
|
|
||||||
# additional: # Additional repos to hydrate from (read-only)
|
|
||||||
# - ~/beads-planning # Personal planning repo
|
|
||||||
# - ~/work-planning # Work planning repo
|
|
||||||
|
|
||||||
# Integration settings (access with 'bd config get/set')
|
|
||||||
# These are stored in the database, not in this file:
|
|
||||||
# - jira.url
|
|
||||||
# - jira.project
|
|
||||||
# - linear.url
|
|
||||||
# - linear.api-key
|
|
||||||
# - github.org
|
|
||||||
# - github.repo
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"database": "beads.db",
|
|
||||||
"jsonl_export": "issues.jsonl"
|
|
||||||
}
|
|
||||||
3
.gitattributes
vendored
3
.gitattributes
vendored
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
# Use bd merge for beads JSONL files
|
|
||||||
.beads/issues.jsonl merge=beads
|
|
||||||
40
AGENTS.md
40
AGENTS.md
|
|
@ -1,40 +0,0 @@
|
||||||
# Agent Instructions
|
|
||||||
|
|
||||||
This project uses **bd** (beads) for issue tracking. Run `bd onboard` to get started.
|
|
||||||
|
|
||||||
## Quick Reference
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bd ready # Find available work
|
|
||||||
bd show <id> # View issue details
|
|
||||||
bd update <id> --status in_progress # Claim work
|
|
||||||
bd close <id> # Complete work
|
|
||||||
bd sync # Sync with git
|
|
||||||
```
|
|
||||||
|
|
||||||
## Landing the Plane (Session Completion)
|
|
||||||
|
|
||||||
**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.
|
|
||||||
|
|
||||||
**MANDATORY WORKFLOW:**
|
|
||||||
|
|
||||||
1. **File issues for remaining work** - Create issues for anything that needs follow-up
|
|
||||||
2. **Run quality gates** (if code changed) - Tests, linters, builds
|
|
||||||
3. **Update issue status** - Close finished work, update in-progress items
|
|
||||||
4. **PUSH TO REMOTE** - This is MANDATORY:
|
|
||||||
```bash
|
|
||||||
git pull --rebase
|
|
||||||
bd sync
|
|
||||||
git push
|
|
||||||
git status # MUST show "up to date with origin"
|
|
||||||
```
|
|
||||||
5. **Clean up** - Clear stashes, prune remote branches
|
|
||||||
6. **Verify** - All changes committed AND pushed
|
|
||||||
7. **Hand off** - Provide context for next session
|
|
||||||
|
|
||||||
**CRITICAL RULES:**
|
|
||||||
- Work is NOT complete until `git push` succeeds
|
|
||||||
- NEVER stop before pushing - that leaves work stranded locally
|
|
||||||
- NEVER say "ready to push when you are" - YOU must push
|
|
||||||
- If push fails, resolve and retry until it succeeds
|
|
||||||
|
|
||||||
|
|
@ -46,7 +46,7 @@ export const Grid = memo(({ gridSize, bounds, machineInfo }: GridProps) => {
|
||||||
const gridColor = canvasColors.grid();
|
const gridColor = canvasColors.grid();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Group name="grid" listening={false}>
|
<Group name="grid">
|
||||||
{lines.verticalLines.map((points, i) => (
|
{lines.verticalLines.map((points, i) => (
|
||||||
<Line
|
<Line
|
||||||
key={`v-${i}`}
|
key={`v-${i}`}
|
||||||
|
|
@ -73,7 +73,7 @@ export const Origin = memo(() => {
|
||||||
const originColor = canvasColors.origin();
|
const originColor = canvasColors.origin();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Group name="origin" listening={false}>
|
<Group name="origin">
|
||||||
<Line points={[-10, 0, 10, 0]} stroke={originColor} strokeWidth={2} />
|
<Line points={[-10, 0, 10, 0]} stroke={originColor} strokeWidth={2} />
|
||||||
<Line points={[0, -10, 0, 10]} stroke={originColor} strokeWidth={2} />
|
<Line points={[0, -10, 0, 10]} stroke={originColor} strokeWidth={2} />
|
||||||
</Group>
|
</Group>
|
||||||
|
|
@ -93,7 +93,7 @@ export const Hoop = memo(({ machineInfo }: HoopProps) => {
|
||||||
const hoopColor = canvasColors.hoop();
|
const hoopColor = canvasColors.hoop();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Group name="hoop" listening={false}>
|
<Group name="hoop">
|
||||||
<Rect
|
<Rect
|
||||||
x={hoopLeft}
|
x={hoopLeft}
|
||||||
y={hoopTop}
|
y={hoopTop}
|
||||||
|
|
|
||||||
|
|
@ -74,8 +74,6 @@ export function PatternCanvas() {
|
||||||
handleZoomIn,
|
handleZoomIn,
|
||||||
handleZoomOut,
|
handleZoomOut,
|
||||||
handleZoomReset,
|
handleZoomReset,
|
||||||
handleStageDragStart,
|
|
||||||
handleStageDragEnd,
|
|
||||||
} = useCanvasViewport({
|
} = useCanvasViewport({
|
||||||
containerRef,
|
containerRef,
|
||||||
pesData,
|
pesData,
|
||||||
|
|
@ -167,8 +165,16 @@ export function PatternCanvas() {
|
||||||
scaleY={stageScale}
|
scaleY={stageScale}
|
||||||
draggable
|
draggable
|
||||||
onWheel={handleWheel}
|
onWheel={handleWheel}
|
||||||
onDragStart={handleStageDragStart}
|
onDragStart={() => {
|
||||||
onDragEnd={handleStageDragEnd}
|
if (stageRef.current) {
|
||||||
|
stageRef.current.container().style.cursor = "grabbing";
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onDragEnd={() => {
|
||||||
|
if (stageRef.current) {
|
||||||
|
stageRef.current.container().style.cursor = "grab";
|
||||||
|
}
|
||||||
|
}}
|
||||||
ref={(node) => {
|
ref={(node) => {
|
||||||
stageRef.current = node;
|
stageRef.current = node;
|
||||||
if (node) {
|
if (node) {
|
||||||
|
|
@ -176,8 +182,8 @@ export function PatternCanvas() {
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* Background layer: grid, origin, hoop - static, no event listening */}
|
{/* Background layer: grid, origin, hoop */}
|
||||||
<Layer listening={false}>
|
<Layer>
|
||||||
{displayPattern && (
|
{displayPattern && (
|
||||||
<>
|
<>
|
||||||
<Grid
|
<Grid
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,10 @@
|
||||||
* useCanvasViewport Hook
|
* useCanvasViewport Hook
|
||||||
*
|
*
|
||||||
* Manages canvas viewport state including zoom, pan, and container size
|
* Manages canvas viewport state including zoom, pan, and container size
|
||||||
* Handles wheel zoom, button zoom operations, and stage drag cursor updates
|
* Handles wheel zoom and button zoom operations
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import { useState, useEffect, useCallback, type RefObject } from "react";
|
||||||
useState,
|
|
||||||
useEffect,
|
|
||||||
useCallback,
|
|
||||||
useRef,
|
|
||||||
type RefObject,
|
|
||||||
} from "react";
|
|
||||||
import type Konva from "konva";
|
import type Konva from "konva";
|
||||||
import type { PesPatternData } from "../../formats/import/pesImporter";
|
import type { PesPatternData } from "../../formats/import/pesImporter";
|
||||||
import type { MachineInfo } from "../../types/machine";
|
import type { MachineInfo } from "../../types/machine";
|
||||||
|
|
@ -93,12 +87,7 @@ export function useCanvasViewport({
|
||||||
setStagePos({ x: containerSize.width / 2, y: containerSize.height / 2 });
|
setStagePos({ x: containerSize.width / 2, y: containerSize.height / 2 });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wheel zoom handler with RAF throttling and delta accumulation
|
// Wheel zoom handler
|
||||||
const wheelThrottleRef = useRef<number | null>(null);
|
|
||||||
const accumulatedDeltaRef = useRef<number>(0);
|
|
||||||
const lastPointerRef = useRef<{ x: number; y: number } | null>(null);
|
|
||||||
const lastStageRef = useRef<Konva.Stage | null>(null);
|
|
||||||
|
|
||||||
const handleWheel = useCallback((e: Konva.KonvaEventObject<WheelEvent>) => {
|
const handleWheel = useCallback((e: Konva.KonvaEventObject<WheelEvent>) => {
|
||||||
e.evt.preventDefault();
|
e.evt.preventDefault();
|
||||||
|
|
||||||
|
|
@ -108,30 +97,8 @@ export function useCanvasViewport({
|
||||||
const pointer = stage.getPointerPosition();
|
const pointer = stage.getPointerPosition();
|
||||||
if (!pointer) return;
|
if (!pointer) return;
|
||||||
|
|
||||||
// Accumulate deltaY from all events during throttle period
|
|
||||||
accumulatedDeltaRef.current += e.evt.deltaY;
|
|
||||||
lastPointerRef.current = pointer;
|
|
||||||
lastStageRef.current = stage;
|
|
||||||
|
|
||||||
// Skip if throttle already in progress
|
|
||||||
if (wheelThrottleRef.current !== null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Schedule update on next animation frame (~16ms)
|
|
||||||
wheelThrottleRef.current = requestAnimationFrame(() => {
|
|
||||||
const accumulatedDelta = accumulatedDeltaRef.current;
|
|
||||||
const pointer = lastPointerRef.current;
|
|
||||||
const stage = lastStageRef.current;
|
|
||||||
|
|
||||||
if (!pointer || !stage || accumulatedDelta === 0) {
|
|
||||||
wheelThrottleRef.current = null;
|
|
||||||
accumulatedDeltaRef.current = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const scaleBy = 1.1;
|
const scaleBy = 1.1;
|
||||||
const direction = accumulatedDelta > 0 ? -1 : 1;
|
const direction = e.evt.deltaY > 0 ? -1 : 1;
|
||||||
|
|
||||||
setStageScale((oldScale) => {
|
setStageScale((oldScale) => {
|
||||||
const newScale = Math.max(
|
const newScale = Math.max(
|
||||||
|
|
@ -146,20 +113,6 @@ export function useCanvasViewport({
|
||||||
|
|
||||||
return newScale;
|
return newScale;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Reset accumulator and throttle
|
|
||||||
wheelThrottleRef.current = null;
|
|
||||||
accumulatedDeltaRef.current = 0;
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// Cleanup wheel throttle on unmount
|
|
||||||
useEffect(() => {
|
|
||||||
return () => {
|
|
||||||
if (wheelThrottleRef.current !== null) {
|
|
||||||
cancelAnimationFrame(wheelThrottleRef.current);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Zoom control handlers
|
// Zoom control handlers
|
||||||
|
|
@ -202,27 +155,6 @@ export function useCanvasViewport({
|
||||||
setStagePos({ x: containerSize.width / 2, y: containerSize.height / 2 });
|
setStagePos({ x: containerSize.width / 2, y: containerSize.height / 2 });
|
||||||
}, [initialScale, containerSize]);
|
}, [initialScale, containerSize]);
|
||||||
|
|
||||||
// Stage drag handlers - cursor updates immediately for better UX
|
|
||||||
const handleStageDragStart = useCallback(
|
|
||||||
(e: Konva.KonvaEventObject<DragEvent>) => {
|
|
||||||
const stage = e.target.getStage();
|
|
||||||
if (stage) {
|
|
||||||
stage.container().style.cursor = "grabbing";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleStageDragEnd = useCallback(
|
|
||||||
(e: Konva.KonvaEventObject<DragEvent>) => {
|
|
||||||
const stage = e.target.getStage();
|
|
||||||
if (stage) {
|
|
||||||
stage.container().style.cursor = "grab";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// State
|
// State
|
||||||
stagePos,
|
stagePos,
|
||||||
|
|
@ -234,7 +166,5 @@ export function useCanvasViewport({
|
||||||
handleZoomIn,
|
handleZoomIn,
|
||||||
handleZoomOut,
|
handleZoomOut,
|
||||||
handleZoomReset,
|
handleZoomReset,
|
||||||
handleStageDragStart,
|
|
||||||
handleStageDragEnd,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -113,8 +113,7 @@ export function usePatternTransform({
|
||||||
setPatternOffset(centerOffset.x, centerOffset.y);
|
setPatternOffset(centerOffset.x, centerOffset.y);
|
||||||
}, [pesData, setPatternOffset]);
|
}, [pesData, setPatternOffset]);
|
||||||
|
|
||||||
// Pattern drag handler - only updates state when drag is complete
|
// Pattern drag handlers
|
||||||
// Konva handles the visual drag internally, no need to update React state during drag
|
|
||||||
const handlePatternDragEnd = useCallback(
|
const handlePatternDragEnd = useCallback(
|
||||||
(e: Konva.KonvaEventObject<DragEvent>) => {
|
(e: Konva.KonvaEventObject<DragEvent>) => {
|
||||||
const newOffset = {
|
const newOffset = {
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,6 @@ import { onPatternDeleted } from "./storeEvents";
|
||||||
import { calculatePatternCenter } from "../components/PatternCanvas/patternCanvasHelpers";
|
import { calculatePatternCenter } from "../components/PatternCanvas/patternCanvasHelpers";
|
||||||
import { calculateRotatedBounds } from "../utils/rotationUtils";
|
import { calculateRotatedBounds } from "../utils/rotationUtils";
|
||||||
|
|
||||||
// Conditional logging for development only
|
|
||||||
const isDev = import.meta.env.DEV;
|
|
||||||
|
|
||||||
interface PatternState {
|
interface PatternState {
|
||||||
// Original pattern (pre-upload)
|
// Original pattern (pre-upload)
|
||||||
pesData: PesPatternData | null;
|
pesData: PesPatternData | null;
|
||||||
|
|
@ -82,17 +79,13 @@ export const usePatternStore = create<PatternState>((set) => ({
|
||||||
// Update pattern offset (for original pattern only)
|
// Update pattern offset (for original pattern only)
|
||||||
setPatternOffset: (x: number, y: number) => {
|
setPatternOffset: (x: number, y: number) => {
|
||||||
set({ patternOffset: { x, y } });
|
set({ patternOffset: { x, y } });
|
||||||
if (isDev) {
|
|
||||||
console.log("[PatternStore] Pattern offset changed:", { x, y });
|
console.log("[PatternStore] Pattern offset changed:", { x, y });
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Set pattern rotation (for original pattern only)
|
// Set pattern rotation (for original pattern only)
|
||||||
setPatternRotation: (rotation: number) => {
|
setPatternRotation: (rotation: number) => {
|
||||||
set({ patternRotation: rotation % 360 });
|
set({ patternRotation: rotation % 360 });
|
||||||
if (isDev) {
|
|
||||||
console.log("[PatternStore] Pattern rotation changed:", rotation);
|
console.log("[PatternStore] Pattern rotation changed:", rotation);
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Set uploaded pattern data (called after upload completes)
|
// Set uploaded pattern data (called after upload completes)
|
||||||
|
|
@ -108,17 +101,13 @@ export const usePatternStore = create<PatternState>((set) => ({
|
||||||
// Optionally set filename if provided (for resume/reconnect scenarios)
|
// Optionally set filename if provided (for resume/reconnect scenarios)
|
||||||
...(fileName && { currentFileName: fileName }),
|
...(fileName && { currentFileName: fileName }),
|
||||||
});
|
});
|
||||||
if (isDev) {
|
|
||||||
console.log("[PatternStore] Uploaded pattern set");
|
console.log("[PatternStore] Uploaded pattern set");
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Clear uploaded pattern (called when deleting from machine)
|
// Clear uploaded pattern (called when deleting from machine)
|
||||||
// This reverts to pre-upload state, keeping pesData so user can re-adjust and re-upload
|
// This reverts to pre-upload state, keeping pesData so user can re-adjust and re-upload
|
||||||
clearUploadedPattern: () => {
|
clearUploadedPattern: () => {
|
||||||
if (isDev) {
|
|
||||||
console.log("[PatternStore] CLEARING uploaded pattern...");
|
console.log("[PatternStore] CLEARING uploaded pattern...");
|
||||||
}
|
|
||||||
set({
|
set({
|
||||||
uploadedPesData: null,
|
uploadedPesData: null,
|
||||||
uploadedPatternOffset: { x: 0, y: 0 },
|
uploadedPatternOffset: { x: 0, y: 0 },
|
||||||
|
|
@ -126,11 +115,9 @@ export const usePatternStore = create<PatternState>((set) => ({
|
||||||
// Keep pesData, currentFileName, patternOffset, patternRotation
|
// Keep pesData, currentFileName, patternOffset, patternRotation
|
||||||
// so user can adjust and re-upload
|
// so user can adjust and re-upload
|
||||||
});
|
});
|
||||||
if (isDev) {
|
|
||||||
console.log(
|
console.log(
|
||||||
"[PatternStore] Uploaded pattern cleared - back to editable mode",
|
"[PatternStore] Uploaded pattern cleared - back to editable mode",
|
||||||
);
|
);
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Reset pattern offset to default
|
// Reset pattern offset to default
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue