// Explicit browser-only UI fixture. Never included in a .curio package. import { createMockBridge } from "./sdk/index.js"; const root = 0xffffffff; const device = { id: "fixture", name: "daniel", model: "HUAWEI Pura 70 Ultra", manufacturer: "模拟设备", }; const storages = [ { id: 1, name: "内部存储", capacity: 256 * 1024 ** 3, free: 128 * 1024 ** 3 }, ]; let attached = true, connection = null, job = null, next = 30; const entries = [ { id: 2, parent: root, storage: 1, name: "Documents", folder: true, size: 0, modified: 0, }, { id: 3, parent: root, storage: 1, name: "DCIM", folder: true, size: 0, modified: 0, }, { id: 4, parent: root, storage: 1, name: "设计稿 🎨 final.zip", folder: false, size: 52_423_111, modified: 1788998400, }, { id: 5, parent: root, storage: 1, name: ".txt", folder: false, size: 48, modified: 1788998400, }, { id: 6, parent: 2, storage: 1, name: "旅行计划.pdf", folder: false, size: 1123988, modified: 1788998400, }, ]; let screenId = 0, screenSequence = 0, screenControl = false; let lastInput = "等待操作"; function screenFrame() { if (!attached) throw new Error("设备已断开(模拟)"); const canvas = document.createElement("canvas"); canvas.width = 600; canvas.height = 1200; const context = canvas.getContext("2d"); const gradient = context.createLinearGradient(0, 0, 600, 1200); gradient.addColorStop(0, "#183958"); gradient.addColorStop(1, "#3d1d52"); context.fillStyle = gradient; context.fillRect(0, 0, 600, 1200); context.fillStyle = "#fff"; context.textAlign = "center"; context.font = "bold 70px sans-serif"; context.fillText("Harmony", 300, 260); context.font = "26px sans-serif"; context.fillText("投屏界面预览 · 模拟画面", 300, 320); context.fillStyle = "#e9dcff"; context.fillText(lastInput, 300, 600, 550); context.fillText(`画面 ${++screenSequence}`, 300, 670); context.fillStyle = "#fff"; context.fillRect(225, 1150, 150, 6); return { dataUrl: canvas.toDataURL("image/jpeg", 0.8), width: 600, height: 1200, geometry: 1, sequence: screenSequence, captureMs: 180, control: screenControl, }; } window.__TROVE_CONTEXT__ = { curioId: "dev.trove.harmony-connector", version: "0.3.0", instanceId: "ui-fixture", platform: "macos", }; window.__TROVE_BRIDGE__ = createMockBridge({ "@self.hdc.screenStart": () => { screenControl = false; return { session: ++screenId, control: false, inputCapabilities: [ "click", "doubleClick", "longClick", "swipe", "drag", "text", "keyEvent", ], }; }, "@self.hdc.screenFrame": screenFrame, "@self.hdc.screenStop": () => ({ stopped: true }), "@self.hdc.screenControl": ({ enabled }) => ({ control: (screenControl = enabled), }), "@self.hdc.screenInput": ({ input }) => { lastInput = input.kind === "text" ? input.text : input.kind === "key" ? input.key : `${input.kind} · ${input.x}, ${input.y}`; return { executed: true }; }, "@self.hdc.screenSave": () => ({ path: "/ui-fixture/screen.jpg" }), "@self.hdc.status": () => ({ busy: false, job: null }), "@self.hdc.tool": () => ({ available: true, version: "HDC · 模拟数据", path: "/fixture/official-sdk/hdc", }), "@self.hdc.devices": () => ({ devices: attached ? [{ id: "fixture-device", transport: "USB", state: "Connected" }] : [], }), "@self.hdc.inspect": () => ({ capabilities: Object.fromEntries( ["apps", "launch", "screenshot", "logs", "report"].map((key) => [ key, { available: true }, ]), ), info: { text: "HUAWEI Pura 70 Ultra · 界面测试数据" }, }), "@self.hdc.apps": () => ({ apps: ["com.example.gallery", "com.example.notes", "com.example.reader"], }), "@self.hdc.app": ({ bundle }) => ({ bundle, versionName: "1.2.0", versionCode: 12, debug: bundle.endsWith("notes"), abilities: [{ name: "Home", module: "entry" }], details: {}, }), "@self.info": () => ({ connection, busy: false }), "@self.devices": () => ({ devices: attached ? [device] : [] }), "@self.monitor": () => ({ connection, devices: attached ? [device] : [], busy: job?.state === "running", }), "@self.connect": () => (connection = { device, storages }), "@self.disconnect": () => { connection = null; job = null; return { disconnected: true }; }, "@self.list": ({ parent, offset = 0 }) => { const all = entries.filter((e) => e.parent === parent); return { entries: all.slice(offset, offset + 500), total: all.length }; }, "@self.mkdir": ({ name, storage, parent }) => { entries.push({ id: next++, name, storage, parent, folder: true, size: 0, modified: 0, }); return { id: next - 1 }; }, "@self.transfer": () => { job = { id: 1, state: "running", sent: 0, total: 10 * 1024 ** 2 }; return { id: 1 }; }, "@self.transferStatus": () => { if (job?.state === "running") { job.sent += 524288; job.statistics = { bytesPerSecond: 1310720, averageBytesPerSecond: 1210720, elapsedSeconds: job.sent / 1310720, remainingSeconds: (job.total - job.sent) / 1310720, filesTotal: 3, filesCompleted: Math.floor((job.sent / job.total) * 3), currentFile: "Documents/设计稿.zip", }; if (job.sent >= job.total) { job.state = "completed"; job.result = { name: "界面测试文件", bytes: job.total }; } } return job; }, "@self.cancelTransfer": () => { job.state = "cancelled"; job.error = { message: "模拟取消已完成。" }; connection = null; return { requested: true }; }, "host.dialog.openFile": () => ({ path: "/ui-fixture/example.txt" }), "host.dialog.openDirectory": () => ({ path: "/ui-fixture/downloads" }), }); const badge = document.createElement("div"); badge.textContent = "界面测试 · 模拟设备,不执行真实文件传输"; badge.style.cssText = "position:fixed;bottom:3px;left:240px;z-index:10;background:#805800;color:white;padding:4px 8px;border-radius:5px;font-size:10px"; document.body.append(badge); const toggle = document.createElement("button"); toggle.textContent = "模拟拔掉 USB"; toggle.style.cssText = "position:fixed;bottom:30px;left:16px;z-index:10;background:#805800;color:white"; toggle.addEventListener("click", () => { attached = !attached; if (!attached) { connection = null; if (job?.state === "running") { job.state = "failed"; job.error = { message: "设备已断开(模拟)" }; } } toggle.textContent = attached ? "模拟拔掉 USB" : "模拟接入 USB"; }); document.body.append(toggle); await import("./app.js");