feat(studio): the desktop-app button says Install the desktop app and never dead-ends (#5854)

* feat(studio): the header's desktop-app button says Install the desktop app and never dead-ends

The button now reads "Install the desktop app" beside Framey drawn as the app
draws it. Where the app is installed, a press opens this project in it; a
folder preview serves from a bare index.html gets its hyperframes.json first,
so the app no longer refuses it. Without the app, the button links straight to
hyperframes.dev's download, and a failed open lands there too. Platforms with
no build of the app show no button. Telemetry now records eligibility, one
impression, the click and the press outcome, with OS, app installed and
download available.

* feat(studio): the desktop-app button records eligibility, impression, click and outcome

* feat(studio): a desktop-app press carries its page id to the download and the app hand-off

* chore(studio): describe Framey's drawing without internal names

* feat(studio): the desktop-app button opens a guide that walks download, install and open

Without the app, the header button opens a card where Framey walks three steps: the
download opens in a new tab, the install is found by asking the preview server while the
card is open, and the project opens through the existing hand-off. A failed hand-off shows
the folder to copy and Try again. With the app ready the press opens the project directly.
Each step change is recorded through trackStudioEvent; a download is never counted as an
install.

* fix(studio): the desktop-app guide counts one install per page

The app removed and found again on the same page recorded install_detected twice; a page
latch keeps it to one, as the telemetry contract says.
This commit is contained in:
Miguel Ángel
2026-10-18 17:34:56 -04:00
committed by GitHub
parent b46ebedeae
commit 5975dd7579
10 changed files with 1332 additions and 146 deletions
+1 -1
View File
@@ -52,7 +52,7 @@ const GET_RESPONSES = new Map([
// interesting assertion is that the shell mounts clean, not that a blocking
// notice renders. The notice has its own tests.
["/api/environment/ffmpeg", json({ ok: true })],
// The header's Edit with Framey asks this on load; shown, so the shell mounts with it.
// The header's "Install the desktop app" asks this on load; shown, so the shell mounts with it.
[
"/api/open-in-desktop",
json({