PrintToVeraeTimeStamp/cmd/verae-print/platform_windows.go
George Lambert 48da24a661 feat: 2026 brand UI — statuslang, tray/menubar, CERT pdf, site kit
- Brand receipt status strings (statuslang) for notify/queue
- Windows tray + Start Menu/Startup install; macOS menubar helper
- CERT-01 plum/gold PDF + multihash/blake3 when present
- printit.verae.ai brand kit, queue page, customer-auth helper
- verae-print pending/tray-status/menubar commands
2026-10-13 21:11:32 -04:00

83 lines
2.6 KiB
Go

//go:build windows
package main
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/VeraeLLC/PrintToVeraeTimeStamp/internal/vlog"
)
func exeDir() string {
exe, err := os.Executable()
if err != nil {
return "."
}
return filepath.Dir(exe)
}
// notifyUser: best-effort balloon via PowerShell (no extra deps). Always logs.
// BalloonTipClicked / DoubleClick open the live loopback /queue (PT-W3).
func notifyUser(title, body string) {
vlog.Printf("notify: %s — %s", title, body)
if os.Getenv("VERAE_NO_NOTIFY") == "1" {
return
}
esc := func(s string) string {
s = strings.ReplaceAll(s, "'", "''")
s = strings.ReplaceAll(s, "\r", " ")
s = strings.ReplaceAll(s, "\n", " ")
return s
}
queue := "http://127.0.0.1:8631/queue"
if serveListenAddr != "" && isLoopbackAddr(serveListenAddr) {
queue = queueURLFor(serveListenAddr)
} else if a := os.Getenv("VERAE_IPP_ADDR"); a != "" && isLoopbackAddr(a) {
queue = queueURLFor(a)
}
// STA + DoEvents so BalloonTipClicked can open /queue before dispose.
ps := fmt.Sprintf(`
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$q='%s'
$n=New-Object System.Windows.Forms.NotifyIcon
$n.Icon=[System.Drawing.SystemIcons]::Information
$n.Visible=$true
$n.Text='Verae Timestamping'
$open={ try { Start-Process $q } catch {} }
$n.add_BalloonTipClicked($open)
$n.add_DoubleClick($open)
$n.ShowBalloonTip(8000,'%s','%s',[System.Windows.Forms.ToolTipIcon]::Info)
$sw=[Diagnostics.Stopwatch]::StartNew()
while($sw.Elapsed.TotalSeconds -lt 9){ [System.Windows.Forms.Application]::DoEvents(); Start-Sleep -Milliseconds 120 }
$n.Visible=$false; $n.Dispose()
`, esc(queue), esc(title), esc(body))
cmd := exec.Command("powershell.exe", "-NoProfile", "-STA", "-WindowStyle", "Hidden", "-Command", ps)
hideWindow(cmd)
_ = cmd.Start()
}
func notify(title, subtitle string) { notifyUser(title, subtitle) }
func openFolderPath(p string) { _ = exec.Command("explorer.exe", p).Start() }
func runInstallPrinterWindows() int {
script := filepath.Join(exeDir(), "..", "scripts", "install-printer.ps1")
ps := filepath.Join(os.Getenv("WINDIR"), "System32", "WindowsPowerShell", "v1.0", "powershell.exe")
cmd := exec.Command(ps, "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", script)
cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
if err := cmd.Run(); err != nil {
fmt.Fprintf(os.Stderr, "install-printer failed: %v (run elevated; see %s)\n", err, vlog.Dir())
return 1
}
return 0
}
func debugFromRegistry() bool {
out, err := exec.Command("reg.exe", "query", `HKLM\Software\Verae\PrintStamp`, "/v", "Debug").Output()
return err == nil && strings.Contains(string(out), "0x1")
}