diff --git a/app/src-tauri/tauri.conf.json b/app/src-tauri/tauri.conf.json index 190d0370..c36e5e8e 100644 --- a/app/src-tauri/tauri.conf.json +++ b/app/src-tauri/tauri.conf.json @@ -21,7 +21,7 @@ } ], "security": { - "csp": "default-src 'self'; connect-src 'self' ipc: http://ipc.localhost ws://127.0.0.1:*; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; frame-src blob:; font-src 'self'" + "csp": "default-src 'self'; connect-src 'self' ipc: http://ipc.localhost ws://127.0.0.1:*; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; frame-src blob: http://127.0.0.1:*; font-src 'self'" } }, "plugins": { diff --git a/app/src/dev/preview.ts b/app/src/dev/preview.ts index e397c48a..c59f0a5c 100644 --- a/app/src/dev/preview.ts +++ b/app/src/dev/preview.ts @@ -14,6 +14,7 @@ import { seedBrowser } from "./seedBrowser"; import { seedChats } from "./seedChats"; import { seedChief } from "./seedChief"; import { seedRoutines } from "./seedRoutines"; +import { seedScreens } from "./seedScreens"; export function previewProps(search: string): { host: Host; connect: Connect } { const params = new URLSearchParams(search); @@ -113,6 +114,7 @@ function seed(fake: FakeBotloft): void { }); seedRoutines(fake, { scout: scout.id, analyst: analyst.id }); seedBrowser(fake, scout.id); + seedScreens(fake, research.id); const ops = fake.addCrew("Ops"); const deploy = fake.addBot(ops.id, "Deploy", "Ships the site on Fridays"); const watcher = fake.addBot(ops.id, "Watcher", "Keeps an eye on the error log"); diff --git a/app/src/dev/seedScreens.ts b/app/src/dev/seedScreens.ts new file mode 100644 index 00000000..f9b297d6 --- /dev/null +++ b/app/src/dev/seedScreens.ts @@ -0,0 +1,72 @@ +// Dev only: a Designer drawing screens in the fake preview, so the design +// area has something live to show. The page arrives in pieces, as the +// daemon's drafts do while the model writes it. + +import type { FakeBotloft } from "../lib/fake"; +import type { CrewId } from "../lib/protocol.gen"; + +const LANDING = ` +Padaria Aurora + + +
+

Pão quente, todo dia às 6h.

+

Fermentação natural de 36 horas, farinha orgânica e um forno a lenha que não apaga desde 1987.

+Ver o cardápio
+
SourdoughCasca crocante, miolo aberto.
+
Croissant81 camadas de manteiga francesa.
+
Bolo de fubáA receita da vó, sem mudar nada.
+`; + +const APP = ` + +
Encomendas
+
2 SourdoughR$ 38
+
6 CroissantsR$ 54
+
Bolo de fubáR$ 29
`; + +/** A Designer that draws the landing page again and again. */ +export function seedScreens(fake: FakeBotloft, crewId: CrewId): void { + const designer = fake.addBot(crewId, "Designer", "Draws the bakery's screens"); + fake.setBotState(designer.id, "busy", 1); + fake.screens.add(designer.id, "encomendas.html", APP, { + folder: "site", + device: "mobile", + at: fake.now - 60_000, + }); + const path = "C:\\Work\\site\\index.html"; + let written = 0; + let resting = 0; + setInterval(() => { + if (resting > 0) { + resting -= 1; + if (resting === 0) { + written = 0; + } + return; + } + written = Math.min(LANDING.length, written + 70); + const done = written === LANDING.length; + if (done) { + fake.screens.add(designer.id, "index.html", LANDING, { folder: "site" }); + resting = 30; + } + fake.screens.draft(designer.id, path, LANDING.slice(0, written), done); + }, 150); +} diff --git a/app/src/features/bots/BotHeader.tsx b/app/src/features/bots/BotHeader.tsx index b93bbdb4..4da45aff 100644 --- a/app/src/features/bots/BotHeader.tsx +++ b/app/src/features/bots/BotHeader.tsx @@ -5,6 +5,7 @@ import { Files, FolderOpen, Globe, + LayoutTemplate, PanelRight, Pause, Pencil, @@ -40,6 +41,9 @@ export function BotHeader({ browserOpen, browsing, onToggleBrowser, + screensOpen, + drawing, + onToggleScreens, }: { bot: Bot; crew: Crew; @@ -53,6 +57,10 @@ export function BotHeader({ /** The bot's browser is open (spec 21.8). */ browsing: boolean; onToggleBrowser(): void; + screensOpen: boolean; + /** The bot is writing a screen (spec 22.5). */ + drawing: boolean; + onToggleScreens(): void; }) { const t = useT(); const words = t.bots.header; @@ -115,6 +123,28 @@ export function BotHeader({ + + )} + {showScreen && tool.file && isScreenFile(tool.file) && tool.status !== "failed" && ( + + )} {showBrowser && isBrowserTool(tool.name) && (