Compare commits
1 Commits
v0.4.9-dem
...
68a50d10b1
| Author | SHA1 | Date | |
|---|---|---|---|
| 68a50d10b1 |
87
CLAUDE.md
87
CLAUDE.md
@@ -2568,6 +2568,93 @@ raw string that is two literal characters and Postgres requires exactly one —
|
|||||||
it would have failed the **whole** customer search at runtime, on a query no
|
it would have failed the **whole** customer search at runtime, on a query no
|
||||||
in-memory test executes.
|
in-memory test executes.
|
||||||
|
|
||||||
|
## The desktop app on two platforms, and three bugs found by launching it
|
||||||
|
|
||||||
|
All three were reported or found by *starting the app the way a person
|
||||||
|
starts one*, and all three had survived every test.
|
||||||
|
|
||||||
|
### "Open dashboard" in the tray did nothing reliable
|
||||||
|
|
||||||
|
`runtime.Show` was wrong three times over and the first is why it failed
|
||||||
|
rather than merely misbehaved. Wails implements `Show()` as a bare
|
||||||
|
`mainWindow.Show()` while `WindowShow()` wraps the identical work in
|
||||||
|
`runtime.LockOSThread`. Win32 window operations must run on the thread owning
|
||||||
|
the window's message pump, and the tray handler runs on the **systray's**
|
||||||
|
goroutine, which never is.
|
||||||
|
|
||||||
|
Two more, each sufficient alone: showing is not un-minimising (hidden and
|
||||||
|
minimised are different states), and Windows refuses the foreground to a
|
||||||
|
process that does not already hold it — so the window returned *behind*
|
||||||
|
whatever was being looked at. A tray click is by definition a moment when the
|
||||||
|
app is not in front, so that is every time, not an edge case. The
|
||||||
|
always-on-top flip is the ordinary way to ask, and it is why this runs in a
|
||||||
|
goroutine: a menu loop that sleeps is a tray that ignores the next click.
|
||||||
|
|
||||||
|
`OnSecondInstanceLaunch` had the same shape and is hit far more often —
|
||||||
|
double-clicking the desktop icon while the app is already running.
|
||||||
|
|
||||||
|
### The engine inherited whatever directory launched the app
|
||||||
|
|
||||||
|
Nothing ever set `cmd.Dir`, so the child took the parent's — and an app
|
||||||
|
started by double-clicking its bundle is handed `/`. On macOS the symptom was
|
||||||
|
`python: No module named behavision` forever, because the dev engine runs as
|
||||||
|
`-m behavision`, which resolves against the working directory.
|
||||||
|
|
||||||
|
**The same app launched from a terminal inside the repo worked perfectly**,
|
||||||
|
which is the shape of a bug that survives every test a developer runs.
|
||||||
|
`Config.EngineDir` (empty = install root) is set by both launchers, which had
|
||||||
|
identical code and the identical omission.
|
||||||
|
|
||||||
|
### macOS is a supported DEVELOPER target, not a product
|
||||||
|
|
||||||
|
Indian retail counters are Windows. A Mac product means an Apple Developer
|
||||||
|
account, notarisation, a second installer, and DPAPI having no macOS
|
||||||
|
equivalent — a permanent second platform for customers who do not have Macs.
|
||||||
|
What it *is* worth is demoing on the machine this is written on.
|
||||||
|
|
||||||
|
It cost one missing framework and then two crashes:
|
||||||
|
|
||||||
|
```
|
||||||
|
link Undefined symbols: _OBJC_CLASS_$_UTType
|
||||||
|
Wails' darwin frontend references it and does not link
|
||||||
|
UniformTypeIdentifiers. Fails at the LINK step after compiling
|
||||||
|
everything, so it reads like a broken toolchain.
|
||||||
|
systray.Run SIGTRAP in cgo — nativeLoop takes the macOS main
|
||||||
|
run loop and Wails already has it
|
||||||
|
RunWithExternalLoop "NSWindow should only be instantiated on the main
|
||||||
|
thread!" — still builds AppKit objects, and
|
||||||
|
OnStartup is not the main thread
|
||||||
|
```
|
||||||
|
|
||||||
|
So **there is no tray on macOS**, and the consequence is handled rather than
|
||||||
|
left: with no tray there is no way back from a hidden window and no way to
|
||||||
|
quit, so on macOS closing the window quits and stops the engine. Same rule the
|
||||||
|
tray's Quit follows — never leave it watching with no visible control.
|
||||||
|
|
||||||
|
**The window could not be maximised**, and that was an omission with a precise
|
||||||
|
consequence. Wails computes `zoomable` *inside* `if frontendOptions.Mac !=
|
||||||
|
nil`; the variable defaults to 0, and the native side then does
|
||||||
|
`if (!zoomable && resizable) [zoomButton setEnabled: NO]`. There was a
|
||||||
|
`Windows` options block and no `Mac` one — so the platform that was configured
|
||||||
|
behaved and the platform that was not looked broken.
|
||||||
|
|
||||||
|
### A macOS release costs nothing extra, and the reason is worth keeping
|
||||||
|
|
||||||
|
`release.sh` has never used PyInstaller. The Windows package is a **source
|
||||||
|
install**: a pure-Python wheel plus `behavision-setup`, which builds a venv on
|
||||||
|
the target machine, done that way because PyInstaller cannot cross-compile.
|
||||||
|
macOS therefore needs nothing new — same wheel, same setup tool, a natively
|
||||||
|
built `.app` instead of the `.exe`. `MAC=1 ./release.sh` opts in.
|
||||||
|
|
||||||
|
Not notarised, and that is stated in the notes rather than discovered: macOS
|
||||||
|
*blocks* an unsigned download rather than warning like SmartScreen, so a first
|
||||||
|
launch needs right-click → Open.
|
||||||
|
|
||||||
|
Verified by extracting the published zip to a clean directory: signature
|
||||||
|
intact through the round trip, the app runs, and it reports *"engine not
|
||||||
|
installed yet; run behavision-setup, then Start"* — the correct fresh-machine
|
||||||
|
state rather than a crash.
|
||||||
|
|
||||||
## Setting up on a new machine
|
## Setting up on a new machine
|
||||||
|
|
||||||
1. Copy the `Behavision` folder **including `.env`** (gitignored, holds
|
1. Copy the `Behavision` folder **including `.env`** (gitignored, holds
|
||||||
|
|||||||
Reference in New Issue
Block a user