Critical bug fixes for the conditions of initial workspace setup and additions to the build scripts which now should fetch all the build dependencies automatically on all platforms.
This commit is contained in:
parent
5d09f56e00
commit
968fd5a6c4
34
README.md
34
README.md
|
|
@ -30,13 +30,39 @@ A desktop application for generating 3D-printable solder paste stencils and snap
|
|||
|
||||
### Requirements
|
||||
|
||||
- [Go](https://go.dev/dl/) 1.21+
|
||||
- [Wails CLI](https://wails.io/docs/gettingstarted/installation): `go install github.com/wailsapp/wails/v2/cmd/wails@latest`
|
||||
- [Node.js](https://nodejs.org/) 18+ (for frontend build)
|
||||
- macOS: Xcode Command Line Tools (`xcode-select --install`)
|
||||
#### macOS
|
||||
|
||||
1. Install [Homebrew](https://brew.sh/) (if not already installed)
|
||||
2. Install dependencies:
|
||||
```bash
|
||||
brew install go node
|
||||
xcode-select --install # Xcode Command Line Tools
|
||||
go install github.com/wailsapp/wails/v2/cmd/wails@latest
|
||||
```
|
||||
|
||||
#### Windows
|
||||
|
||||
1. Install dependencies (using [winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/), built into Windows 10/11):
|
||||
```powershell
|
||||
winget install GoLang.Go
|
||||
winget install OpenJS.NodeJS.LTS
|
||||
go install github.com/wailsapp/wails/v2/cmd/wails@latest
|
||||
```
|
||||
Or download manually: [Go](https://go.dev/dl/) 1.21+, [Node.js](https://nodejs.org/) 18+
|
||||
2. **WebView2 Runtime** — required by Wails. Pre-installed on most Windows 10/11 machines with Edge. If missing, download from [Microsoft](https://developer.microsoft.com/en-us/microsoft-edge/webview2/).
|
||||
|
||||
#### Version Summary
|
||||
|
||||
| Tool | Minimum | Install docs |
|
||||
|------|---------|--------------|
|
||||
| Go | 1.21+ | https://go.dev/dl/ |
|
||||
| Node.js | 18+ | https://nodejs.org/ |
|
||||
| Wails CLI | v2 | https://wails.io/docs/gettingstarted/installation |
|
||||
|
||||
### Build
|
||||
|
||||
The build scripts check for missing dependencies and print install instructions if anything is missing.
|
||||
|
||||
**macOS:**
|
||||
```bash
|
||||
./build.sh
|
||||
|
|
|
|||
61
app.go
61
app.go
|
|
@ -143,6 +143,7 @@ func (a *App) autosaveCutouts() {
|
|||
}
|
||||
|
||||
func (a *App) startup(ctx context.Context) {
|
||||
debugLog("app.startup() called")
|
||||
a.ctx = ctx
|
||||
|
||||
// Render and cache the logo (PNG for favicon, SVG for background art)
|
||||
|
|
@ -153,15 +154,19 @@ func (a *App) startup(ctx context.Context) {
|
|||
a.imageServer.Store("/api/logo.png", buf.Bytes())
|
||||
}
|
||||
a.imageServer.Store("/api/logo.svg", formerLogoSVG)
|
||||
debugLog("app.startup() done, logo stored (svg=%d bytes)", len(formerLogoSVG))
|
||||
}
|
||||
|
||||
// ======== Landing Page ========
|
||||
|
||||
func (a *App) GetRecentProjects() []ProjectInfoJS {
|
||||
debugLog("GetRecentProjects() called")
|
||||
entries, err := ListProjects(20)
|
||||
if err != nil {
|
||||
debugLog("GetRecentProjects() error: %v", err)
|
||||
return nil
|
||||
}
|
||||
debugLog("GetRecentProjects() found %d projects", len(entries))
|
||||
var result []ProjectInfoJS
|
||||
for _, e := range entries {
|
||||
name := e.Data.ProjectName
|
||||
|
|
@ -194,6 +199,13 @@ func (a *App) GetLogoDataURL() string {
|
|||
return "data:image/png;base64," + base64.StdEncoding.EncodeToString(buf.Bytes())
|
||||
}
|
||||
|
||||
func (a *App) GetLogoSVGDataURL() string {
|
||||
if len(formerLogoSVG) == 0 {
|
||||
return ""
|
||||
}
|
||||
return "data:image/svg+xml;base64," + base64.StdEncoding.EncodeToString(formerLogoSVG)
|
||||
}
|
||||
|
||||
// ======== File Dialogs ========
|
||||
|
||||
func (a *App) SelectFile(title string, patterns string) (string, error) {
|
||||
|
|
@ -300,10 +312,15 @@ func (a *App) DiscoverGerberFiles(folderPath string) ([]string, error) {
|
|||
}
|
||||
|
||||
func (a *App) BuildEnclosureSession(gbrjobPath string, gerberPaths []string, drillPath, npthPath string, wallThickness, wallHeight, clearance, dpi float64, exports []string) error {
|
||||
debugLog("BuildEnclosureSession() called: gbrjob=%s gerbers=%d drill=%q npth=%q", gbrjobPath, len(gerberPaths), drillPath, npthPath)
|
||||
debugLog(" params: wallThick=%.2f wallH=%.2f clearance=%.2f dpi=%.0f exports=%v", wallThickness, wallHeight, clearance, dpi, exports)
|
||||
|
||||
if gbrjobPath == "" {
|
||||
debugLog(" ERROR: no gerber job file selected")
|
||||
return fmt.Errorf("no gerber job file selected")
|
||||
}
|
||||
if len(gerberPaths) == 0 {
|
||||
debugLog(" ERROR: no gerber files selected")
|
||||
return fmt.Errorf("no gerber files selected")
|
||||
}
|
||||
|
||||
|
|
@ -329,12 +346,21 @@ func (a *App) BuildEnclosureSession(gbrjobPath string, gerberPaths []string, dri
|
|||
exports = []string{"stl", "scad"}
|
||||
}
|
||||
|
||||
os.MkdirAll("temp", 0755)
|
||||
tempDir := formerTempDir()
|
||||
cwd, _ := os.Getwd()
|
||||
debugLog(" CWD=%s, tempDir=%s", cwd, tempDir)
|
||||
if err := os.MkdirAll(tempDir, 0755); err != nil {
|
||||
debugLog(" ERROR creating temp dir: %v", err)
|
||||
return fmt.Errorf("failed to create temp dir: %v", err)
|
||||
}
|
||||
uuid := randomID()
|
||||
debugLog(" session uuid=%s", uuid)
|
||||
|
||||
// Copy gbrjob
|
||||
gbrjobDst := filepath.Join("temp", uuid+"_"+filepath.Base(gbrjobPath))
|
||||
gbrjobDst := filepath.Join(tempDir, uuid+"_"+filepath.Base(gbrjobPath))
|
||||
debugLog(" copying gbrjob %s -> %s", gbrjobPath, gbrjobDst)
|
||||
if err := CopyFile(gbrjobPath, gbrjobDst); err != nil {
|
||||
debugLog(" ERROR copy gbrjob: %v", err)
|
||||
return fmt.Errorf("failed to copy gbrjob: %v", err)
|
||||
}
|
||||
|
||||
|
|
@ -343,8 +369,10 @@ func (a *App) BuildEnclosureSession(gbrjobPath string, gerberPaths []string, dri
|
|||
var sourceDir string
|
||||
for _, src := range gerberPaths {
|
||||
baseName := filepath.Base(src)
|
||||
dst := filepath.Join("temp", uuid+"_"+baseName)
|
||||
dst := filepath.Join(tempDir, uuid+"_"+baseName)
|
||||
debugLog(" copying gerber %s -> %s", src, dst)
|
||||
if err := CopyFile(src, dst); err != nil {
|
||||
debugLog(" ERROR copy gerber %s: %v", baseName, err)
|
||||
return fmt.Errorf("failed to copy %s: %v", baseName, err)
|
||||
}
|
||||
savedGerbers[baseName] = dst
|
||||
|
|
@ -356,36 +384,46 @@ func (a *App) BuildEnclosureSession(gbrjobPath string, gerberPaths []string, dri
|
|||
// Copy drill files
|
||||
var drillDst, npthDst string
|
||||
if drillPath != "" {
|
||||
drillDst = filepath.Join("temp", uuid+"_drill"+filepath.Ext(drillPath))
|
||||
drillDst = filepath.Join(tempDir, uuid+"_drill"+filepath.Ext(drillPath))
|
||||
debugLog(" copying drill %s -> %s", drillPath, drillDst)
|
||||
if err := CopyFile(drillPath, drillDst); err != nil {
|
||||
debugLog(" ERROR copy drill: %v", err)
|
||||
return fmt.Errorf("failed to copy PTH drill: %v", err)
|
||||
}
|
||||
}
|
||||
if npthPath != "" {
|
||||
npthDst = filepath.Join("temp", uuid+"_npth"+filepath.Ext(npthPath))
|
||||
npthDst = filepath.Join(tempDir, uuid+"_npth"+filepath.Ext(npthPath))
|
||||
debugLog(" copying npth %s -> %s", npthPath, npthDst)
|
||||
if err := CopyFile(npthPath, npthDst); err != nil {
|
||||
debugLog(" ERROR copy npth: %v", err)
|
||||
return fmt.Errorf("failed to copy NPTH drill: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
debugLog(" calling core BuildEnclosureSession...")
|
||||
_, session, err := BuildEnclosureSession(gbrjobDst, savedGerbers, drillDst, npthDst, ecfg, exports)
|
||||
if err != nil {
|
||||
debugLog(" ERROR session build: %v", err)
|
||||
return fmt.Errorf("session build failed: %v", err)
|
||||
}
|
||||
debugLog(" session built OK: project=%s board=%.1fx%.1fmm", session.ProjectName, session.BoardW, session.BoardH)
|
||||
session.SourceDir = sourceDir
|
||||
|
||||
a.mu.Lock()
|
||||
a.enclosureSession = session
|
||||
a.cutouts = nil
|
||||
a.mu.Unlock()
|
||||
debugLog(" session stored in app state")
|
||||
|
||||
// Render board preview
|
||||
if session.OutlineImg != nil {
|
||||
var buf bytes.Buffer
|
||||
png.Encode(&buf, session.OutlineImg)
|
||||
a.imageServer.Store("/api/board-preview.png", buf.Bytes())
|
||||
debugLog(" board preview rendered (%d bytes)", buf.Len())
|
||||
}
|
||||
|
||||
debugLog("BuildEnclosureSession() returning nil (success)")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -605,6 +643,7 @@ func (a *App) ClearLidCutouts() {
|
|||
}
|
||||
|
||||
func (a *App) GenerateEnclosureOutputs() (*GenerateResultJS, error) {
|
||||
debugLog("GenerateEnclosureOutputs() called")
|
||||
a.mu.RLock()
|
||||
session := a.enclosureSession
|
||||
allCutouts := make([]Cutout, len(a.cutouts))
|
||||
|
|
@ -612,18 +651,22 @@ func (a *App) GenerateEnclosureOutputs() (*GenerateResultJS, error) {
|
|||
a.mu.RUnlock()
|
||||
|
||||
if session == nil {
|
||||
debugLog(" ERROR: no enclosure session active")
|
||||
return nil, fmt.Errorf("no enclosure session active")
|
||||
}
|
||||
|
||||
outputDir := session.SourceDir
|
||||
if outputDir == "" {
|
||||
outputDir = filepath.Join(".", "temp")
|
||||
outputDir = formerTempDir()
|
||||
}
|
||||
debugLog(" outputDir=%s cutouts=%d", outputDir, len(allCutouts))
|
||||
|
||||
files, err := GenerateEnclosureOutputs(session, allCutouts, outputDir)
|
||||
if err != nil {
|
||||
debugLog(" ERROR generate: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
debugLog(" generated %d files", len(files))
|
||||
|
||||
// Auto-save session
|
||||
inst := InstanceData{
|
||||
|
|
@ -643,7 +686,7 @@ func (a *App) GenerateEnclosureOutputs() (*GenerateResultJS, error) {
|
|||
ProjectName: session.ProjectName,
|
||||
Cutouts: allCutouts,
|
||||
}
|
||||
if savedDir, saveErr := SaveSession(inst, filepath.Join(".", "temp"), session.OutlineImg); saveErr != nil {
|
||||
if savedDir, saveErr := SaveSession(inst, formerTempDir(), session.OutlineImg); saveErr != nil {
|
||||
log.Printf("Warning: could not save session: %v", saveErr)
|
||||
} else {
|
||||
a.mu.Lock()
|
||||
|
|
@ -697,7 +740,7 @@ func (a *App) SaveEnclosureProfile(name string) error {
|
|||
}
|
||||
sourceDir := session.SourceDir
|
||||
if sourceDir == "" {
|
||||
sourceDir = filepath.Join(".", "temp")
|
||||
sourceDir = formerTempDir()
|
||||
}
|
||||
savedDir, err := SaveProfile(inst, name, sourceDir, session.OutlineImg)
|
||||
if err == nil && savedDir != "" {
|
||||
|
|
@ -961,7 +1004,7 @@ func (a *App) GetOutputDir() (string, error) {
|
|||
|
||||
outputDir := session.SourceDir
|
||||
if outputDir == "" {
|
||||
outputDir = filepath.Join(".", "temp")
|
||||
outputDir = formerTempDir()
|
||||
}
|
||||
|
||||
absDir, err := filepath.Abs(outputDir)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,56 @@
|
|||
@echo off
|
||||
REM Build Former for Windows — run this on a Windows machine with Go and Wails installed
|
||||
REM Prerequisites: Go 1.21+, Wails CLI (go install github.com/wailsapp/wails/v2/cmd/wails@latest)
|
||||
REM Build Former for Windows
|
||||
setlocal
|
||||
|
||||
REM --- Dependency checks ---
|
||||
set "missing="
|
||||
|
||||
where go >nul 2>&1
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
set "missing=1"
|
||||
echo ERROR: Go not found.
|
||||
echo Install: winget install GoLang.Go
|
||||
echo Or download from https://go.dev/dl/
|
||||
echo.
|
||||
)
|
||||
|
||||
where node >nul 2>&1
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
set "missing=1"
|
||||
echo ERROR: Node.js not found.
|
||||
echo Install: winget install OpenJS.NodeJS.LTS
|
||||
echo Or download from https://nodejs.org/
|
||||
echo.
|
||||
)
|
||||
|
||||
where wails >nul 2>&1
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
set "missing=1"
|
||||
echo ERROR: Wails CLI not found.
|
||||
echo Install: go install github.com/wailsapp/wails/v2/cmd/wails@latest
|
||||
echo Docs: https://wails.io/docs/gettingstarted/installation
|
||||
echo.
|
||||
)
|
||||
|
||||
REM Check for WebView2 runtime (required by Wails on Windows)
|
||||
reg query "HKLM\SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" >nul 2>&1
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
reg query "HKLM\SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" >nul 2>&1
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
set "missing=1"
|
||||
echo ERROR: WebView2 runtime not found.
|
||||
echo Usually pre-installed on Windows 10/11 with Edge.
|
||||
echo Download: https://developer.microsoft.com/en-us/microsoft-edge/webview2/
|
||||
echo.
|
||||
)
|
||||
)
|
||||
|
||||
if defined missing (
|
||||
echo Install the tools listed above and re-run this script.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
REM --- Build ---
|
||||
echo Generating app icon...
|
||||
go run ./cmd/genicon 2>nul && echo Icon generated. || echo Icon generation skipped.
|
||||
|
||||
|
|
@ -14,3 +63,4 @@ if %ERRORLEVEL% NEQ 0 (
|
|||
|
||||
echo.
|
||||
echo Done: build\bin\Former.exe
|
||||
endlocal
|
||||
|
|
|
|||
|
|
@ -2,6 +2,49 @@
|
|||
# Cross-compile Former for Windows (amd64) from macOS/Linux
|
||||
set -e
|
||||
|
||||
# --- Dependency checks ---
|
||||
missing=()
|
||||
|
||||
if ! command -v go &>/dev/null; then
|
||||
missing+=("go")
|
||||
echo "ERROR: Go not found."
|
||||
if [[ "$OSTYPE" == darwin* ]]; then
|
||||
echo " Install: brew install go"
|
||||
else
|
||||
echo " Install: sudo apt install golang (or your distro's package manager)"
|
||||
fi
|
||||
echo " Or download from https://go.dev/dl/"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if ! command -v node &>/dev/null; then
|
||||
missing+=("node")
|
||||
echo "ERROR: Node.js not found."
|
||||
if [[ "$OSTYPE" == darwin* ]]; then
|
||||
echo " Install: brew install node"
|
||||
else
|
||||
echo " Install: sudo apt install nodejs npm (or your distro's package manager)"
|
||||
fi
|
||||
echo " Or download from https://nodejs.org/"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if ! command -v wails &>/dev/null && [ ! -x "$HOME/go/bin/wails" ]; then
|
||||
missing+=("wails")
|
||||
echo "ERROR: Wails CLI not found."
|
||||
echo " Install: go install github.com/wailsapp/wails/v2/cmd/wails@latest"
|
||||
echo " Docs: https://wails.io/docs/gettingstarted/installation"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if [ ${#missing[@]} -gt 0 ]; then
|
||||
echo "Missing dependencies: ${missing[*]}"
|
||||
echo "Install the tools listed above and re-run this script."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Build ---
|
||||
|
||||
# Generate app icon (needs CGO on macOS for native SVG rendering)
|
||||
echo "Generating app icon..."
|
||||
if [[ "$OSTYPE" == darwin* ]]; then
|
||||
|
|
|
|||
42
build.sh
42
build.sh
|
|
@ -1,6 +1,48 @@
|
|||
#!/bin/bash
|
||||
# Build Former for macOS
|
||||
set -e
|
||||
|
||||
# --- Dependency checks ---
|
||||
missing=()
|
||||
|
||||
if ! command -v go &>/dev/null; then
|
||||
missing+=("go")
|
||||
echo "ERROR: Go not found."
|
||||
echo " Install: brew install go"
|
||||
echo " Or download from https://go.dev/dl/"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if ! command -v node &>/dev/null; then
|
||||
missing+=("node")
|
||||
echo "ERROR: Node.js not found."
|
||||
echo " Install: brew install node"
|
||||
echo " Or download from https://nodejs.org/"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if ! command -v wails &>/dev/null && [ ! -x "$HOME/go/bin/wails" ]; then
|
||||
missing+=("wails")
|
||||
echo "ERROR: Wails CLI not found."
|
||||
echo " Install: go install github.com/wailsapp/wails/v2/cmd/wails@latest"
|
||||
echo " Docs: https://wails.io/docs/gettingstarted/installation"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if ! xcode-select -p &>/dev/null; then
|
||||
missing+=("xcode-cli")
|
||||
echo "ERROR: Xcode Command Line Tools not found."
|
||||
echo " Install: xcode-select --install"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if [ ${#missing[@]} -gt 0 ]; then
|
||||
echo "Missing dependencies: ${missing[*]}"
|
||||
echo "Install the tools listed above and re-run this script."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Build ---
|
||||
pkill -f "Former.app" || true
|
||||
sleep 0.5
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
#!/bin/bash
|
||||
# Build Former for macOS — DEBUG mode (logs to ~/former/debug.log)
|
||||
set -e
|
||||
pkill -f "Former.app" || true
|
||||
sleep 0.5
|
||||
|
||||
export SDKROOT=$(xcrun --show-sdk-path)
|
||||
export CC=/usr/bin/clang
|
||||
export CGO_ENABLED=1
|
||||
|
||||
WAILS=$(command -v wails || echo "$HOME/go/bin/wails")
|
||||
|
||||
# Generate app icon from Former.svg
|
||||
echo "Generating app icon..."
|
||||
go run ./cmd/genicon 2>/dev/null && echo "Icon generated." || echo "Icon generation skipped."
|
||||
|
||||
echo "Building Former (DEBUG)..."
|
||||
"$WAILS" build -skipbindings -tags debug
|
||||
|
||||
echo ""
|
||||
echo "Debug build complete. Logs will be written to ~/former/debug.log"
|
||||
echo "Launching..."
|
||||
open build/bin/Former.app
|
||||
|
||||
# Tail the log so you can see it live
|
||||
sleep 1
|
||||
echo ""
|
||||
echo "=== Tailing ~/former/debug.log (Ctrl-C to stop) ==="
|
||||
tail -f ~/former/debug.log 2>/dev/null || echo "Waiting for log file..."
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
//go:build !debug
|
||||
|
||||
package main
|
||||
|
||||
func debugLog(format string, args ...interface{}) {}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
//go:build debug
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
var debugLogger *log.Logger
|
||||
|
||||
func init() {
|
||||
home, _ := os.UserHomeDir()
|
||||
logDir := filepath.Join(home, "former")
|
||||
os.MkdirAll(logDir, 0755)
|
||||
logPath := filepath.Join(logDir, "debug.log")
|
||||
|
||||
f, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
|
||||
if err != nil {
|
||||
// Fall back to stderr
|
||||
debugLogger = log.New(os.Stderr, "[DEBUG] ", log.Ltime|log.Lshortfile)
|
||||
debugLogger.Printf("Could not open %s: %v — logging to stderr", logPath, err)
|
||||
return
|
||||
}
|
||||
|
||||
debugLogger = log.New(f, "[DEBUG] ", log.Ltime|log.Lshortfile)
|
||||
debugLogger.Printf("=== Former debug session started %s ===", time.Now().Format(time.RFC3339))
|
||||
debugLogger.Printf("Log file: %s", logPath)
|
||||
fmt.Fprintf(os.Stderr, "[Former] Debug logging to %s\n", logPath)
|
||||
}
|
||||
|
||||
func debugLog(format string, args ...interface{}) {
|
||||
if debugLogger != nil {
|
||||
debugLogger.Printf(format, args...)
|
||||
}
|
||||
}
|
||||
|
|
@ -53,8 +53,7 @@ function navigate(page) {
|
|||
async function initLanding() {
|
||||
const page = $('#page-landing');
|
||||
const projects = await wails()?.GetRecentProjects() || [];
|
||||
|
||||
let logoSrc = '/api/logo.png';
|
||||
const logoSrc = await wails()?.GetLogoSVGDataURL() || '';
|
||||
|
||||
let projectsHTML = '';
|
||||
if (projects.length > 0) {
|
||||
|
|
@ -73,13 +72,11 @@ async function initLanding() {
|
|||
}
|
||||
|
||||
page.innerHTML = `
|
||||
<div class="landing-bg-art">
|
||||
<img src="/api/logo.svg" alt="" class="landing-bg-logo" onerror="this.style.display='none'">
|
||||
</div>
|
||||
<div class="landing-hero">
|
||||
<h1>Former</h1>
|
||||
<p>PCB Stencil & Enclosure Generator</p>
|
||||
</div>
|
||||
${logoSrc ? `<div class="landing-bg-art"><img src="${logoSrc}" alt="" class="landing-bg-logo"></div>` : ''}
|
||||
<div class="landing-actions">
|
||||
<div class="action-card" onclick="navigate('stencil')">
|
||||
<h3>New Stencil</h3>
|
||||
|
|
@ -286,19 +283,19 @@ function initEnclosure() {
|
|||
<div class="card-title">Parameters</div>
|
||||
<div class="form-row">
|
||||
<span class="form-label">Wall Thickness (mm)</span>
|
||||
<input class="form-input" id="enc-wall-thick" type="number" step="0.1" placeholder="1.5">
|
||||
<input class="form-input" id="enc-wall-thick" type="number" step="0.1" value="1.5">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<span class="form-label">Wall Height (mm)</span>
|
||||
<input class="form-input" id="enc-wall-height" type="number" step="0.1" placeholder="10.0">
|
||||
<input class="form-input" id="enc-wall-height" type="number" step="0.1" value="10.0">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<span class="form-label">Clearance (mm)</span>
|
||||
<input class="form-input" id="enc-clearance" type="number" step="0.1" placeholder="0.3">
|
||||
<input class="form-input" id="enc-clearance" type="number" step="0.1" value="0.3">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<span class="form-label">DPI</span>
|
||||
<input class="form-input" id="enc-dpi" type="number" step="1" placeholder="600">
|
||||
<input class="form-input" id="enc-dpi" type="number" step="1" value="600">
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
|
|
@ -415,8 +412,16 @@ async function buildEnclosure() {
|
|||
if ($('#enc-svg')?.checked) exports.push('svg');
|
||||
if ($('#enc-png')?.checked) exports.push('png');
|
||||
|
||||
console.log('[Former] buildEnclosure: gbrjob=' + state.enclosure.gbrjobPath +
|
||||
' gerbers=' + state.enclosure.gerberPaths.length +
|
||||
' drill=' + state.enclosure.drillPath +
|
||||
' npth=' + state.enclosure.npthPath +
|
||||
' exports=' + exports.join(','));
|
||||
console.log('[Former] wails() =', wails());
|
||||
|
||||
showLoading('Building enclosure session...');
|
||||
try {
|
||||
console.log('[Former] calling BuildEnclosureSession...');
|
||||
await wails().BuildEnclosureSession(
|
||||
state.enclosure.gbrjobPath,
|
||||
state.enclosure.gerberPaths,
|
||||
|
|
@ -428,9 +433,11 @@ async function buildEnclosure() {
|
|||
parseFloat($('#enc-dpi')?.value) || 0,
|
||||
exports,
|
||||
);
|
||||
console.log('[Former] BuildEnclosureSession succeeded, navigating to preview');
|
||||
hideLoading();
|
||||
navigate('preview');
|
||||
} catch (e) {
|
||||
console.error('[Former] BuildEnclosureSession FAILED:', e);
|
||||
hideLoading();
|
||||
alert('Session build failed: ' + e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,8 +134,6 @@ body {
|
|||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: -8px;
|
||||
margin-bottom: -60px;
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
-webkit-mask-image: linear-gradient(to bottom, rgba(0,0,0,1) 20%, rgba(0,0,0,0.5) 100%);
|
||||
|
|
|
|||
5
main.go
5
main.go
|
|
@ -45,8 +45,11 @@ func main() {
|
|||
}
|
||||
|
||||
// Ensure working directories exist
|
||||
os.MkdirAll("temp", 0755)
|
||||
cwd, _ := os.Getwd()
|
||||
debugLog("CWD: %s", cwd)
|
||||
debugLog("Ensuring ~/former dirs (includes temp)...")
|
||||
ensureFormerDirs()
|
||||
debugLog("Startup complete, launching GUI")
|
||||
|
||||
runGUI()
|
||||
}
|
||||
|
|
|
|||
19
storage.go
19
storage.go
|
|
@ -17,6 +17,10 @@ func formerBaseDir() string {
|
|||
return filepath.Join(home, "former")
|
||||
}
|
||||
|
||||
func formerTempDir() string {
|
||||
return filepath.Join(formerBaseDir(), "temp")
|
||||
}
|
||||
|
||||
func formerSessionsDir() string {
|
||||
return filepath.Join(formerBaseDir(), "sessions")
|
||||
}
|
||||
|
|
@ -26,8 +30,19 @@ func formerProfilesDir() string {
|
|||
}
|
||||
|
||||
func ensureFormerDirs() {
|
||||
os.MkdirAll(formerSessionsDir(), 0755)
|
||||
os.MkdirAll(formerProfilesDir(), 0755)
|
||||
td := formerTempDir()
|
||||
sd := formerSessionsDir()
|
||||
pd := formerProfilesDir()
|
||||
debugLog("ensureFormerDirs: temp=%s sessions=%s profiles=%s", td, sd, pd)
|
||||
if err := os.MkdirAll(td, 0755); err != nil {
|
||||
debugLog(" ERROR creating temp dir: %v", err)
|
||||
}
|
||||
if err := os.MkdirAll(sd, 0755); err != nil {
|
||||
debugLog(" ERROR creating sessions dir: %v", err)
|
||||
}
|
||||
if err := os.MkdirAll(pd, 0755); err != nil {
|
||||
debugLog(" ERROR creating profiles dir: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// ProjectEntry represents a saved project on disk
|
||||
|
|
|
|||
Loading…
Reference in New Issue