Use USB descriptors and MTP identity instead of the static libmtp product label. Monitor attachment, discard stale UI responses, clear disconnected views, and release slow MTP sessions in the background while preserving operation serialization. Publish 0.1.1 with immutable source history. Cover discovery, names, unplugging and slow disconnect with native and UI regressions. Verify real Pura 70 Ultra identity and prompt disconnect; run the newest published backend during Git-source checks.
145 lines
3.7 KiB
JavaScript
145 lines
3.7 KiB
JavaScript
// 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: "<script>alert(1)</script>.txt",
|
|
folder: false,
|
|
size: 48,
|
|
modified: 1788998400,
|
|
},
|
|
{
|
|
id: 6,
|
|
parent: 2,
|
|
storage: 1,
|
|
name: "旅行计划.pdf",
|
|
folder: false,
|
|
size: 1123988,
|
|
modified: 1788998400,
|
|
},
|
|
];
|
|
window.__TROVE_CONTEXT__ = {
|
|
curioId: "dev.trove.harmony-connector",
|
|
version: "0.1.1",
|
|
instanceId: "ui-fixture",
|
|
platform: "macos",
|
|
};
|
|
window.__TROVE_BRIDGE__ = createMockBridge({
|
|
"@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;
|
|
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");
|