diff --git a/foundry/packages/backend/src/actors/workspace/app-shell.ts b/foundry/packages/backend/src/actors/workspace/app-shell.ts index aff0fe18..8ac6b400 100644 --- a/foundry/packages/backend/src/actors/workspace/app-shell.ts +++ b/foundry/packages/backend/src/actors/workspace/app-shell.ts @@ -245,6 +245,7 @@ async function buildAppSnapshot(c: any, sessionId: string): Promise organization.id), } diff --git a/foundry/packages/client/src/mock-app.ts b/foundry/packages/client/src/mock-app.ts index 61dadd27..bcc5ea85 100644 --- a/foundry/packages/client/src/mock-app.ts +++ b/foundry/packages/client/src/mock-app.ts @@ -12,6 +12,7 @@ export interface MockFoundryUser { name: string; email: string; githubLogin: string; + avatarUrl: string | null; roleLabel: string; eligibleOrganizationIds: string[]; } @@ -22,6 +23,8 @@ export interface MockFoundryOrganizationMember { email: string; role: "owner" | "admin" | "member"; state: "active" | "invited"; + avatarUrl: string | null; + githubLogin: string | null; } export interface MockFoundryInvoice { @@ -162,6 +165,7 @@ function buildDefaultSnapshot(): MockFoundryAppSnapshot { name: "Nathan", email: "nathan@acme.dev", githubLogin: "nathan", + avatarUrl: "https://github.com/NathanFlurry.png", roleLabel: "Founder", eligibleOrganizationIds: ["personal-nathan", "acme", "rivet"], }, @@ -170,6 +174,7 @@ function buildDefaultSnapshot(): MockFoundryAppSnapshot { name: "Maya", email: "maya@acme.dev", githubLogin: "maya", + avatarUrl: "https://github.com/octocat.png", roleLabel: "Staff Engineer", eligibleOrganizationIds: ["acme"], }, @@ -178,6 +183,7 @@ function buildDefaultSnapshot(): MockFoundryAppSnapshot { name: "Jamie", email: "jamie@rivet.dev", githubLogin: "jamie", + avatarUrl: "https://github.com/defunkt.png", roleLabel: "Platform Lead", eligibleOrganizationIds: ["personal-jamie", "rivet"], }, @@ -213,7 +219,17 @@ function buildDefaultSnapshot(): MockFoundryAppSnapshot { paymentMethodLabel: "No card required", invoices: [], }, - members: [{ id: "member-nathan", name: "Nathan", email: "nathan@acme.dev", role: "owner", state: "active" }], + members: [ + { + id: "member-nathan", + name: "Nathan", + email: "nathan@acme.dev", + role: "owner", + state: "active", + avatarUrl: "https://github.com/NathanFlurry.png", + githubLogin: "NathanFlurry", + }, + ], seatAssignments: ["nathan@acme.dev"], repoCatalog: ["nathan/personal-site"], }, @@ -251,10 +267,34 @@ function buildDefaultSnapshot(): MockFoundryAppSnapshot { ], }, members: [ - { id: "member-acme-nathan", name: "Nathan", email: "nathan@acme.dev", role: "owner", state: "active" }, - { id: "member-acme-maya", name: "Maya", email: "maya@acme.dev", role: "admin", state: "active" }, - { id: "member-acme-priya", name: "Priya", email: "priya@acme.dev", role: "member", state: "active" }, - { id: "member-acme-devon", name: "Devon", email: "devon@acme.dev", role: "member", state: "invited" }, + { + id: "member-acme-nathan", + name: "Nathan", + email: "nathan@acme.dev", + role: "owner", + state: "active", + avatarUrl: "https://github.com/NathanFlurry.png", + githubLogin: "NathanFlurry", + }, + { + id: "member-acme-maya", + name: "Maya", + email: "maya@acme.dev", + role: "admin", + state: "active", + avatarUrl: "https://github.com/octocat.png", + githubLogin: "octocat", + }, + { + id: "member-acme-priya", + name: "Priya", + email: "priya@acme.dev", + role: "member", + state: "active", + avatarUrl: "https://github.com/mona.png", + githubLogin: "mona", + }, + { id: "member-acme-devon", name: "Devon", email: "devon@acme.dev", role: "member", state: "invited", avatarUrl: null, githubLogin: null }, ], seatAssignments: ["nathan@acme.dev", "maya@acme.dev"], repoCatalog: ["acme/backend", "acme/frontend", "acme/infra"], @@ -290,9 +330,33 @@ function buildDefaultSnapshot(): MockFoundryAppSnapshot { invoices: [{ id: "inv-rivet-001", label: "Team pilot", issuedAt: "2026-03-04", amountUsd: 0, status: "paid" }], }, members: [ - { id: "member-rivet-jamie", name: "Jamie", email: "jamie@rivet.dev", role: "owner", state: "active" }, - { id: "member-rivet-nathan", name: "Nathan", email: "nathan@acme.dev", role: "member", state: "active" }, - { id: "member-rivet-lena", name: "Lena", email: "lena@rivet.dev", role: "admin", state: "active" }, + { + id: "member-rivet-jamie", + name: "Jamie", + email: "jamie@rivet.dev", + role: "owner", + state: "active", + avatarUrl: "https://github.com/defunkt.png", + githubLogin: "defunkt", + }, + { + id: "member-rivet-nathan", + name: "Nathan", + email: "nathan@acme.dev", + role: "member", + state: "active", + avatarUrl: "https://github.com/NathanFlurry.png", + githubLogin: "NathanFlurry", + }, + { + id: "member-rivet-lena", + name: "Lena", + email: "lena@rivet.dev", + role: "admin", + state: "active", + avatarUrl: "https://github.com/mojombo.png", + githubLogin: "mojombo", + }, ], seatAssignments: ["jamie@rivet.dev"], repoCatalog: ["rivet/dashboard", "rivet/agents", "rivet/billing", "rivet/infrastructure"], @@ -327,7 +391,17 @@ function buildDefaultSnapshot(): MockFoundryAppSnapshot { paymentMethodLabel: "No card required", invoices: [], }, - members: [{ id: "member-jamie", name: "Jamie", email: "jamie@rivet.dev", role: "owner", state: "active" }], + members: [ + { + id: "member-jamie", + name: "Jamie", + email: "jamie@rivet.dev", + role: "owner", + state: "active", + avatarUrl: "https://github.com/defunkt.png", + githubLogin: "defunkt", + }, + ], seatAssignments: ["jamie@rivet.dev"], repoCatalog: ["jamie/demo-app"], }, diff --git a/foundry/packages/client/src/mock/workbench-client.ts b/foundry/packages/client/src/mock/workbench-client.ts index f27c4363..fc2ce668 100644 --- a/foundry/packages/client/src/mock/workbench-client.ts +++ b/foundry/packages/client/src/mock/workbench-client.ts @@ -100,6 +100,7 @@ class MockWorkbenchStore implements TaskWorkbenchClient { diffs: {}, fileTree: [], minutesUsed: 0, + presence: [], }; this.updateState((current) => ({ diff --git a/foundry/packages/client/src/workbench-model.ts b/foundry/packages/client/src/workbench-model.ts index 42cff084..01a75fb1 100644 --- a/foundry/packages/client/src/workbench-model.ts +++ b/foundry/packages/client/src/workbench-model.ts @@ -435,6 +435,10 @@ export function buildInitialTasks(): Task[] { }, ], minutesUsed: 42, + presence: [ + { memberId: "member-acme-nathan", name: "Nathan", avatarUrl: "https://github.com/NathanFlurry.png", lastSeenAtMs: minutesAgo(1) }, + { memberId: "member-acme-maya", name: "Maya", avatarUrl: "https://github.com/octocat.png", lastSeenAtMs: minutesAgo(0), typing: true }, + ], }, { id: "h2", @@ -535,6 +539,7 @@ export function buildInitialTasks(): Task[] { }, ], minutesUsed: 187, + presence: [{ memberId: "member-acme-priya", name: "Priya", avatarUrl: "https://github.com/mona.png", lastSeenAtMs: minutesAgo(0) }], }, { id: "h3", @@ -609,6 +614,7 @@ export function buildInitialTasks(): Task[] { }, ], minutesUsed: 23, + presence: [], }, // ── rivet-dev/rivet ── { @@ -744,6 +750,11 @@ export function buildInitialTasks(): Task[] { }, ], minutesUsed: 5, + presence: [ + { memberId: "member-acme-nathan", name: "Nathan", avatarUrl: "https://github.com/NathanFlurry.png", lastSeenAtMs: minutesAgo(0) }, + { memberId: "member-acme-maya", name: "Maya", avatarUrl: "https://github.com/octocat.png", lastSeenAtMs: minutesAgo(2) }, + { memberId: "member-acme-priya", name: "Priya", avatarUrl: "https://github.com/mona.png", lastSeenAtMs: minutesAgo(5) }, + ], }, { id: "h5", @@ -800,6 +811,7 @@ export function buildInitialTasks(): Task[] { diffs: {}, fileTree: [], minutesUsed: 312, + presence: [{ memberId: "member-acme-maya", name: "Maya", avatarUrl: "https://github.com/octocat.png", lastSeenAtMs: minutesAgo(45) }], }, // ── rivet-dev/cloud ── { @@ -909,6 +921,7 @@ export function buildInitialTasks(): Task[] { }, ], minutesUsed: 0, + presence: [], }, // ── rivet-dev/engine-ee ── { @@ -1023,6 +1036,7 @@ export function buildInitialTasks(): Task[] { }, ], minutesUsed: 78, + presence: [], }, // ── rivet-dev/engine-ee (archived) ── { @@ -1065,6 +1079,7 @@ export function buildInitialTasks(): Task[] { diffs: {}, fileTree: [], minutesUsed: 15, + presence: [], }, // ── rivet-dev/secure-exec ── { @@ -1118,6 +1133,7 @@ export function buildInitialTasks(): Task[] { diffs: {}, fileTree: [], minutesUsed: 3, + presence: [], }, ]; } diff --git a/foundry/packages/desktop/package.json b/foundry/packages/desktop/package.json index 825d62d4..e3b8c966 100644 --- a/foundry/packages/desktop/package.json +++ b/foundry/packages/desktop/package.json @@ -5,10 +5,16 @@ "type": "module", "scripts": { "dev": "tauri dev", + "dev:ios": "VITE_MOBILE=1 tauri ios dev", + "dev:android": "VITE_MOBILE=1 tauri android dev", "build": "tauri build", + "build:ios": "tauri ios build", + "build:android": "tauri android build", "build:sidecar": "tsx scripts/build-sidecar.ts", "build:frontend": "tsx scripts/build-frontend.ts", + "build:frontend:mobile": "tsx scripts/build-frontend-mobile.ts", "build:all": "pnpm build:sidecar && pnpm build:frontend && pnpm build", + "build:all:ios": "pnpm build:frontend:mobile && pnpm build:ios", "tauri": "tauri" }, "devDependencies": { diff --git a/foundry/packages/desktop/scripts/build-frontend-mobile.ts b/foundry/packages/desktop/scripts/build-frontend-mobile.ts new file mode 100644 index 00000000..38d02a48 --- /dev/null +++ b/foundry/packages/desktop/scripts/build-frontend-mobile.ts @@ -0,0 +1,42 @@ +import { execSync } from "node:child_process"; +import { cpSync, readFileSync, writeFileSync, rmSync, existsSync } from "node:fs"; +import { resolve, dirname } from "node:path"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const desktopRoot = resolve(__dirname, ".."); +const repoRoot = resolve(desktopRoot, "../../.."); +const frontendDist = resolve(desktopRoot, "../frontend/dist"); +const destDir = resolve(desktopRoot, "frontend-dist"); + +function run(cmd: string, opts?: { cwd?: string; env?: NodeJS.ProcessEnv }) { + console.log(`> ${cmd}`); + execSync(cmd, { + stdio: "inherit", + cwd: opts?.cwd ?? repoRoot, + env: { ...process.env, ...opts?.env }, + }); +} + +// Step 1: Build the frontend for mobile (no hardcoded backend endpoint) +console.log("\n=== Building frontend for mobile ===\n"); +run("pnpm --filter @sandbox-agent/foundry-frontend build", { + env: { + VITE_MOBILE: "1", + }, +}); + +// Step 2: Copy dist to frontend-dist/ +console.log("\n=== Copying frontend build output ===\n"); +if (existsSync(destDir)) { + rmSync(destDir, { recursive: true }); +} +cpSync(frontendDist, destDir, { recursive: true }); + +// Step 3: Strip react-scan script from index.html (it loads unconditionally) +const indexPath = resolve(destDir, "index.html"); +let html = readFileSync(indexPath, "utf-8"); +html = html.replace(/]*><\/script>\s*/g, ""); +writeFileSync(indexPath, html); + +console.log("\n=== Mobile frontend build complete ===\n"); diff --git a/foundry/packages/desktop/src-tauri/Cargo.toml b/foundry/packages/desktop/src-tauri/Cargo.toml index bf861889..2dab87f4 100644 --- a/foundry/packages/desktop/src-tauri/Cargo.toml +++ b/foundry/packages/desktop/src-tauri/Cargo.toml @@ -3,13 +3,20 @@ name = "foundry" version = "0.1.0" edition = "2021" +[lib] +crate-type = ["staticlib", "cdylib", "lib"] + [build-dependencies] tauri-build = { version = "2", features = [] } [dependencies] tauri = { version = "2", features = [] } -tauri-plugin-shell = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" reqwest = { version = "0.12", features = ["json"] } tokio = { version = "1", features = ["time"] } + +# Shell plugin is desktop-only (used for sidecar spawning). +# Exclude iOS and Android targets. +[target.'cfg(not(any(target_os = "ios", target_os = "android")))'.dependencies] +tauri-plugin-shell = "2" diff --git a/foundry/packages/desktop/src-tauri/capabilities/default.json b/foundry/packages/desktop/src-tauri/capabilities/default.json index 1275b582..c13d51d2 100644 --- a/foundry/packages/desktop/src-tauri/capabilities/default.json +++ b/foundry/packages/desktop/src-tauri/capabilities/default.json @@ -2,6 +2,7 @@ "identifier": "default", "description": "Default capability for Foundry desktop", "windows": ["main"], + "platforms": ["macOS", "windows", "linux"], "permissions": [ "core:default", "core:window:allow-start-dragging", diff --git a/foundry/packages/desktop/src-tauri/capabilities/mobile.json b/foundry/packages/desktop/src-tauri/capabilities/mobile.json new file mode 100644 index 00000000..fc0e328e --- /dev/null +++ b/foundry/packages/desktop/src-tauri/capabilities/mobile.json @@ -0,0 +1,7 @@ +{ + "identifier": "mobile", + "description": "Capability for Foundry mobile (iOS/Android)", + "windows": ["main"], + "platforms": ["iOS", "android"], + "permissions": ["core:default"] +} diff --git a/foundry/packages/desktop/src-tauri/gen/apple/.gitignore b/foundry/packages/desktop/src-tauri/gen/apple/.gitignore new file mode 100644 index 00000000..6726e2f8 --- /dev/null +++ b/foundry/packages/desktop/src-tauri/gen/apple/.gitignore @@ -0,0 +1,3 @@ +xcuserdata/ +build/ +Externals/ diff --git a/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@1x.png b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@1x.png new file mode 100644 index 00000000..a6ac2a8c Binary files /dev/null and b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@1x.png differ diff --git a/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@2x-1.png b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@2x-1.png new file mode 100644 index 00000000..2869541f Binary files /dev/null and b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@2x-1.png differ diff --git a/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@2x.png b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@2x.png new file mode 100644 index 00000000..2869541f Binary files /dev/null and b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@2x.png differ diff --git a/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@3x.png b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@3x.png new file mode 100644 index 00000000..cf265a45 Binary files /dev/null and b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-20x20@3x.png differ diff --git a/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@1x.png b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@1x.png new file mode 100644 index 00000000..29c9746c Binary files /dev/null and b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@1x.png differ diff --git a/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@2x-1.png b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@2x-1.png new file mode 100644 index 00000000..a4e68c8d Binary files /dev/null and b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@2x-1.png differ diff --git a/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@2x.png b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@2x.png new file mode 100644 index 00000000..a4e68c8d Binary files /dev/null and b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@2x.png differ diff --git a/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@3x.png b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@3x.png new file mode 100644 index 00000000..e4adcbce Binary files /dev/null and b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-29x29@3x.png differ diff --git a/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@1x.png b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@1x.png new file mode 100644 index 00000000..2869541f Binary files /dev/null and b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@1x.png differ diff --git a/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@2x-1.png b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@2x-1.png new file mode 100644 index 00000000..a414e65b Binary files /dev/null and b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@2x-1.png differ diff --git a/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@2x.png b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@2x.png new file mode 100644 index 00000000..a414e65b Binary files /dev/null and b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@2x.png differ diff --git a/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@3x.png b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@3x.png new file mode 100644 index 00000000..a0807e5d Binary files /dev/null and b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-40x40@3x.png differ diff --git a/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png new file mode 100644 index 00000000..704c9291 Binary files /dev/null and b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png differ diff --git a/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-60x60@2x.png b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-60x60@2x.png new file mode 100644 index 00000000..a0807e5d Binary files /dev/null and b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-60x60@2x.png differ diff --git a/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-60x60@3x.png b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-60x60@3x.png new file mode 100644 index 00000000..2a9fbc26 Binary files /dev/null and b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-60x60@3x.png differ diff --git a/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-76x76@1x.png b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-76x76@1x.png new file mode 100644 index 00000000..2cdf1848 Binary files /dev/null and b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-76x76@1x.png differ diff --git a/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-76x76@2x.png b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-76x76@2x.png new file mode 100644 index 00000000..4723e4b4 Binary files /dev/null and b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-76x76@2x.png differ diff --git a/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-83.5x83.5@2x.png b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-83.5x83.5@2x.png new file mode 100644 index 00000000..f26fee45 Binary files /dev/null and b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/AppIcon-83.5x83.5@2x.png differ diff --git a/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/Contents.json b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..dd3b8bcc --- /dev/null +++ b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,116 @@ +{ + "images": [ + { + "size": "20x20", + "idiom": "iphone", + "filename": "AppIcon-20x20@2x.png", + "scale": "2x" + }, + { + "size": "20x20", + "idiom": "iphone", + "filename": "AppIcon-20x20@3x.png", + "scale": "3x" + }, + { + "size": "29x29", + "idiom": "iphone", + "filename": "AppIcon-29x29@2x-1.png", + "scale": "2x" + }, + { + "size": "29x29", + "idiom": "iphone", + "filename": "AppIcon-29x29@3x.png", + "scale": "3x" + }, + { + "size": "40x40", + "idiom": "iphone", + "filename": "AppIcon-40x40@2x.png", + "scale": "2x" + }, + { + "size": "40x40", + "idiom": "iphone", + "filename": "AppIcon-40x40@3x.png", + "scale": "3x" + }, + { + "size": "60x60", + "idiom": "iphone", + "filename": "AppIcon-60x60@2x.png", + "scale": "2x" + }, + { + "size": "60x60", + "idiom": "iphone", + "filename": "AppIcon-60x60@3x.png", + "scale": "3x" + }, + { + "size": "20x20", + "idiom": "ipad", + "filename": "AppIcon-20x20@1x.png", + "scale": "1x" + }, + { + "size": "20x20", + "idiom": "ipad", + "filename": "AppIcon-20x20@2x-1.png", + "scale": "2x" + }, + { + "size": "29x29", + "idiom": "ipad", + "filename": "AppIcon-29x29@1x.png", + "scale": "1x" + }, + { + "size": "29x29", + "idiom": "ipad", + "filename": "AppIcon-29x29@2x.png", + "scale": "2x" + }, + { + "size": "40x40", + "idiom": "ipad", + "filename": "AppIcon-40x40@1x.png", + "scale": "1x" + }, + { + "size": "40x40", + "idiom": "ipad", + "filename": "AppIcon-40x40@2x-1.png", + "scale": "2x" + }, + { + "size": "76x76", + "idiom": "ipad", + "filename": "AppIcon-76x76@1x.png", + "scale": "1x" + }, + { + "size": "76x76", + "idiom": "ipad", + "filename": "AppIcon-76x76@2x.png", + "scale": "2x" + }, + { + "size": "83.5x83.5", + "idiom": "ipad", + "filename": "AppIcon-83.5x83.5@2x.png", + "scale": "2x" + }, + { + "size": "1024x1024", + "idiom": "ios-marketing", + "filename": "AppIcon-512@2x.png", + "scale": "1x" + } + ], + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/Contents.json b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/Contents.json new file mode 100644 index 00000000..97a8662e --- /dev/null +++ b/foundry/packages/desktop/src-tauri/gen/apple/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info": { + "version": 1, + "author": "xcode" + } +} diff --git a/foundry/packages/desktop/src-tauri/gen/apple/ExportOptions.plist b/foundry/packages/desktop/src-tauri/gen/apple/ExportOptions.plist new file mode 100644 index 00000000..0428a171 --- /dev/null +++ b/foundry/packages/desktop/src-tauri/gen/apple/ExportOptions.plist @@ -0,0 +1,8 @@ + + + + + method + debugging + + diff --git a/foundry/packages/desktop/src-tauri/gen/apple/LaunchScreen.storyboard b/foundry/packages/desktop/src-tauri/gen/apple/LaunchScreen.storyboard new file mode 100644 index 00000000..81b5f90e --- /dev/null +++ b/foundry/packages/desktop/src-tauri/gen/apple/LaunchScreen.storyboard @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/foundry/packages/desktop/src-tauri/gen/apple/Podfile b/foundry/packages/desktop/src-tauri/gen/apple/Podfile new file mode 100644 index 00000000..110c0814 --- /dev/null +++ b/foundry/packages/desktop/src-tauri/gen/apple/Podfile @@ -0,0 +1,21 @@ +# Uncomment the next line to define a global platform for your project + +target 'foundry_iOS' do +platform :ios, '14.0' + # Pods for foundry_iOS +end + +target 'foundry_macOS' do +platform :osx, '11.0' + # Pods for foundry_macOS +end + +# Delete the deployment target for iOS and macOS, causing it to be inherited from the Podfile +post_install do |installer| + installer.pods_project.targets.each do |target| + target.build_configurations.each do |config| + config.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET' + config.build_settings.delete 'MACOSX_DEPLOYMENT_TARGET' + end + end +end diff --git a/foundry/packages/desktop/src-tauri/gen/apple/Sources/foundry/bindings/bindings.h b/foundry/packages/desktop/src-tauri/gen/apple/Sources/foundry/bindings/bindings.h new file mode 100644 index 00000000..51522007 --- /dev/null +++ b/foundry/packages/desktop/src-tauri/gen/apple/Sources/foundry/bindings/bindings.h @@ -0,0 +1,8 @@ +#pragma once + +namespace ffi { + extern "C" { + void start_app(); + } +} + diff --git a/foundry/packages/desktop/src-tauri/gen/apple/Sources/foundry/main.mm b/foundry/packages/desktop/src-tauri/gen/apple/Sources/foundry/main.mm new file mode 100644 index 00000000..7793a9d5 --- /dev/null +++ b/foundry/packages/desktop/src-tauri/gen/apple/Sources/foundry/main.mm @@ -0,0 +1,6 @@ +#include "bindings/bindings.h" + +int main(int argc, char * argv[]) { + ffi::start_app(); + return 0; +} diff --git a/foundry/packages/desktop/src-tauri/gen/apple/foundry.xcodeproj/project.pbxproj b/foundry/packages/desktop/src-tauri/gen/apple/foundry.xcodeproj/project.pbxproj new file mode 100644 index 00000000..0d27a2cc --- /dev/null +++ b/foundry/packages/desktop/src-tauri/gen/apple/foundry.xcodeproj/project.pbxproj @@ -0,0 +1,460 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 77; + objects = { + +/* Begin PBXBuildFile section */ + 18AA2DEF7E37375920E5C2A0 /* assets in Resources */ = {isa = PBXBuildFile; fileRef = 5839511CE1969F167776E5BA /* assets */; }; + 41F61AA6A6395C0E1A22A01D /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C796B246B7EFC59BE22BEAE /* Metal.framework */; }; + 46451E98CD8CC918B270DF4E /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4CA3839E082C9EE1FBE47017 /* CoreGraphics.framework */; }; + 5823D1D3CF428AB8675028CA /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 916B38007890BE6F5229D88A /* QuartzCore.framework */; }; + 63828790DD4F121B20E1314C /* libapp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 61706E406133F9FEA10A02CF /* libapp.a */; }; + 6DF20201B9860B37359D8373 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7FB0AF0861142E98564AE14D /* WebKit.framework */; }; + 84F2A1451B638E04DC7D9C77 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0FFD378E56937244899E32B9 /* UIKit.framework */; }; + A391FE2BDE082320542B786E /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9503D8DA5A521E10DE980308 /* MetalKit.framework */; }; + A9D64B11D3591BA69A9FF24D /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 41768F9AEEC30C6F3A657349 /* main.mm */; }; + C2EC09AB9A1F311F389731DA /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 73239B7F777F17978C5F9FB3 /* LaunchScreen.storyboard */; }; + E05514D9EF3C91D648336FAF /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1BE59BDC6646E6E88C37132A /* Security.framework */; }; + EF8153BCCF98E828B21D22B8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2C2D23C60F5F67FF1B8EF9BE /* Assets.xcassets */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 0FFD378E56937244899E32B9 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 1BE59BDC6646E6E88C37132A /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + 2C2D23C60F5F67FF1B8EF9BE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 41768F9AEEC30C6F3A657349 /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = ""; }; + 46675940F25D441B14F4D9BD /* bindings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bindings.h; sourceTree = ""; }; + 4BF135A484B3FD794B6BE633 /* main.rs */ = {isa = PBXFileReference; path = main.rs; sourceTree = ""; }; + 4C796B246B7EFC59BE22BEAE /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; + 4CA3839E082C9EE1FBE47017 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 5839511CE1969F167776E5BA /* assets */ = {isa = PBXFileReference; lastKnownFileType = folder; path = assets; sourceTree = SOURCE_ROOT; }; + 61706E406133F9FEA10A02CF /* libapp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libapp.a; sourceTree = ""; }; + 6C52C06D919E696C88F980CA /* lib.rs */ = {isa = PBXFileReference; path = lib.rs; sourceTree = ""; }; + 73239B7F777F17978C5F9FB3 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; + 7A2D8F7E3AD2D4401F4C016B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 7CD23EC29DD8E675CF62425F /* foundry_iOS.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = foundry_iOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 7FB0AF0861142E98564AE14D /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; + 916B38007890BE6F5229D88A /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; + 9503D8DA5A521E10DE980308 /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; }; + E33D510DA88C9082AA568044 /* foundry_iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = foundry_iOS.entitlements; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 2A55D5F956F7DFC89A1EF6A3 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 63828790DD4F121B20E1314C /* libapp.a in Frameworks */, + 46451E98CD8CC918B270DF4E /* CoreGraphics.framework in Frameworks */, + 41F61AA6A6395C0E1A22A01D /* Metal.framework in Frameworks */, + A391FE2BDE082320542B786E /* MetalKit.framework in Frameworks */, + 5823D1D3CF428AB8675028CA /* QuartzCore.framework in Frameworks */, + E05514D9EF3C91D648336FAF /* Security.framework in Frameworks */, + 84F2A1451B638E04DC7D9C77 /* UIKit.framework in Frameworks */, + 6DF20201B9860B37359D8373 /* WebKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1C4A0974016D1DFD8F8C4DDB /* Frameworks */ = { + isa = PBXGroup; + children = ( + 4CA3839E082C9EE1FBE47017 /* CoreGraphics.framework */, + 61706E406133F9FEA10A02CF /* libapp.a */, + 4C796B246B7EFC59BE22BEAE /* Metal.framework */, + 9503D8DA5A521E10DE980308 /* MetalKit.framework */, + 916B38007890BE6F5229D88A /* QuartzCore.framework */, + 1BE59BDC6646E6E88C37132A /* Security.framework */, + 0FFD378E56937244899E32B9 /* UIKit.framework */, + 7FB0AF0861142E98564AE14D /* WebKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 2FD745FA11757414C89CF97B /* Products */ = { + isa = PBXGroup; + children = ( + 7CD23EC29DD8E675CF62425F /* foundry_iOS.app */, + ); + name = Products; + sourceTree = ""; + }; + 3BB81CF687DD217A69E52F28 /* src */ = { + isa = PBXGroup; + children = ( + 6C52C06D919E696C88F980CA /* lib.rs */, + 4BF135A484B3FD794B6BE633 /* main.rs */, + ); + name = src; + path = ../../src; + sourceTree = ""; + }; + 57E35B817B051AAFCDF3B583 /* bindings */ = { + isa = PBXGroup; + children = ( + 46675940F25D441B14F4D9BD /* bindings.h */, + ); + path = bindings; + sourceTree = ""; + }; + 8A9C64E5F1382764F31A9C3E = { + isa = PBXGroup; + children = ( + 5839511CE1969F167776E5BA /* assets */, + 2C2D23C60F5F67FF1B8EF9BE /* Assets.xcassets */, + 73239B7F777F17978C5F9FB3 /* LaunchScreen.storyboard */, + D848E3356050EA6A0C214268 /* Externals */, + A8C8B8DF2C7F39FBBD9C49F8 /* foundry_iOS */, + F7BF3354D37B8C8E0475FD89 /* Sources */, + 3BB81CF687DD217A69E52F28 /* src */, + 1C4A0974016D1DFD8F8C4DDB /* Frameworks */, + 2FD745FA11757414C89CF97B /* Products */, + ); + sourceTree = ""; + }; + A8C8B8DF2C7F39FBBD9C49F8 /* foundry_iOS */ = { + isa = PBXGroup; + children = ( + E33D510DA88C9082AA568044 /* foundry_iOS.entitlements */, + 7A2D8F7E3AD2D4401F4C016B /* Info.plist */, + ); + path = foundry_iOS; + sourceTree = ""; + }; + D848E3356050EA6A0C214268 /* Externals */ = { + isa = PBXGroup; + children = ( + ); + path = Externals; + sourceTree = ""; + }; + F5B02224172A9BB7345E5123 /* foundry */ = { + isa = PBXGroup; + children = ( + 41768F9AEEC30C6F3A657349 /* main.mm */, + 57E35B817B051AAFCDF3B583 /* bindings */, + ); + path = foundry; + sourceTree = ""; + }; + F7BF3354D37B8C8E0475FD89 /* Sources */ = { + isa = PBXGroup; + children = ( + F5B02224172A9BB7345E5123 /* foundry */, + ); + path = Sources; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + B133A72EA416CD7D39FE3E92 /* foundry_iOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = D445EACB90281484F8FFC686 /* Build configuration list for PBXNativeTarget "foundry_iOS" */; + buildPhases = ( + FB6BE1E1013DC03BA292046D /* Build Rust Code */, + 5D12D268150FB53F48EDE74C /* Sources */, + 0391435C164ED2F1E2300246 /* Resources */, + 2A55D5F956F7DFC89A1EF6A3 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = foundry_iOS; + packageProductDependencies = ( + ); + productName = foundry_iOS; + productReference = 7CD23EC29DD8E675CF62425F /* foundry_iOS.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 376A77EF2CEF8254085FAA46 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1430; + TargetAttributes = { + }; + }; + buildConfigurationList = 98E4F3D9D125FB8973826CB2 /* Build configuration list for PBXProject "foundry" */; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + Base, + en, + ); + mainGroup = 8A9C64E5F1382764F31A9C3E; + minimizedProjectReferenceProxies = 1; + preferredProjectObjectVersion = 77; + productRefGroup = 2FD745FA11757414C89CF97B /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + B133A72EA416CD7D39FE3E92 /* foundry_iOS */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 0391435C164ED2F1E2300246 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + EF8153BCCF98E828B21D22B8 /* Assets.xcassets in Resources */, + C2EC09AB9A1F311F389731DA /* LaunchScreen.storyboard in Resources */, + 18AA2DEF7E37375920E5C2A0 /* assets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + FB6BE1E1013DC03BA292046D /* Build Rust Code */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Build Rust Code"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(SRCROOT)/Externals/x86_64/${CONFIGURATION}/libapp.a", + "$(SRCROOT)/Externals/arm64/${CONFIGURATION}/libapp.a", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "pnpm tauri ios xcode-script -v --platform ${PLATFORM_DISPLAY_NAME:?} --sdk-root ${SDKROOT:?} --framework-search-paths \"${FRAMEWORK_SEARCH_PATHS:?}\" --header-search-paths \"${HEADER_SEARCH_PATHS:?}\" --gcc-preprocessor-definitions \"${GCC_PREPROCESSOR_DEFINITIONS:-}\" --configuration ${CONFIGURATION:?} ${FORCE_COLOR} ${ARCHS:?}"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 5D12D268150FB53F48EDE74C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A9D64B11D3591BA69A9FF24D /* main.mm in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 2B285D0ECCDEA51DB6635985 /* debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "DEBUG=1", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = debug; + }; + 362B62575264ECB0984A8FC7 /* release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ARCHS = ( + arm64, + ); + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = foundry_iOS/foundry_iOS.entitlements; + CODE_SIGN_IDENTITY = "iPhone Developer"; + ENABLE_BITCODE = NO; + "EXCLUDED_ARCHS[sdk=iphoneos*]" = x86_64; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\".\"", + ); + INFOPLIST_FILE = foundry_iOS/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + "LIBRARY_SEARCH_PATHS[arch=arm64]" = "$(inherited) $(PROJECT_DIR)/Externals/arm64/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)"; + "LIBRARY_SEARCH_PATHS[arch=x86_64]" = "$(inherited) $(PROJECT_DIR)/Externals/x86_64/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)"; + PRODUCT_BUNDLE_IDENTIFIER = dev.sandboxagent.foundry; + PRODUCT_NAME = "Foundry"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALID_ARCHS = arm64; + }; + name = release; + }; + 6503634097DB1CB8102F723F /* debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ARCHS = ( + arm64, + ); + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = foundry_iOS/foundry_iOS.entitlements; + CODE_SIGN_IDENTITY = "iPhone Developer"; + ENABLE_BITCODE = NO; + "EXCLUDED_ARCHS[sdk=iphoneos*]" = x86_64; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\".\"", + ); + INFOPLIST_FILE = foundry_iOS/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + "LIBRARY_SEARCH_PATHS[arch=arm64]" = "$(inherited) $(PROJECT_DIR)/Externals/arm64/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)"; + "LIBRARY_SEARCH_PATHS[arch=x86_64]" = "$(inherited) $(PROJECT_DIR)/Externals/x86_64/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)"; + PRODUCT_BUNDLE_IDENTIFIER = dev.sandboxagent.foundry; + PRODUCT_NAME = "Foundry"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALID_ARCHS = arm64; + }; + name = debug; + }; + 7DD9B8183C37530AE219A355 /* release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + }; + name = release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 98E4F3D9D125FB8973826CB2 /* Build configuration list for PBXProject "foundry" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2B285D0ECCDEA51DB6635985 /* debug */, + 7DD9B8183C37530AE219A355 /* release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = debug; + }; + D445EACB90281484F8FFC686 /* Build configuration list for PBXNativeTarget "foundry_iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6503634097DB1CB8102F723F /* debug */, + 362B62575264ECB0984A8FC7 /* release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = debug; + }; +/* End XCConfigurationList section */ + }; + rootObject = 376A77EF2CEF8254085FAA46 /* Project object */; +} diff --git a/foundry/packages/desktop/src-tauri/gen/apple/foundry.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/foundry/packages/desktop/src-tauri/gen/apple/foundry.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/foundry/packages/desktop/src-tauri/gen/apple/foundry.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/foundry/packages/desktop/src-tauri/gen/apple/foundry.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/foundry/packages/desktop/src-tauri/gen/apple/foundry.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..ac90d5ac --- /dev/null +++ b/foundry/packages/desktop/src-tauri/gen/apple/foundry.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,10 @@ + + + + + BuildSystemType + Original + DisableBuildSystemDeprecationDiagnostic + + + diff --git a/foundry/packages/desktop/src-tauri/gen/apple/foundry.xcodeproj/xcshareddata/xcschemes/foundry_iOS.xcscheme b/foundry/packages/desktop/src-tauri/gen/apple/foundry.xcodeproj/xcshareddata/xcschemes/foundry_iOS.xcscheme new file mode 100644 index 00000000..0e103fab --- /dev/null +++ b/foundry/packages/desktop/src-tauri/gen/apple/foundry.xcodeproj/xcshareddata/xcschemes/foundry_iOS.xcscheme @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/foundry/packages/desktop/src-tauri/gen/apple/foundry_iOS/Info.plist b/foundry/packages/desktop/src-tauri/gen/apple/foundry_iOS/Info.plist new file mode 100644 index 00000000..19c7bdec --- /dev/null +++ b/foundry/packages/desktop/src-tauri/gen/apple/foundry_iOS/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 0.1.0 + CFBundleVersion + 0.1.0 + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + arm64 + metal + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + \ No newline at end of file diff --git a/foundry/packages/desktop/src-tauri/gen/apple/foundry_iOS/foundry_iOS.entitlements b/foundry/packages/desktop/src-tauri/gen/apple/foundry_iOS/foundry_iOS.entitlements new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/foundry/packages/desktop/src-tauri/gen/apple/foundry_iOS/foundry_iOS.entitlements @@ -0,0 +1,5 @@ + + + + + diff --git a/foundry/packages/desktop/src-tauri/gen/apple/project.yml b/foundry/packages/desktop/src-tauri/gen/apple/project.yml new file mode 100644 index 00000000..e46690b1 --- /dev/null +++ b/foundry/packages/desktop/src-tauri/gen/apple/project.yml @@ -0,0 +1,88 @@ +name: foundry +options: + bundleIdPrefix: dev.sandboxagent.foundry + deploymentTarget: + iOS: 14.0 +fileGroups: [../../src] +configs: + debug: debug + release: release +settingGroups: + app: + base: + PRODUCT_NAME: Foundry + PRODUCT_BUNDLE_IDENTIFIER: dev.sandboxagent.foundry +targetTemplates: + app: + type: application + sources: + - path: Sources + scheme: + environmentVariables: + RUST_BACKTRACE: full + RUST_LOG: info + settings: + groups: [app] +targets: + foundry_iOS: + type: application + platform: iOS + sources: + - path: Sources + - path: Assets.xcassets + - path: Externals + - path: foundry_iOS + - path: assets + buildPhase: resources + type: folder + - path: LaunchScreen.storyboard + info: + path: foundry_iOS/Info.plist + properties: + LSRequiresIPhoneOS: true + UILaunchStoryboardName: LaunchScreen + UIRequiredDeviceCapabilities: [arm64, metal] + UISupportedInterfaceOrientations: + - UIInterfaceOrientationPortrait + - UIInterfaceOrientationLandscapeLeft + - UIInterfaceOrientationLandscapeRight + UISupportedInterfaceOrientations~ipad: + - UIInterfaceOrientationPortrait + - UIInterfaceOrientationPortraitUpsideDown + - UIInterfaceOrientationLandscapeLeft + - UIInterfaceOrientationLandscapeRight + CFBundleShortVersionString: 0.1.0 + CFBundleVersion: "0.1.0" + entitlements: + path: foundry_iOS/foundry_iOS.entitlements + scheme: + environmentVariables: + RUST_BACKTRACE: full + RUST_LOG: info + settings: + base: + ENABLE_BITCODE: false + ARCHS: [arm64] + VALID_ARCHS: arm64 + LIBRARY_SEARCH_PATHS[arch=x86_64]: $(inherited) $(PROJECT_DIR)/Externals/x86_64/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME) + LIBRARY_SEARCH_PATHS[arch=arm64]: $(inherited) $(PROJECT_DIR)/Externals/arm64/$(CONFIGURATION) $(SDKROOT)/usr/lib/swift $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME) $(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME) + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES: true + EXCLUDED_ARCHS[sdk=iphoneos*]: x86_64 + groups: [app] + dependencies: + - framework: libapp.a + embed: false + - sdk: CoreGraphics.framework + - sdk: Metal.framework + - sdk: MetalKit.framework + - sdk: QuartzCore.framework + - sdk: Security.framework + - sdk: UIKit.framework + - sdk: WebKit.framework + preBuildScripts: + - script: pnpm tauri ios xcode-script -v --platform ${PLATFORM_DISPLAY_NAME:?} --sdk-root ${SDKROOT:?} --framework-search-paths "${FRAMEWORK_SEARCH_PATHS:?}" --header-search-paths "${HEADER_SEARCH_PATHS:?}" --gcc-preprocessor-definitions "${GCC_PREPROCESSOR_DEFINITIONS:-}" --configuration ${CONFIGURATION:?} ${FORCE_COLOR} ${ARCHS:?} + name: Build Rust Code + basedOnDependencyAnalysis: false + outputFiles: + - $(SRCROOT)/Externals/x86_64/${CONFIGURATION}/libapp.a + - $(SRCROOT)/Externals/arm64/${CONFIGURATION}/libapp.a \ No newline at end of file diff --git a/foundry/packages/desktop/src-tauri/gen/schemas/capabilities.json b/foundry/packages/desktop/src-tauri/gen/schemas/capabilities.json index fe3a6f38..d351e57b 100644 --- a/foundry/packages/desktop/src-tauri/gen/schemas/capabilities.json +++ b/foundry/packages/desktop/src-tauri/gen/schemas/capabilities.json @@ -1 +1,24 @@ -{"default":{"identifier":"default","description":"Default capability for Foundry desktop","local":true,"windows":["main"],"permissions":["core:default","core:window:allow-start-dragging","shell:allow-open",{"identifier":"shell:allow-execute","allow":[{"args":true,"name":"sidecars/foundry-backend","sidecar":true}]},{"identifier":"shell:allow-spawn","allow":[{"args":true,"name":"sidecars/foundry-backend","sidecar":true}]}]}} \ No newline at end of file +{ + "default": { + "identifier": "default", + "description": "Default capability for Foundry desktop", + "local": true, + "windows": ["main"], + "permissions": [ + "core:default", + "core:window:allow-start-dragging", + "shell:allow-open", + { "identifier": "shell:allow-execute", "allow": [{ "args": true, "name": "sidecars/foundry-backend", "sidecar": true }] }, + { "identifier": "shell:allow-spawn", "allow": [{ "args": true, "name": "sidecars/foundry-backend", "sidecar": true }] } + ], + "platforms": ["macOS", "windows", "linux"] + }, + "mobile": { + "identifier": "mobile", + "description": "Capability for Foundry mobile (iOS/Android)", + "local": true, + "windows": ["main"], + "permissions": ["core:default"], + "platforms": ["iOS", "android"] + } +} diff --git a/foundry/packages/desktop/src-tauri/gen/schemas/iOS-schema.json b/foundry/packages/desktop/src-tauri/gen/schemas/iOS-schema.json new file mode 100644 index 00000000..39c46104 --- /dev/null +++ b/foundry/packages/desktop/src-tauri/gen/schemas/iOS-schema.json @@ -0,0 +1,2216 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "CapabilityFile", + "description": "Capability formats accepted in a capability file.", + "anyOf": [ + { + "description": "A single capability.", + "allOf": [ + { + "$ref": "#/definitions/Capability" + } + ] + }, + { + "description": "A list of capabilities.", + "type": "array", + "items": { + "$ref": "#/definitions/Capability" + } + }, + { + "description": "A list of capabilities.", + "type": "object", + "required": ["capabilities"], + "properties": { + "capabilities": { + "description": "The list of capabilities.", + "type": "array", + "items": { + "$ref": "#/definitions/Capability" + } + } + } + } + ], + "definitions": { + "Capability": { + "description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\nIt controls application windows' and webviews' fine grained access to the Tauri core, application, or plugin commands. If a webview or its window is not matching any capability then it has no access to the IPC layer at all.\n\nThis can be done to create groups of windows, based on their required system access, which can reduce impact of frontend vulnerabilities in less privileged windows. Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`. A Window can have none, one, or multiple associated capabilities.\n\n## Example\n\n```json { \"identifier\": \"main-user-files-write\", \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programmatic access to files selected by the user.\", \"windows\": [ \"main\" ], \"permissions\": [ \"core:default\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] }, ], \"platforms\": [\"macOS\",\"windows\"] } ```", + "type": "object", + "required": ["identifier", "permissions"], + "properties": { + "identifier": { + "description": "Identifier of the capability.\n\n## Example\n\n`main-user-files-write`", + "type": "string" + }, + "description": { + "description": "Description of what the capability is intended to allow on associated windows.\n\nIt should contain a description of what the grouped permissions should allow.\n\n## Example\n\nThis capability allows the `main` window access to `filesystem` write related commands and `dialog` commands to enable programmatic access to files selected by the user.", + "default": "", + "type": "string" + }, + "remote": { + "description": "Configure remote URLs that can use the capability permissions.\n\nThis setting is optional and defaults to not being set, as our default use case is that the content is served from our local application.\n\n:::caution Make sure you understand the security implications of providing remote sources with local system access. :::\n\n## Example\n\n```json { \"urls\": [\"https://*.mydomain.dev\"] } ```", + "anyOf": [ + { + "$ref": "#/definitions/CapabilityRemote" + }, + { + "type": "null" + } + ] + }, + "local": { + "description": "Whether this capability is enabled for local app URLs or not. Defaults to `true`.", + "default": true, + "type": "boolean" + }, + "windows": { + "description": "List of windows that are affected by this capability. Can be a glob pattern.\n\nIf a window label matches any of the patterns in this list, the capability will be enabled on all the webviews of that window, regardless of the value of [`Self::webviews`].\n\nOn multiwebview windows, prefer specifying [`Self::webviews`] and omitting [`Self::windows`] for a fine grained access control.\n\n## Example\n\n`[\"main\"]`", + "type": "array", + "items": { + "type": "string" + } + }, + "webviews": { + "description": "List of webviews that are affected by this capability. Can be a glob pattern.\n\nThe capability will be enabled on all the webviews whose label matches any of the patterns in this list, regardless of whether the webview's window label matches a pattern in [`Self::windows`].\n\n## Example\n\n`[\"sub-webview-one\", \"sub-webview-two\"]`", + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "description": "List of permissions attached to this capability.\n\nMust include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`. For commands directly implemented in the application itself only `${permission-name}` is required.\n\n## Example\n\n```json [ \"core:default\", \"shell:allow-open\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] } ] ```", + "type": "array", + "items": { + "$ref": "#/definitions/PermissionEntry" + }, + "uniqueItems": true + }, + "platforms": { + "description": "Limit which target platforms this capability applies to.\n\nBy default all platforms are targeted.\n\n## Example\n\n`[\"macOS\",\"windows\"]`", + "type": ["array", "null"], + "items": { + "$ref": "#/definitions/Target" + } + } + } + }, + "CapabilityRemote": { + "description": "Configuration for remote URLs that are associated with the capability.", + "type": "object", + "required": ["urls"], + "properties": { + "urls": { + "description": "Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).\n\n## Examples\n\n- \"https://*.mydomain.dev\": allows subdomains of mydomain.dev - \"https://mydomain.dev/api/*\": allows any subpath of mydomain.dev/api", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "PermissionEntry": { + "description": "An entry for a permission value in a [`Capability`] can be either a raw permission [`Identifier`] or an object that references a permission and extends its scope.", + "anyOf": [ + { + "description": "Reference a permission or permission set by identifier.", + "allOf": [ + { + "$ref": "#/definitions/Identifier" + } + ] + }, + { + "description": "Reference a permission or permission set by identifier and extends its scope.", + "type": "object", + "allOf": [ + { + "properties": { + "identifier": { + "description": "Identifier of the permission or permission set.", + "allOf": [ + { + "$ref": "#/definitions/Identifier" + } + ] + }, + "allow": { + "description": "Data that defines what is allowed by the scope.", + "type": ["array", "null"], + "items": { + "$ref": "#/definitions/Value" + } + }, + "deny": { + "description": "Data that defines what is denied by the scope. This should be prioritized by validation logic.", + "type": ["array", "null"], + "items": { + "$ref": "#/definitions/Value" + } + } + } + } + ], + "required": ["identifier"] + } + ] + }, + "Identifier": { + "description": "Permission identifier", + "oneOf": [ + { + "description": "Default core plugins set.\n#### This default permission set includes:\n\n- `core:path:default`\n- `core:event:default`\n- `core:window:default`\n- `core:webview:default`\n- `core:app:default`\n- `core:image:default`\n- `core:resources:default`\n- `core:menu:default`\n- `core:tray:default`", + "type": "string", + "const": "core:default", + "markdownDescription": "Default core plugins set.\n#### This default permission set includes:\n\n- `core:path:default`\n- `core:event:default`\n- `core:window:default`\n- `core:webview:default`\n- `core:app:default`\n- `core:image:default`\n- `core:resources:default`\n- `core:menu:default`\n- `core:tray:default`" + }, + { + "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`", + "type": "string", + "const": "core:app:default", + "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`" + }, + { + "description": "Enables the app_hide command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-app-hide", + "markdownDescription": "Enables the app_hide command without any pre-configured scope." + }, + { + "description": "Enables the app_show command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-app-show", + "markdownDescription": "Enables the app_show command without any pre-configured scope." + }, + { + "description": "Enables the bundle_type command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-bundle-type", + "markdownDescription": "Enables the bundle_type command without any pre-configured scope." + }, + { + "description": "Enables the default_window_icon command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-default-window-icon", + "markdownDescription": "Enables the default_window_icon command without any pre-configured scope." + }, + { + "description": "Enables the fetch_data_store_identifiers command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-fetch-data-store-identifiers", + "markdownDescription": "Enables the fetch_data_store_identifiers command without any pre-configured scope." + }, + { + "description": "Enables the identifier command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-identifier", + "markdownDescription": "Enables the identifier command without any pre-configured scope." + }, + { + "description": "Enables the name command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-name", + "markdownDescription": "Enables the name command without any pre-configured scope." + }, + { + "description": "Enables the register_listener command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-register-listener", + "markdownDescription": "Enables the register_listener command without any pre-configured scope." + }, + { + "description": "Enables the remove_data_store command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-remove-data-store", + "markdownDescription": "Enables the remove_data_store command without any pre-configured scope." + }, + { + "description": "Enables the remove_listener command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-remove-listener", + "markdownDescription": "Enables the remove_listener command without any pre-configured scope." + }, + { + "description": "Enables the set_app_theme command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-set-app-theme", + "markdownDescription": "Enables the set_app_theme command without any pre-configured scope." + }, + { + "description": "Enables the set_dock_visibility command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-set-dock-visibility", + "markdownDescription": "Enables the set_dock_visibility command without any pre-configured scope." + }, + { + "description": "Enables the tauri_version command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-tauri-version", + "markdownDescription": "Enables the tauri_version command without any pre-configured scope." + }, + { + "description": "Enables the version command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-version", + "markdownDescription": "Enables the version command without any pre-configured scope." + }, + { + "description": "Denies the app_hide command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-app-hide", + "markdownDescription": "Denies the app_hide command without any pre-configured scope." + }, + { + "description": "Denies the app_show command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-app-show", + "markdownDescription": "Denies the app_show command without any pre-configured scope." + }, + { + "description": "Denies the bundle_type command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-bundle-type", + "markdownDescription": "Denies the bundle_type command without any pre-configured scope." + }, + { + "description": "Denies the default_window_icon command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-default-window-icon", + "markdownDescription": "Denies the default_window_icon command without any pre-configured scope." + }, + { + "description": "Denies the fetch_data_store_identifiers command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-fetch-data-store-identifiers", + "markdownDescription": "Denies the fetch_data_store_identifiers command without any pre-configured scope." + }, + { + "description": "Denies the identifier command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-identifier", + "markdownDescription": "Denies the identifier command without any pre-configured scope." + }, + { + "description": "Denies the name command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-name", + "markdownDescription": "Denies the name command without any pre-configured scope." + }, + { + "description": "Denies the register_listener command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-register-listener", + "markdownDescription": "Denies the register_listener command without any pre-configured scope." + }, + { + "description": "Denies the remove_data_store command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-remove-data-store", + "markdownDescription": "Denies the remove_data_store command without any pre-configured scope." + }, + { + "description": "Denies the remove_listener command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-remove-listener", + "markdownDescription": "Denies the remove_listener command without any pre-configured scope." + }, + { + "description": "Denies the set_app_theme command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-set-app-theme", + "markdownDescription": "Denies the set_app_theme command without any pre-configured scope." + }, + { + "description": "Denies the set_dock_visibility command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-set-dock-visibility", + "markdownDescription": "Denies the set_dock_visibility command without any pre-configured scope." + }, + { + "description": "Denies the tauri_version command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-tauri-version", + "markdownDescription": "Denies the tauri_version command without any pre-configured scope." + }, + { + "description": "Denies the version command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-version", + "markdownDescription": "Denies the version command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-listen`\n- `allow-unlisten`\n- `allow-emit`\n- `allow-emit-to`", + "type": "string", + "const": "core:event:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-listen`\n- `allow-unlisten`\n- `allow-emit`\n- `allow-emit-to`" + }, + { + "description": "Enables the emit command without any pre-configured scope.", + "type": "string", + "const": "core:event:allow-emit", + "markdownDescription": "Enables the emit command without any pre-configured scope." + }, + { + "description": "Enables the emit_to command without any pre-configured scope.", + "type": "string", + "const": "core:event:allow-emit-to", + "markdownDescription": "Enables the emit_to command without any pre-configured scope." + }, + { + "description": "Enables the listen command without any pre-configured scope.", + "type": "string", + "const": "core:event:allow-listen", + "markdownDescription": "Enables the listen command without any pre-configured scope." + }, + { + "description": "Enables the unlisten command without any pre-configured scope.", + "type": "string", + "const": "core:event:allow-unlisten", + "markdownDescription": "Enables the unlisten command without any pre-configured scope." + }, + { + "description": "Denies the emit command without any pre-configured scope.", + "type": "string", + "const": "core:event:deny-emit", + "markdownDescription": "Denies the emit command without any pre-configured scope." + }, + { + "description": "Denies the emit_to command without any pre-configured scope.", + "type": "string", + "const": "core:event:deny-emit-to", + "markdownDescription": "Denies the emit_to command without any pre-configured scope." + }, + { + "description": "Denies the listen command without any pre-configured scope.", + "type": "string", + "const": "core:event:deny-listen", + "markdownDescription": "Denies the listen command without any pre-configured scope." + }, + { + "description": "Denies the unlisten command without any pre-configured scope.", + "type": "string", + "const": "core:event:deny-unlisten", + "markdownDescription": "Denies the unlisten command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-from-bytes`\n- `allow-from-path`\n- `allow-rgba`\n- `allow-size`", + "type": "string", + "const": "core:image:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-from-bytes`\n- `allow-from-path`\n- `allow-rgba`\n- `allow-size`" + }, + { + "description": "Enables the from_bytes command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-from-bytes", + "markdownDescription": "Enables the from_bytes command without any pre-configured scope." + }, + { + "description": "Enables the from_path command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-from-path", + "markdownDescription": "Enables the from_path command without any pre-configured scope." + }, + { + "description": "Enables the new command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-new", + "markdownDescription": "Enables the new command without any pre-configured scope." + }, + { + "description": "Enables the rgba command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-rgba", + "markdownDescription": "Enables the rgba command without any pre-configured scope." + }, + { + "description": "Enables the size command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-size", + "markdownDescription": "Enables the size command without any pre-configured scope." + }, + { + "description": "Denies the from_bytes command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-from-bytes", + "markdownDescription": "Denies the from_bytes command without any pre-configured scope." + }, + { + "description": "Denies the from_path command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-from-path", + "markdownDescription": "Denies the from_path command without any pre-configured scope." + }, + { + "description": "Denies the new command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-new", + "markdownDescription": "Denies the new command without any pre-configured scope." + }, + { + "description": "Denies the rgba command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-rgba", + "markdownDescription": "Denies the rgba command without any pre-configured scope." + }, + { + "description": "Denies the size command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-size", + "markdownDescription": "Denies the size command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-append`\n- `allow-prepend`\n- `allow-insert`\n- `allow-remove`\n- `allow-remove-at`\n- `allow-items`\n- `allow-get`\n- `allow-popup`\n- `allow-create-default`\n- `allow-set-as-app-menu`\n- `allow-set-as-window-menu`\n- `allow-text`\n- `allow-set-text`\n- `allow-is-enabled`\n- `allow-set-enabled`\n- `allow-set-accelerator`\n- `allow-set-as-windows-menu-for-nsapp`\n- `allow-set-as-help-menu-for-nsapp`\n- `allow-is-checked`\n- `allow-set-checked`\n- `allow-set-icon`", + "type": "string", + "const": "core:menu:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-append`\n- `allow-prepend`\n- `allow-insert`\n- `allow-remove`\n- `allow-remove-at`\n- `allow-items`\n- `allow-get`\n- `allow-popup`\n- `allow-create-default`\n- `allow-set-as-app-menu`\n- `allow-set-as-window-menu`\n- `allow-text`\n- `allow-set-text`\n- `allow-is-enabled`\n- `allow-set-enabled`\n- `allow-set-accelerator`\n- `allow-set-as-windows-menu-for-nsapp`\n- `allow-set-as-help-menu-for-nsapp`\n- `allow-is-checked`\n- `allow-set-checked`\n- `allow-set-icon`" + }, + { + "description": "Enables the append command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-append", + "markdownDescription": "Enables the append command without any pre-configured scope." + }, + { + "description": "Enables the create_default command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-create-default", + "markdownDescription": "Enables the create_default command without any pre-configured scope." + }, + { + "description": "Enables the get command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-get", + "markdownDescription": "Enables the get command without any pre-configured scope." + }, + { + "description": "Enables the insert command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-insert", + "markdownDescription": "Enables the insert command without any pre-configured scope." + }, + { + "description": "Enables the is_checked command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-is-checked", + "markdownDescription": "Enables the is_checked command without any pre-configured scope." + }, + { + "description": "Enables the is_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-is-enabled", + "markdownDescription": "Enables the is_enabled command without any pre-configured scope." + }, + { + "description": "Enables the items command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-items", + "markdownDescription": "Enables the items command without any pre-configured scope." + }, + { + "description": "Enables the new command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-new", + "markdownDescription": "Enables the new command without any pre-configured scope." + }, + { + "description": "Enables the popup command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-popup", + "markdownDescription": "Enables the popup command without any pre-configured scope." + }, + { + "description": "Enables the prepend command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-prepend", + "markdownDescription": "Enables the prepend command without any pre-configured scope." + }, + { + "description": "Enables the remove command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-remove", + "markdownDescription": "Enables the remove command without any pre-configured scope." + }, + { + "description": "Enables the remove_at command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-remove-at", + "markdownDescription": "Enables the remove_at command without any pre-configured scope." + }, + { + "description": "Enables the set_accelerator command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-accelerator", + "markdownDescription": "Enables the set_accelerator command without any pre-configured scope." + }, + { + "description": "Enables the set_as_app_menu command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-as-app-menu", + "markdownDescription": "Enables the set_as_app_menu command without any pre-configured scope." + }, + { + "description": "Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-as-help-menu-for-nsapp", + "markdownDescription": "Enables the set_as_help_menu_for_nsapp command without any pre-configured scope." + }, + { + "description": "Enables the set_as_window_menu command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-as-window-menu", + "markdownDescription": "Enables the set_as_window_menu command without any pre-configured scope." + }, + { + "description": "Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-as-windows-menu-for-nsapp", + "markdownDescription": "Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope." + }, + { + "description": "Enables the set_checked command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-checked", + "markdownDescription": "Enables the set_checked command without any pre-configured scope." + }, + { + "description": "Enables the set_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-enabled", + "markdownDescription": "Enables the set_enabled command without any pre-configured scope." + }, + { + "description": "Enables the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-icon", + "markdownDescription": "Enables the set_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_text command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-text", + "markdownDescription": "Enables the set_text command without any pre-configured scope." + }, + { + "description": "Enables the text command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-text", + "markdownDescription": "Enables the text command without any pre-configured scope." + }, + { + "description": "Denies the append command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-append", + "markdownDescription": "Denies the append command without any pre-configured scope." + }, + { + "description": "Denies the create_default command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-create-default", + "markdownDescription": "Denies the create_default command without any pre-configured scope." + }, + { + "description": "Denies the get command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-get", + "markdownDescription": "Denies the get command without any pre-configured scope." + }, + { + "description": "Denies the insert command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-insert", + "markdownDescription": "Denies the insert command without any pre-configured scope." + }, + { + "description": "Denies the is_checked command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-is-checked", + "markdownDescription": "Denies the is_checked command without any pre-configured scope." + }, + { + "description": "Denies the is_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-is-enabled", + "markdownDescription": "Denies the is_enabled command without any pre-configured scope." + }, + { + "description": "Denies the items command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-items", + "markdownDescription": "Denies the items command without any pre-configured scope." + }, + { + "description": "Denies the new command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-new", + "markdownDescription": "Denies the new command without any pre-configured scope." + }, + { + "description": "Denies the popup command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-popup", + "markdownDescription": "Denies the popup command without any pre-configured scope." + }, + { + "description": "Denies the prepend command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-prepend", + "markdownDescription": "Denies the prepend command without any pre-configured scope." + }, + { + "description": "Denies the remove command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-remove", + "markdownDescription": "Denies the remove command without any pre-configured scope." + }, + { + "description": "Denies the remove_at command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-remove-at", + "markdownDescription": "Denies the remove_at command without any pre-configured scope." + }, + { + "description": "Denies the set_accelerator command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-accelerator", + "markdownDescription": "Denies the set_accelerator command without any pre-configured scope." + }, + { + "description": "Denies the set_as_app_menu command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-as-app-menu", + "markdownDescription": "Denies the set_as_app_menu command without any pre-configured scope." + }, + { + "description": "Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-as-help-menu-for-nsapp", + "markdownDescription": "Denies the set_as_help_menu_for_nsapp command without any pre-configured scope." + }, + { + "description": "Denies the set_as_window_menu command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-as-window-menu", + "markdownDescription": "Denies the set_as_window_menu command without any pre-configured scope." + }, + { + "description": "Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-as-windows-menu-for-nsapp", + "markdownDescription": "Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope." + }, + { + "description": "Denies the set_checked command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-checked", + "markdownDescription": "Denies the set_checked command without any pre-configured scope." + }, + { + "description": "Denies the set_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-enabled", + "markdownDescription": "Denies the set_enabled command without any pre-configured scope." + }, + { + "description": "Denies the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-icon", + "markdownDescription": "Denies the set_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_text command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-text", + "markdownDescription": "Denies the set_text command without any pre-configured scope." + }, + { + "description": "Denies the text command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-text", + "markdownDescription": "Denies the text command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-resolve-directory`\n- `allow-resolve`\n- `allow-normalize`\n- `allow-join`\n- `allow-dirname`\n- `allow-extname`\n- `allow-basename`\n- `allow-is-absolute`", + "type": "string", + "const": "core:path:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-resolve-directory`\n- `allow-resolve`\n- `allow-normalize`\n- `allow-join`\n- `allow-dirname`\n- `allow-extname`\n- `allow-basename`\n- `allow-is-absolute`" + }, + { + "description": "Enables the basename command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-basename", + "markdownDescription": "Enables the basename command without any pre-configured scope." + }, + { + "description": "Enables the dirname command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-dirname", + "markdownDescription": "Enables the dirname command without any pre-configured scope." + }, + { + "description": "Enables the extname command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-extname", + "markdownDescription": "Enables the extname command without any pre-configured scope." + }, + { + "description": "Enables the is_absolute command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-is-absolute", + "markdownDescription": "Enables the is_absolute command without any pre-configured scope." + }, + { + "description": "Enables the join command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-join", + "markdownDescription": "Enables the join command without any pre-configured scope." + }, + { + "description": "Enables the normalize command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-normalize", + "markdownDescription": "Enables the normalize command without any pre-configured scope." + }, + { + "description": "Enables the resolve command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-resolve", + "markdownDescription": "Enables the resolve command without any pre-configured scope." + }, + { + "description": "Enables the resolve_directory command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-resolve-directory", + "markdownDescription": "Enables the resolve_directory command without any pre-configured scope." + }, + { + "description": "Denies the basename command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-basename", + "markdownDescription": "Denies the basename command without any pre-configured scope." + }, + { + "description": "Denies the dirname command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-dirname", + "markdownDescription": "Denies the dirname command without any pre-configured scope." + }, + { + "description": "Denies the extname command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-extname", + "markdownDescription": "Denies the extname command without any pre-configured scope." + }, + { + "description": "Denies the is_absolute command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-is-absolute", + "markdownDescription": "Denies the is_absolute command without any pre-configured scope." + }, + { + "description": "Denies the join command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-join", + "markdownDescription": "Denies the join command without any pre-configured scope." + }, + { + "description": "Denies the normalize command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-normalize", + "markdownDescription": "Denies the normalize command without any pre-configured scope." + }, + { + "description": "Denies the resolve command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-resolve", + "markdownDescription": "Denies the resolve command without any pre-configured scope." + }, + { + "description": "Denies the resolve_directory command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-resolve-directory", + "markdownDescription": "Denies the resolve_directory command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-close`", + "type": "string", + "const": "core:resources:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-close`" + }, + { + "description": "Enables the close command without any pre-configured scope.", + "type": "string", + "const": "core:resources:allow-close", + "markdownDescription": "Enables the close command without any pre-configured scope." + }, + { + "description": "Denies the close command without any pre-configured scope.", + "type": "string", + "const": "core:resources:deny-close", + "markdownDescription": "Denies the close command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-get-by-id`\n- `allow-remove-by-id`\n- `allow-set-icon`\n- `allow-set-menu`\n- `allow-set-tooltip`\n- `allow-set-title`\n- `allow-set-visible`\n- `allow-set-temp-dir-path`\n- `allow-set-icon-as-template`\n- `allow-set-show-menu-on-left-click`", + "type": "string", + "const": "core:tray:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-get-by-id`\n- `allow-remove-by-id`\n- `allow-set-icon`\n- `allow-set-menu`\n- `allow-set-tooltip`\n- `allow-set-title`\n- `allow-set-visible`\n- `allow-set-temp-dir-path`\n- `allow-set-icon-as-template`\n- `allow-set-show-menu-on-left-click`" + }, + { + "description": "Enables the get_by_id command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-get-by-id", + "markdownDescription": "Enables the get_by_id command without any pre-configured scope." + }, + { + "description": "Enables the new command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-new", + "markdownDescription": "Enables the new command without any pre-configured scope." + }, + { + "description": "Enables the remove_by_id command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-remove-by-id", + "markdownDescription": "Enables the remove_by_id command without any pre-configured scope." + }, + { + "description": "Enables the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-icon", + "markdownDescription": "Enables the set_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_icon_as_template command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-icon-as-template", + "markdownDescription": "Enables the set_icon_as_template command without any pre-configured scope." + }, + { + "description": "Enables the set_menu command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-menu", + "markdownDescription": "Enables the set_menu command without any pre-configured scope." + }, + { + "description": "Enables the set_show_menu_on_left_click command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-show-menu-on-left-click", + "markdownDescription": "Enables the set_show_menu_on_left_click command without any pre-configured scope." + }, + { + "description": "Enables the set_temp_dir_path command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-temp-dir-path", + "markdownDescription": "Enables the set_temp_dir_path command without any pre-configured scope." + }, + { + "description": "Enables the set_title command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-title", + "markdownDescription": "Enables the set_title command without any pre-configured scope." + }, + { + "description": "Enables the set_tooltip command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-tooltip", + "markdownDescription": "Enables the set_tooltip command without any pre-configured scope." + }, + { + "description": "Enables the set_visible command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-visible", + "markdownDescription": "Enables the set_visible command without any pre-configured scope." + }, + { + "description": "Denies the get_by_id command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-get-by-id", + "markdownDescription": "Denies the get_by_id command without any pre-configured scope." + }, + { + "description": "Denies the new command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-new", + "markdownDescription": "Denies the new command without any pre-configured scope." + }, + { + "description": "Denies the remove_by_id command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-remove-by-id", + "markdownDescription": "Denies the remove_by_id command without any pre-configured scope." + }, + { + "description": "Denies the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-icon", + "markdownDescription": "Denies the set_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_icon_as_template command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-icon-as-template", + "markdownDescription": "Denies the set_icon_as_template command without any pre-configured scope." + }, + { + "description": "Denies the set_menu command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-menu", + "markdownDescription": "Denies the set_menu command without any pre-configured scope." + }, + { + "description": "Denies the set_show_menu_on_left_click command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-show-menu-on-left-click", + "markdownDescription": "Denies the set_show_menu_on_left_click command without any pre-configured scope." + }, + { + "description": "Denies the set_temp_dir_path command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-temp-dir-path", + "markdownDescription": "Denies the set_temp_dir_path command without any pre-configured scope." + }, + { + "description": "Denies the set_title command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-title", + "markdownDescription": "Denies the set_title command without any pre-configured scope." + }, + { + "description": "Denies the set_tooltip command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-tooltip", + "markdownDescription": "Denies the set_tooltip command without any pre-configured scope." + }, + { + "description": "Denies the set_visible command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-visible", + "markdownDescription": "Denies the set_visible command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-webviews`\n- `allow-webview-position`\n- `allow-webview-size`\n- `allow-internal-toggle-devtools`", + "type": "string", + "const": "core:webview:default", + "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-webviews`\n- `allow-webview-position`\n- `allow-webview-size`\n- `allow-internal-toggle-devtools`" + }, + { + "description": "Enables the clear_all_browsing_data command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-clear-all-browsing-data", + "markdownDescription": "Enables the clear_all_browsing_data command without any pre-configured scope." + }, + { + "description": "Enables the create_webview command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-create-webview", + "markdownDescription": "Enables the create_webview command without any pre-configured scope." + }, + { + "description": "Enables the create_webview_window command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-create-webview-window", + "markdownDescription": "Enables the create_webview_window command without any pre-configured scope." + }, + { + "description": "Enables the get_all_webviews command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-get-all-webviews", + "markdownDescription": "Enables the get_all_webviews command without any pre-configured scope." + }, + { + "description": "Enables the internal_toggle_devtools command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-internal-toggle-devtools", + "markdownDescription": "Enables the internal_toggle_devtools command without any pre-configured scope." + }, + { + "description": "Enables the print command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-print", + "markdownDescription": "Enables the print command without any pre-configured scope." + }, + { + "description": "Enables the reparent command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-reparent", + "markdownDescription": "Enables the reparent command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_auto_resize command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-auto-resize", + "markdownDescription": "Enables the set_webview_auto_resize command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_background_color command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-background-color", + "markdownDescription": "Enables the set_webview_background_color command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_focus command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-focus", + "markdownDescription": "Enables the set_webview_focus command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_position command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-position", + "markdownDescription": "Enables the set_webview_position command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_size command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-size", + "markdownDescription": "Enables the set_webview_size command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_zoom command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-zoom", + "markdownDescription": "Enables the set_webview_zoom command without any pre-configured scope." + }, + { + "description": "Enables the webview_close command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-close", + "markdownDescription": "Enables the webview_close command without any pre-configured scope." + }, + { + "description": "Enables the webview_hide command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-hide", + "markdownDescription": "Enables the webview_hide command without any pre-configured scope." + }, + { + "description": "Enables the webview_position command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-position", + "markdownDescription": "Enables the webview_position command without any pre-configured scope." + }, + { + "description": "Enables the webview_show command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-show", + "markdownDescription": "Enables the webview_show command without any pre-configured scope." + }, + { + "description": "Enables the webview_size command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-size", + "markdownDescription": "Enables the webview_size command without any pre-configured scope." + }, + { + "description": "Denies the clear_all_browsing_data command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-clear-all-browsing-data", + "markdownDescription": "Denies the clear_all_browsing_data command without any pre-configured scope." + }, + { + "description": "Denies the create_webview command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-create-webview", + "markdownDescription": "Denies the create_webview command without any pre-configured scope." + }, + { + "description": "Denies the create_webview_window command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-create-webview-window", + "markdownDescription": "Denies the create_webview_window command without any pre-configured scope." + }, + { + "description": "Denies the get_all_webviews command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-get-all-webviews", + "markdownDescription": "Denies the get_all_webviews command without any pre-configured scope." + }, + { + "description": "Denies the internal_toggle_devtools command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-internal-toggle-devtools", + "markdownDescription": "Denies the internal_toggle_devtools command without any pre-configured scope." + }, + { + "description": "Denies the print command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-print", + "markdownDescription": "Denies the print command without any pre-configured scope." + }, + { + "description": "Denies the reparent command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-reparent", + "markdownDescription": "Denies the reparent command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_auto_resize command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-auto-resize", + "markdownDescription": "Denies the set_webview_auto_resize command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_background_color command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-background-color", + "markdownDescription": "Denies the set_webview_background_color command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_focus command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-focus", + "markdownDescription": "Denies the set_webview_focus command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_position command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-position", + "markdownDescription": "Denies the set_webview_position command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_size command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-size", + "markdownDescription": "Denies the set_webview_size command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_zoom command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-zoom", + "markdownDescription": "Denies the set_webview_zoom command without any pre-configured scope." + }, + { + "description": "Denies the webview_close command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-close", + "markdownDescription": "Denies the webview_close command without any pre-configured scope." + }, + { + "description": "Denies the webview_hide command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-hide", + "markdownDescription": "Denies the webview_hide command without any pre-configured scope." + }, + { + "description": "Denies the webview_position command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-position", + "markdownDescription": "Denies the webview_position command without any pre-configured scope." + }, + { + "description": "Denies the webview_show command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-show", + "markdownDescription": "Denies the webview_show command without any pre-configured scope." + }, + { + "description": "Denies the webview_size command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-size", + "markdownDescription": "Denies the webview_size command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-windows`\n- `allow-scale-factor`\n- `allow-inner-position`\n- `allow-outer-position`\n- `allow-inner-size`\n- `allow-outer-size`\n- `allow-is-fullscreen`\n- `allow-is-minimized`\n- `allow-is-maximized`\n- `allow-is-focused`\n- `allow-is-decorated`\n- `allow-is-resizable`\n- `allow-is-maximizable`\n- `allow-is-minimizable`\n- `allow-is-closable`\n- `allow-is-visible`\n- `allow-is-enabled`\n- `allow-title`\n- `allow-current-monitor`\n- `allow-primary-monitor`\n- `allow-monitor-from-point`\n- `allow-available-monitors`\n- `allow-cursor-position`\n- `allow-theme`\n- `allow-is-always-on-top`\n- `allow-internal-toggle-maximize`", + "type": "string", + "const": "core:window:default", + "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-windows`\n- `allow-scale-factor`\n- `allow-inner-position`\n- `allow-outer-position`\n- `allow-inner-size`\n- `allow-outer-size`\n- `allow-is-fullscreen`\n- `allow-is-minimized`\n- `allow-is-maximized`\n- `allow-is-focused`\n- `allow-is-decorated`\n- `allow-is-resizable`\n- `allow-is-maximizable`\n- `allow-is-minimizable`\n- `allow-is-closable`\n- `allow-is-visible`\n- `allow-is-enabled`\n- `allow-title`\n- `allow-current-monitor`\n- `allow-primary-monitor`\n- `allow-monitor-from-point`\n- `allow-available-monitors`\n- `allow-cursor-position`\n- `allow-theme`\n- `allow-is-always-on-top`\n- `allow-internal-toggle-maximize`" + }, + { + "description": "Enables the available_monitors command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-available-monitors", + "markdownDescription": "Enables the available_monitors command without any pre-configured scope." + }, + { + "description": "Enables the center command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-center", + "markdownDescription": "Enables the center command without any pre-configured scope." + }, + { + "description": "Enables the close command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-close", + "markdownDescription": "Enables the close command without any pre-configured scope." + }, + { + "description": "Enables the create command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-create", + "markdownDescription": "Enables the create command without any pre-configured scope." + }, + { + "description": "Enables the current_monitor command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-current-monitor", + "markdownDescription": "Enables the current_monitor command without any pre-configured scope." + }, + { + "description": "Enables the cursor_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-cursor-position", + "markdownDescription": "Enables the cursor_position command without any pre-configured scope." + }, + { + "description": "Enables the destroy command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-destroy", + "markdownDescription": "Enables the destroy command without any pre-configured scope." + }, + { + "description": "Enables the get_all_windows command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-get-all-windows", + "markdownDescription": "Enables the get_all_windows command without any pre-configured scope." + }, + { + "description": "Enables the hide command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-hide", + "markdownDescription": "Enables the hide command without any pre-configured scope." + }, + { + "description": "Enables the inner_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-inner-position", + "markdownDescription": "Enables the inner_position command without any pre-configured scope." + }, + { + "description": "Enables the inner_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-inner-size", + "markdownDescription": "Enables the inner_size command without any pre-configured scope." + }, + { + "description": "Enables the internal_toggle_maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-internal-toggle-maximize", + "markdownDescription": "Enables the internal_toggle_maximize command without any pre-configured scope." + }, + { + "description": "Enables the is_always_on_top command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-always-on-top", + "markdownDescription": "Enables the is_always_on_top command without any pre-configured scope." + }, + { + "description": "Enables the is_closable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-closable", + "markdownDescription": "Enables the is_closable command without any pre-configured scope." + }, + { + "description": "Enables the is_decorated command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-decorated", + "markdownDescription": "Enables the is_decorated command without any pre-configured scope." + }, + { + "description": "Enables the is_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-enabled", + "markdownDescription": "Enables the is_enabled command without any pre-configured scope." + }, + { + "description": "Enables the is_focused command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-focused", + "markdownDescription": "Enables the is_focused command without any pre-configured scope." + }, + { + "description": "Enables the is_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-fullscreen", + "markdownDescription": "Enables the is_fullscreen command without any pre-configured scope." + }, + { + "description": "Enables the is_maximizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-maximizable", + "markdownDescription": "Enables the is_maximizable command without any pre-configured scope." + }, + { + "description": "Enables the is_maximized command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-maximized", + "markdownDescription": "Enables the is_maximized command without any pre-configured scope." + }, + { + "description": "Enables the is_minimizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-minimizable", + "markdownDescription": "Enables the is_minimizable command without any pre-configured scope." + }, + { + "description": "Enables the is_minimized command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-minimized", + "markdownDescription": "Enables the is_minimized command without any pre-configured scope." + }, + { + "description": "Enables the is_resizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-resizable", + "markdownDescription": "Enables the is_resizable command without any pre-configured scope." + }, + { + "description": "Enables the is_visible command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-visible", + "markdownDescription": "Enables the is_visible command without any pre-configured scope." + }, + { + "description": "Enables the maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-maximize", + "markdownDescription": "Enables the maximize command without any pre-configured scope." + }, + { + "description": "Enables the minimize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-minimize", + "markdownDescription": "Enables the minimize command without any pre-configured scope." + }, + { + "description": "Enables the monitor_from_point command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-monitor-from-point", + "markdownDescription": "Enables the monitor_from_point command without any pre-configured scope." + }, + { + "description": "Enables the outer_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-outer-position", + "markdownDescription": "Enables the outer_position command without any pre-configured scope." + }, + { + "description": "Enables the outer_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-outer-size", + "markdownDescription": "Enables the outer_size command without any pre-configured scope." + }, + { + "description": "Enables the primary_monitor command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-primary-monitor", + "markdownDescription": "Enables the primary_monitor command without any pre-configured scope." + }, + { + "description": "Enables the request_user_attention command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-request-user-attention", + "markdownDescription": "Enables the request_user_attention command without any pre-configured scope." + }, + { + "description": "Enables the scale_factor command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-scale-factor", + "markdownDescription": "Enables the scale_factor command without any pre-configured scope." + }, + { + "description": "Enables the set_always_on_bottom command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-always-on-bottom", + "markdownDescription": "Enables the set_always_on_bottom command without any pre-configured scope." + }, + { + "description": "Enables the set_always_on_top command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-always-on-top", + "markdownDescription": "Enables the set_always_on_top command without any pre-configured scope." + }, + { + "description": "Enables the set_background_color command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-background-color", + "markdownDescription": "Enables the set_background_color command without any pre-configured scope." + }, + { + "description": "Enables the set_badge_count command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-badge-count", + "markdownDescription": "Enables the set_badge_count command without any pre-configured scope." + }, + { + "description": "Enables the set_badge_label command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-badge-label", + "markdownDescription": "Enables the set_badge_label command without any pre-configured scope." + }, + { + "description": "Enables the set_closable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-closable", + "markdownDescription": "Enables the set_closable command without any pre-configured scope." + }, + { + "description": "Enables the set_content_protected command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-content-protected", + "markdownDescription": "Enables the set_content_protected command without any pre-configured scope." + }, + { + "description": "Enables the set_cursor_grab command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-cursor-grab", + "markdownDescription": "Enables the set_cursor_grab command without any pre-configured scope." + }, + { + "description": "Enables the set_cursor_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-cursor-icon", + "markdownDescription": "Enables the set_cursor_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_cursor_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-cursor-position", + "markdownDescription": "Enables the set_cursor_position command without any pre-configured scope." + }, + { + "description": "Enables the set_cursor_visible command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-cursor-visible", + "markdownDescription": "Enables the set_cursor_visible command without any pre-configured scope." + }, + { + "description": "Enables the set_decorations command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-decorations", + "markdownDescription": "Enables the set_decorations command without any pre-configured scope." + }, + { + "description": "Enables the set_effects command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-effects", + "markdownDescription": "Enables the set_effects command without any pre-configured scope." + }, + { + "description": "Enables the set_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-enabled", + "markdownDescription": "Enables the set_enabled command without any pre-configured scope." + }, + { + "description": "Enables the set_focus command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-focus", + "markdownDescription": "Enables the set_focus command without any pre-configured scope." + }, + { + "description": "Enables the set_focusable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-focusable", + "markdownDescription": "Enables the set_focusable command without any pre-configured scope." + }, + { + "description": "Enables the set_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-fullscreen", + "markdownDescription": "Enables the set_fullscreen command without any pre-configured scope." + }, + { + "description": "Enables the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-icon", + "markdownDescription": "Enables the set_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_ignore_cursor_events command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-ignore-cursor-events", + "markdownDescription": "Enables the set_ignore_cursor_events command without any pre-configured scope." + }, + { + "description": "Enables the set_max_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-max-size", + "markdownDescription": "Enables the set_max_size command without any pre-configured scope." + }, + { + "description": "Enables the set_maximizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-maximizable", + "markdownDescription": "Enables the set_maximizable command without any pre-configured scope." + }, + { + "description": "Enables the set_min_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-min-size", + "markdownDescription": "Enables the set_min_size command without any pre-configured scope." + }, + { + "description": "Enables the set_minimizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-minimizable", + "markdownDescription": "Enables the set_minimizable command without any pre-configured scope." + }, + { + "description": "Enables the set_overlay_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-overlay-icon", + "markdownDescription": "Enables the set_overlay_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-position", + "markdownDescription": "Enables the set_position command without any pre-configured scope." + }, + { + "description": "Enables the set_progress_bar command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-progress-bar", + "markdownDescription": "Enables the set_progress_bar command without any pre-configured scope." + }, + { + "description": "Enables the set_resizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-resizable", + "markdownDescription": "Enables the set_resizable command without any pre-configured scope." + }, + { + "description": "Enables the set_shadow command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-shadow", + "markdownDescription": "Enables the set_shadow command without any pre-configured scope." + }, + { + "description": "Enables the set_simple_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-simple-fullscreen", + "markdownDescription": "Enables the set_simple_fullscreen command without any pre-configured scope." + }, + { + "description": "Enables the set_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-size", + "markdownDescription": "Enables the set_size command without any pre-configured scope." + }, + { + "description": "Enables the set_size_constraints command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-size-constraints", + "markdownDescription": "Enables the set_size_constraints command without any pre-configured scope." + }, + { + "description": "Enables the set_skip_taskbar command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-skip-taskbar", + "markdownDescription": "Enables the set_skip_taskbar command without any pre-configured scope." + }, + { + "description": "Enables the set_theme command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-theme", + "markdownDescription": "Enables the set_theme command without any pre-configured scope." + }, + { + "description": "Enables the set_title command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-title", + "markdownDescription": "Enables the set_title command without any pre-configured scope." + }, + { + "description": "Enables the set_title_bar_style command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-title-bar-style", + "markdownDescription": "Enables the set_title_bar_style command without any pre-configured scope." + }, + { + "description": "Enables the set_visible_on_all_workspaces command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-visible-on-all-workspaces", + "markdownDescription": "Enables the set_visible_on_all_workspaces command without any pre-configured scope." + }, + { + "description": "Enables the show command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-show", + "markdownDescription": "Enables the show command without any pre-configured scope." + }, + { + "description": "Enables the start_dragging command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-start-dragging", + "markdownDescription": "Enables the start_dragging command without any pre-configured scope." + }, + { + "description": "Enables the start_resize_dragging command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-start-resize-dragging", + "markdownDescription": "Enables the start_resize_dragging command without any pre-configured scope." + }, + { + "description": "Enables the theme command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-theme", + "markdownDescription": "Enables the theme command without any pre-configured scope." + }, + { + "description": "Enables the title command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-title", + "markdownDescription": "Enables the title command without any pre-configured scope." + }, + { + "description": "Enables the toggle_maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-toggle-maximize", + "markdownDescription": "Enables the toggle_maximize command without any pre-configured scope." + }, + { + "description": "Enables the unmaximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-unmaximize", + "markdownDescription": "Enables the unmaximize command without any pre-configured scope." + }, + { + "description": "Enables the unminimize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-unminimize", + "markdownDescription": "Enables the unminimize command without any pre-configured scope." + }, + { + "description": "Denies the available_monitors command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-available-monitors", + "markdownDescription": "Denies the available_monitors command without any pre-configured scope." + }, + { + "description": "Denies the center command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-center", + "markdownDescription": "Denies the center command without any pre-configured scope." + }, + { + "description": "Denies the close command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-close", + "markdownDescription": "Denies the close command without any pre-configured scope." + }, + { + "description": "Denies the create command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-create", + "markdownDescription": "Denies the create command without any pre-configured scope." + }, + { + "description": "Denies the current_monitor command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-current-monitor", + "markdownDescription": "Denies the current_monitor command without any pre-configured scope." + }, + { + "description": "Denies the cursor_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-cursor-position", + "markdownDescription": "Denies the cursor_position command without any pre-configured scope." + }, + { + "description": "Denies the destroy command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-destroy", + "markdownDescription": "Denies the destroy command without any pre-configured scope." + }, + { + "description": "Denies the get_all_windows command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-get-all-windows", + "markdownDescription": "Denies the get_all_windows command without any pre-configured scope." + }, + { + "description": "Denies the hide command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-hide", + "markdownDescription": "Denies the hide command without any pre-configured scope." + }, + { + "description": "Denies the inner_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-inner-position", + "markdownDescription": "Denies the inner_position command without any pre-configured scope." + }, + { + "description": "Denies the inner_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-inner-size", + "markdownDescription": "Denies the inner_size command without any pre-configured scope." + }, + { + "description": "Denies the internal_toggle_maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-internal-toggle-maximize", + "markdownDescription": "Denies the internal_toggle_maximize command without any pre-configured scope." + }, + { + "description": "Denies the is_always_on_top command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-always-on-top", + "markdownDescription": "Denies the is_always_on_top command without any pre-configured scope." + }, + { + "description": "Denies the is_closable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-closable", + "markdownDescription": "Denies the is_closable command without any pre-configured scope." + }, + { + "description": "Denies the is_decorated command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-decorated", + "markdownDescription": "Denies the is_decorated command without any pre-configured scope." + }, + { + "description": "Denies the is_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-enabled", + "markdownDescription": "Denies the is_enabled command without any pre-configured scope." + }, + { + "description": "Denies the is_focused command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-focused", + "markdownDescription": "Denies the is_focused command without any pre-configured scope." + }, + { + "description": "Denies the is_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-fullscreen", + "markdownDescription": "Denies the is_fullscreen command without any pre-configured scope." + }, + { + "description": "Denies the is_maximizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-maximizable", + "markdownDescription": "Denies the is_maximizable command without any pre-configured scope." + }, + { + "description": "Denies the is_maximized command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-maximized", + "markdownDescription": "Denies the is_maximized command without any pre-configured scope." + }, + { + "description": "Denies the is_minimizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-minimizable", + "markdownDescription": "Denies the is_minimizable command without any pre-configured scope." + }, + { + "description": "Denies the is_minimized command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-minimized", + "markdownDescription": "Denies the is_minimized command without any pre-configured scope." + }, + { + "description": "Denies the is_resizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-resizable", + "markdownDescription": "Denies the is_resizable command without any pre-configured scope." + }, + { + "description": "Denies the is_visible command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-visible", + "markdownDescription": "Denies the is_visible command without any pre-configured scope." + }, + { + "description": "Denies the maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-maximize", + "markdownDescription": "Denies the maximize command without any pre-configured scope." + }, + { + "description": "Denies the minimize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-minimize", + "markdownDescription": "Denies the minimize command without any pre-configured scope." + }, + { + "description": "Denies the monitor_from_point command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-monitor-from-point", + "markdownDescription": "Denies the monitor_from_point command without any pre-configured scope." + }, + { + "description": "Denies the outer_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-outer-position", + "markdownDescription": "Denies the outer_position command without any pre-configured scope." + }, + { + "description": "Denies the outer_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-outer-size", + "markdownDescription": "Denies the outer_size command without any pre-configured scope." + }, + { + "description": "Denies the primary_monitor command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-primary-monitor", + "markdownDescription": "Denies the primary_monitor command without any pre-configured scope." + }, + { + "description": "Denies the request_user_attention command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-request-user-attention", + "markdownDescription": "Denies the request_user_attention command without any pre-configured scope." + }, + { + "description": "Denies the scale_factor command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-scale-factor", + "markdownDescription": "Denies the scale_factor command without any pre-configured scope." + }, + { + "description": "Denies the set_always_on_bottom command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-always-on-bottom", + "markdownDescription": "Denies the set_always_on_bottom command without any pre-configured scope." + }, + { + "description": "Denies the set_always_on_top command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-always-on-top", + "markdownDescription": "Denies the set_always_on_top command without any pre-configured scope." + }, + { + "description": "Denies the set_background_color command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-background-color", + "markdownDescription": "Denies the set_background_color command without any pre-configured scope." + }, + { + "description": "Denies the set_badge_count command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-badge-count", + "markdownDescription": "Denies the set_badge_count command without any pre-configured scope." + }, + { + "description": "Denies the set_badge_label command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-badge-label", + "markdownDescription": "Denies the set_badge_label command without any pre-configured scope." + }, + { + "description": "Denies the set_closable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-closable", + "markdownDescription": "Denies the set_closable command without any pre-configured scope." + }, + { + "description": "Denies the set_content_protected command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-content-protected", + "markdownDescription": "Denies the set_content_protected command without any pre-configured scope." + }, + { + "description": "Denies the set_cursor_grab command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-cursor-grab", + "markdownDescription": "Denies the set_cursor_grab command without any pre-configured scope." + }, + { + "description": "Denies the set_cursor_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-cursor-icon", + "markdownDescription": "Denies the set_cursor_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_cursor_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-cursor-position", + "markdownDescription": "Denies the set_cursor_position command without any pre-configured scope." + }, + { + "description": "Denies the set_cursor_visible command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-cursor-visible", + "markdownDescription": "Denies the set_cursor_visible command without any pre-configured scope." + }, + { + "description": "Denies the set_decorations command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-decorations", + "markdownDescription": "Denies the set_decorations command without any pre-configured scope." + }, + { + "description": "Denies the set_effects command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-effects", + "markdownDescription": "Denies the set_effects command without any pre-configured scope." + }, + { + "description": "Denies the set_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-enabled", + "markdownDescription": "Denies the set_enabled command without any pre-configured scope." + }, + { + "description": "Denies the set_focus command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-focus", + "markdownDescription": "Denies the set_focus command without any pre-configured scope." + }, + { + "description": "Denies the set_focusable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-focusable", + "markdownDescription": "Denies the set_focusable command without any pre-configured scope." + }, + { + "description": "Denies the set_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-fullscreen", + "markdownDescription": "Denies the set_fullscreen command without any pre-configured scope." + }, + { + "description": "Denies the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-icon", + "markdownDescription": "Denies the set_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_ignore_cursor_events command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-ignore-cursor-events", + "markdownDescription": "Denies the set_ignore_cursor_events command without any pre-configured scope." + }, + { + "description": "Denies the set_max_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-max-size", + "markdownDescription": "Denies the set_max_size command without any pre-configured scope." + }, + { + "description": "Denies the set_maximizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-maximizable", + "markdownDescription": "Denies the set_maximizable command without any pre-configured scope." + }, + { + "description": "Denies the set_min_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-min-size", + "markdownDescription": "Denies the set_min_size command without any pre-configured scope." + }, + { + "description": "Denies the set_minimizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-minimizable", + "markdownDescription": "Denies the set_minimizable command without any pre-configured scope." + }, + { + "description": "Denies the set_overlay_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-overlay-icon", + "markdownDescription": "Denies the set_overlay_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-position", + "markdownDescription": "Denies the set_position command without any pre-configured scope." + }, + { + "description": "Denies the set_progress_bar command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-progress-bar", + "markdownDescription": "Denies the set_progress_bar command without any pre-configured scope." + }, + { + "description": "Denies the set_resizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-resizable", + "markdownDescription": "Denies the set_resizable command without any pre-configured scope." + }, + { + "description": "Denies the set_shadow command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-shadow", + "markdownDescription": "Denies the set_shadow command without any pre-configured scope." + }, + { + "description": "Denies the set_simple_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-simple-fullscreen", + "markdownDescription": "Denies the set_simple_fullscreen command without any pre-configured scope." + }, + { + "description": "Denies the set_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-size", + "markdownDescription": "Denies the set_size command without any pre-configured scope." + }, + { + "description": "Denies the set_size_constraints command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-size-constraints", + "markdownDescription": "Denies the set_size_constraints command without any pre-configured scope." + }, + { + "description": "Denies the set_skip_taskbar command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-skip-taskbar", + "markdownDescription": "Denies the set_skip_taskbar command without any pre-configured scope." + }, + { + "description": "Denies the set_theme command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-theme", + "markdownDescription": "Denies the set_theme command without any pre-configured scope." + }, + { + "description": "Denies the set_title command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-title", + "markdownDescription": "Denies the set_title command without any pre-configured scope." + }, + { + "description": "Denies the set_title_bar_style command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-title-bar-style", + "markdownDescription": "Denies the set_title_bar_style command without any pre-configured scope." + }, + { + "description": "Denies the set_visible_on_all_workspaces command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-visible-on-all-workspaces", + "markdownDescription": "Denies the set_visible_on_all_workspaces command without any pre-configured scope." + }, + { + "description": "Denies the show command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-show", + "markdownDescription": "Denies the show command without any pre-configured scope." + }, + { + "description": "Denies the start_dragging command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-start-dragging", + "markdownDescription": "Denies the start_dragging command without any pre-configured scope." + }, + { + "description": "Denies the start_resize_dragging command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-start-resize-dragging", + "markdownDescription": "Denies the start_resize_dragging command without any pre-configured scope." + }, + { + "description": "Denies the theme command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-theme", + "markdownDescription": "Denies the theme command without any pre-configured scope." + }, + { + "description": "Denies the title command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-title", + "markdownDescription": "Denies the title command without any pre-configured scope." + }, + { + "description": "Denies the toggle_maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-toggle-maximize", + "markdownDescription": "Denies the toggle_maximize command without any pre-configured scope." + }, + { + "description": "Denies the unmaximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-unmaximize", + "markdownDescription": "Denies the unmaximize command without any pre-configured scope." + }, + { + "description": "Denies the unminimize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-unminimize", + "markdownDescription": "Denies the unminimize command without any pre-configured scope." + } + ] + }, + "Value": { + "description": "All supported ACL values.", + "anyOf": [ + { + "description": "Represents a null JSON value.", + "type": "null" + }, + { + "description": "Represents a [`bool`].", + "type": "boolean" + }, + { + "description": "Represents a valid ACL [`Number`].", + "allOf": [ + { + "$ref": "#/definitions/Number" + } + ] + }, + { + "description": "Represents a [`String`].", + "type": "string" + }, + { + "description": "Represents a list of other [`Value`]s.", + "type": "array", + "items": { + "$ref": "#/definitions/Value" + } + }, + { + "description": "Represents a map of [`String`] keys to [`Value`]s.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/Value" + } + } + ] + }, + "Number": { + "description": "A valid ACL number.", + "anyOf": [ + { + "description": "Represents an [`i64`].", + "type": "integer", + "format": "int64" + }, + { + "description": "Represents a [`f64`].", + "type": "number", + "format": "double" + } + ] + }, + "Target": { + "description": "Platform target.", + "oneOf": [ + { + "description": "MacOS.", + "type": "string", + "enum": ["macOS"] + }, + { + "description": "Windows.", + "type": "string", + "enum": ["windows"] + }, + { + "description": "Linux.", + "type": "string", + "enum": ["linux"] + }, + { + "description": "Android.", + "type": "string", + "enum": ["android"] + }, + { + "description": "iOS.", + "type": "string", + "enum": ["iOS"] + } + ] + } + } +} diff --git a/foundry/packages/desktop/src-tauri/gen/schemas/mobile-schema.json b/foundry/packages/desktop/src-tauri/gen/schemas/mobile-schema.json new file mode 100644 index 00000000..39c46104 --- /dev/null +++ b/foundry/packages/desktop/src-tauri/gen/schemas/mobile-schema.json @@ -0,0 +1,2216 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "CapabilityFile", + "description": "Capability formats accepted in a capability file.", + "anyOf": [ + { + "description": "A single capability.", + "allOf": [ + { + "$ref": "#/definitions/Capability" + } + ] + }, + { + "description": "A list of capabilities.", + "type": "array", + "items": { + "$ref": "#/definitions/Capability" + } + }, + { + "description": "A list of capabilities.", + "type": "object", + "required": ["capabilities"], + "properties": { + "capabilities": { + "description": "The list of capabilities.", + "type": "array", + "items": { + "$ref": "#/definitions/Capability" + } + } + } + } + ], + "definitions": { + "Capability": { + "description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\nIt controls application windows' and webviews' fine grained access to the Tauri core, application, or plugin commands. If a webview or its window is not matching any capability then it has no access to the IPC layer at all.\n\nThis can be done to create groups of windows, based on their required system access, which can reduce impact of frontend vulnerabilities in less privileged windows. Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`. A Window can have none, one, or multiple associated capabilities.\n\n## Example\n\n```json { \"identifier\": \"main-user-files-write\", \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programmatic access to files selected by the user.\", \"windows\": [ \"main\" ], \"permissions\": [ \"core:default\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] }, ], \"platforms\": [\"macOS\",\"windows\"] } ```", + "type": "object", + "required": ["identifier", "permissions"], + "properties": { + "identifier": { + "description": "Identifier of the capability.\n\n## Example\n\n`main-user-files-write`", + "type": "string" + }, + "description": { + "description": "Description of what the capability is intended to allow on associated windows.\n\nIt should contain a description of what the grouped permissions should allow.\n\n## Example\n\nThis capability allows the `main` window access to `filesystem` write related commands and `dialog` commands to enable programmatic access to files selected by the user.", + "default": "", + "type": "string" + }, + "remote": { + "description": "Configure remote URLs that can use the capability permissions.\n\nThis setting is optional and defaults to not being set, as our default use case is that the content is served from our local application.\n\n:::caution Make sure you understand the security implications of providing remote sources with local system access. :::\n\n## Example\n\n```json { \"urls\": [\"https://*.mydomain.dev\"] } ```", + "anyOf": [ + { + "$ref": "#/definitions/CapabilityRemote" + }, + { + "type": "null" + } + ] + }, + "local": { + "description": "Whether this capability is enabled for local app URLs or not. Defaults to `true`.", + "default": true, + "type": "boolean" + }, + "windows": { + "description": "List of windows that are affected by this capability. Can be a glob pattern.\n\nIf a window label matches any of the patterns in this list, the capability will be enabled on all the webviews of that window, regardless of the value of [`Self::webviews`].\n\nOn multiwebview windows, prefer specifying [`Self::webviews`] and omitting [`Self::windows`] for a fine grained access control.\n\n## Example\n\n`[\"main\"]`", + "type": "array", + "items": { + "type": "string" + } + }, + "webviews": { + "description": "List of webviews that are affected by this capability. Can be a glob pattern.\n\nThe capability will be enabled on all the webviews whose label matches any of the patterns in this list, regardless of whether the webview's window label matches a pattern in [`Self::windows`].\n\n## Example\n\n`[\"sub-webview-one\", \"sub-webview-two\"]`", + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "description": "List of permissions attached to this capability.\n\nMust include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`. For commands directly implemented in the application itself only `${permission-name}` is required.\n\n## Example\n\n```json [ \"core:default\", \"shell:allow-open\", \"dialog:open\", { \"identifier\": \"fs:allow-write-text-file\", \"allow\": [{ \"path\": \"$HOME/test.txt\" }] } ] ```", + "type": "array", + "items": { + "$ref": "#/definitions/PermissionEntry" + }, + "uniqueItems": true + }, + "platforms": { + "description": "Limit which target platforms this capability applies to.\n\nBy default all platforms are targeted.\n\n## Example\n\n`[\"macOS\",\"windows\"]`", + "type": ["array", "null"], + "items": { + "$ref": "#/definitions/Target" + } + } + } + }, + "CapabilityRemote": { + "description": "Configuration for remote URLs that are associated with the capability.", + "type": "object", + "required": ["urls"], + "properties": { + "urls": { + "description": "Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).\n\n## Examples\n\n- \"https://*.mydomain.dev\": allows subdomains of mydomain.dev - \"https://mydomain.dev/api/*\": allows any subpath of mydomain.dev/api", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "PermissionEntry": { + "description": "An entry for a permission value in a [`Capability`] can be either a raw permission [`Identifier`] or an object that references a permission and extends its scope.", + "anyOf": [ + { + "description": "Reference a permission or permission set by identifier.", + "allOf": [ + { + "$ref": "#/definitions/Identifier" + } + ] + }, + { + "description": "Reference a permission or permission set by identifier and extends its scope.", + "type": "object", + "allOf": [ + { + "properties": { + "identifier": { + "description": "Identifier of the permission or permission set.", + "allOf": [ + { + "$ref": "#/definitions/Identifier" + } + ] + }, + "allow": { + "description": "Data that defines what is allowed by the scope.", + "type": ["array", "null"], + "items": { + "$ref": "#/definitions/Value" + } + }, + "deny": { + "description": "Data that defines what is denied by the scope. This should be prioritized by validation logic.", + "type": ["array", "null"], + "items": { + "$ref": "#/definitions/Value" + } + } + } + } + ], + "required": ["identifier"] + } + ] + }, + "Identifier": { + "description": "Permission identifier", + "oneOf": [ + { + "description": "Default core plugins set.\n#### This default permission set includes:\n\n- `core:path:default`\n- `core:event:default`\n- `core:window:default`\n- `core:webview:default`\n- `core:app:default`\n- `core:image:default`\n- `core:resources:default`\n- `core:menu:default`\n- `core:tray:default`", + "type": "string", + "const": "core:default", + "markdownDescription": "Default core plugins set.\n#### This default permission set includes:\n\n- `core:path:default`\n- `core:event:default`\n- `core:window:default`\n- `core:webview:default`\n- `core:app:default`\n- `core:image:default`\n- `core:resources:default`\n- `core:menu:default`\n- `core:tray:default`" + }, + { + "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`", + "type": "string", + "const": "core:app:default", + "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`" + }, + { + "description": "Enables the app_hide command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-app-hide", + "markdownDescription": "Enables the app_hide command without any pre-configured scope." + }, + { + "description": "Enables the app_show command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-app-show", + "markdownDescription": "Enables the app_show command without any pre-configured scope." + }, + { + "description": "Enables the bundle_type command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-bundle-type", + "markdownDescription": "Enables the bundle_type command without any pre-configured scope." + }, + { + "description": "Enables the default_window_icon command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-default-window-icon", + "markdownDescription": "Enables the default_window_icon command without any pre-configured scope." + }, + { + "description": "Enables the fetch_data_store_identifiers command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-fetch-data-store-identifiers", + "markdownDescription": "Enables the fetch_data_store_identifiers command without any pre-configured scope." + }, + { + "description": "Enables the identifier command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-identifier", + "markdownDescription": "Enables the identifier command without any pre-configured scope." + }, + { + "description": "Enables the name command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-name", + "markdownDescription": "Enables the name command without any pre-configured scope." + }, + { + "description": "Enables the register_listener command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-register-listener", + "markdownDescription": "Enables the register_listener command without any pre-configured scope." + }, + { + "description": "Enables the remove_data_store command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-remove-data-store", + "markdownDescription": "Enables the remove_data_store command without any pre-configured scope." + }, + { + "description": "Enables the remove_listener command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-remove-listener", + "markdownDescription": "Enables the remove_listener command without any pre-configured scope." + }, + { + "description": "Enables the set_app_theme command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-set-app-theme", + "markdownDescription": "Enables the set_app_theme command without any pre-configured scope." + }, + { + "description": "Enables the set_dock_visibility command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-set-dock-visibility", + "markdownDescription": "Enables the set_dock_visibility command without any pre-configured scope." + }, + { + "description": "Enables the tauri_version command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-tauri-version", + "markdownDescription": "Enables the tauri_version command without any pre-configured scope." + }, + { + "description": "Enables the version command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-version", + "markdownDescription": "Enables the version command without any pre-configured scope." + }, + { + "description": "Denies the app_hide command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-app-hide", + "markdownDescription": "Denies the app_hide command without any pre-configured scope." + }, + { + "description": "Denies the app_show command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-app-show", + "markdownDescription": "Denies the app_show command without any pre-configured scope." + }, + { + "description": "Denies the bundle_type command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-bundle-type", + "markdownDescription": "Denies the bundle_type command without any pre-configured scope." + }, + { + "description": "Denies the default_window_icon command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-default-window-icon", + "markdownDescription": "Denies the default_window_icon command without any pre-configured scope." + }, + { + "description": "Denies the fetch_data_store_identifiers command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-fetch-data-store-identifiers", + "markdownDescription": "Denies the fetch_data_store_identifiers command without any pre-configured scope." + }, + { + "description": "Denies the identifier command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-identifier", + "markdownDescription": "Denies the identifier command without any pre-configured scope." + }, + { + "description": "Denies the name command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-name", + "markdownDescription": "Denies the name command without any pre-configured scope." + }, + { + "description": "Denies the register_listener command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-register-listener", + "markdownDescription": "Denies the register_listener command without any pre-configured scope." + }, + { + "description": "Denies the remove_data_store command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-remove-data-store", + "markdownDescription": "Denies the remove_data_store command without any pre-configured scope." + }, + { + "description": "Denies the remove_listener command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-remove-listener", + "markdownDescription": "Denies the remove_listener command without any pre-configured scope." + }, + { + "description": "Denies the set_app_theme command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-set-app-theme", + "markdownDescription": "Denies the set_app_theme command without any pre-configured scope." + }, + { + "description": "Denies the set_dock_visibility command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-set-dock-visibility", + "markdownDescription": "Denies the set_dock_visibility command without any pre-configured scope." + }, + { + "description": "Denies the tauri_version command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-tauri-version", + "markdownDescription": "Denies the tauri_version command without any pre-configured scope." + }, + { + "description": "Denies the version command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-version", + "markdownDescription": "Denies the version command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-listen`\n- `allow-unlisten`\n- `allow-emit`\n- `allow-emit-to`", + "type": "string", + "const": "core:event:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-listen`\n- `allow-unlisten`\n- `allow-emit`\n- `allow-emit-to`" + }, + { + "description": "Enables the emit command without any pre-configured scope.", + "type": "string", + "const": "core:event:allow-emit", + "markdownDescription": "Enables the emit command without any pre-configured scope." + }, + { + "description": "Enables the emit_to command without any pre-configured scope.", + "type": "string", + "const": "core:event:allow-emit-to", + "markdownDescription": "Enables the emit_to command without any pre-configured scope." + }, + { + "description": "Enables the listen command without any pre-configured scope.", + "type": "string", + "const": "core:event:allow-listen", + "markdownDescription": "Enables the listen command without any pre-configured scope." + }, + { + "description": "Enables the unlisten command without any pre-configured scope.", + "type": "string", + "const": "core:event:allow-unlisten", + "markdownDescription": "Enables the unlisten command without any pre-configured scope." + }, + { + "description": "Denies the emit command without any pre-configured scope.", + "type": "string", + "const": "core:event:deny-emit", + "markdownDescription": "Denies the emit command without any pre-configured scope." + }, + { + "description": "Denies the emit_to command without any pre-configured scope.", + "type": "string", + "const": "core:event:deny-emit-to", + "markdownDescription": "Denies the emit_to command without any pre-configured scope." + }, + { + "description": "Denies the listen command without any pre-configured scope.", + "type": "string", + "const": "core:event:deny-listen", + "markdownDescription": "Denies the listen command without any pre-configured scope." + }, + { + "description": "Denies the unlisten command without any pre-configured scope.", + "type": "string", + "const": "core:event:deny-unlisten", + "markdownDescription": "Denies the unlisten command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-from-bytes`\n- `allow-from-path`\n- `allow-rgba`\n- `allow-size`", + "type": "string", + "const": "core:image:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-from-bytes`\n- `allow-from-path`\n- `allow-rgba`\n- `allow-size`" + }, + { + "description": "Enables the from_bytes command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-from-bytes", + "markdownDescription": "Enables the from_bytes command without any pre-configured scope." + }, + { + "description": "Enables the from_path command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-from-path", + "markdownDescription": "Enables the from_path command without any pre-configured scope." + }, + { + "description": "Enables the new command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-new", + "markdownDescription": "Enables the new command without any pre-configured scope." + }, + { + "description": "Enables the rgba command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-rgba", + "markdownDescription": "Enables the rgba command without any pre-configured scope." + }, + { + "description": "Enables the size command without any pre-configured scope.", + "type": "string", + "const": "core:image:allow-size", + "markdownDescription": "Enables the size command without any pre-configured scope." + }, + { + "description": "Denies the from_bytes command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-from-bytes", + "markdownDescription": "Denies the from_bytes command without any pre-configured scope." + }, + { + "description": "Denies the from_path command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-from-path", + "markdownDescription": "Denies the from_path command without any pre-configured scope." + }, + { + "description": "Denies the new command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-new", + "markdownDescription": "Denies the new command without any pre-configured scope." + }, + { + "description": "Denies the rgba command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-rgba", + "markdownDescription": "Denies the rgba command without any pre-configured scope." + }, + { + "description": "Denies the size command without any pre-configured scope.", + "type": "string", + "const": "core:image:deny-size", + "markdownDescription": "Denies the size command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-append`\n- `allow-prepend`\n- `allow-insert`\n- `allow-remove`\n- `allow-remove-at`\n- `allow-items`\n- `allow-get`\n- `allow-popup`\n- `allow-create-default`\n- `allow-set-as-app-menu`\n- `allow-set-as-window-menu`\n- `allow-text`\n- `allow-set-text`\n- `allow-is-enabled`\n- `allow-set-enabled`\n- `allow-set-accelerator`\n- `allow-set-as-windows-menu-for-nsapp`\n- `allow-set-as-help-menu-for-nsapp`\n- `allow-is-checked`\n- `allow-set-checked`\n- `allow-set-icon`", + "type": "string", + "const": "core:menu:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-append`\n- `allow-prepend`\n- `allow-insert`\n- `allow-remove`\n- `allow-remove-at`\n- `allow-items`\n- `allow-get`\n- `allow-popup`\n- `allow-create-default`\n- `allow-set-as-app-menu`\n- `allow-set-as-window-menu`\n- `allow-text`\n- `allow-set-text`\n- `allow-is-enabled`\n- `allow-set-enabled`\n- `allow-set-accelerator`\n- `allow-set-as-windows-menu-for-nsapp`\n- `allow-set-as-help-menu-for-nsapp`\n- `allow-is-checked`\n- `allow-set-checked`\n- `allow-set-icon`" + }, + { + "description": "Enables the append command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-append", + "markdownDescription": "Enables the append command without any pre-configured scope." + }, + { + "description": "Enables the create_default command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-create-default", + "markdownDescription": "Enables the create_default command without any pre-configured scope." + }, + { + "description": "Enables the get command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-get", + "markdownDescription": "Enables the get command without any pre-configured scope." + }, + { + "description": "Enables the insert command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-insert", + "markdownDescription": "Enables the insert command without any pre-configured scope." + }, + { + "description": "Enables the is_checked command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-is-checked", + "markdownDescription": "Enables the is_checked command without any pre-configured scope." + }, + { + "description": "Enables the is_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-is-enabled", + "markdownDescription": "Enables the is_enabled command without any pre-configured scope." + }, + { + "description": "Enables the items command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-items", + "markdownDescription": "Enables the items command without any pre-configured scope." + }, + { + "description": "Enables the new command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-new", + "markdownDescription": "Enables the new command without any pre-configured scope." + }, + { + "description": "Enables the popup command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-popup", + "markdownDescription": "Enables the popup command without any pre-configured scope." + }, + { + "description": "Enables the prepend command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-prepend", + "markdownDescription": "Enables the prepend command without any pre-configured scope." + }, + { + "description": "Enables the remove command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-remove", + "markdownDescription": "Enables the remove command without any pre-configured scope." + }, + { + "description": "Enables the remove_at command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-remove-at", + "markdownDescription": "Enables the remove_at command without any pre-configured scope." + }, + { + "description": "Enables the set_accelerator command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-accelerator", + "markdownDescription": "Enables the set_accelerator command without any pre-configured scope." + }, + { + "description": "Enables the set_as_app_menu command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-as-app-menu", + "markdownDescription": "Enables the set_as_app_menu command without any pre-configured scope." + }, + { + "description": "Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-as-help-menu-for-nsapp", + "markdownDescription": "Enables the set_as_help_menu_for_nsapp command without any pre-configured scope." + }, + { + "description": "Enables the set_as_window_menu command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-as-window-menu", + "markdownDescription": "Enables the set_as_window_menu command without any pre-configured scope." + }, + { + "description": "Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-as-windows-menu-for-nsapp", + "markdownDescription": "Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope." + }, + { + "description": "Enables the set_checked command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-checked", + "markdownDescription": "Enables the set_checked command without any pre-configured scope." + }, + { + "description": "Enables the set_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-enabled", + "markdownDescription": "Enables the set_enabled command without any pre-configured scope." + }, + { + "description": "Enables the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-icon", + "markdownDescription": "Enables the set_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_text command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-set-text", + "markdownDescription": "Enables the set_text command without any pre-configured scope." + }, + { + "description": "Enables the text command without any pre-configured scope.", + "type": "string", + "const": "core:menu:allow-text", + "markdownDescription": "Enables the text command without any pre-configured scope." + }, + { + "description": "Denies the append command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-append", + "markdownDescription": "Denies the append command without any pre-configured scope." + }, + { + "description": "Denies the create_default command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-create-default", + "markdownDescription": "Denies the create_default command without any pre-configured scope." + }, + { + "description": "Denies the get command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-get", + "markdownDescription": "Denies the get command without any pre-configured scope." + }, + { + "description": "Denies the insert command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-insert", + "markdownDescription": "Denies the insert command without any pre-configured scope." + }, + { + "description": "Denies the is_checked command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-is-checked", + "markdownDescription": "Denies the is_checked command without any pre-configured scope." + }, + { + "description": "Denies the is_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-is-enabled", + "markdownDescription": "Denies the is_enabled command without any pre-configured scope." + }, + { + "description": "Denies the items command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-items", + "markdownDescription": "Denies the items command without any pre-configured scope." + }, + { + "description": "Denies the new command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-new", + "markdownDescription": "Denies the new command without any pre-configured scope." + }, + { + "description": "Denies the popup command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-popup", + "markdownDescription": "Denies the popup command without any pre-configured scope." + }, + { + "description": "Denies the prepend command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-prepend", + "markdownDescription": "Denies the prepend command without any pre-configured scope." + }, + { + "description": "Denies the remove command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-remove", + "markdownDescription": "Denies the remove command without any pre-configured scope." + }, + { + "description": "Denies the remove_at command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-remove-at", + "markdownDescription": "Denies the remove_at command without any pre-configured scope." + }, + { + "description": "Denies the set_accelerator command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-accelerator", + "markdownDescription": "Denies the set_accelerator command without any pre-configured scope." + }, + { + "description": "Denies the set_as_app_menu command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-as-app-menu", + "markdownDescription": "Denies the set_as_app_menu command without any pre-configured scope." + }, + { + "description": "Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-as-help-menu-for-nsapp", + "markdownDescription": "Denies the set_as_help_menu_for_nsapp command without any pre-configured scope." + }, + { + "description": "Denies the set_as_window_menu command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-as-window-menu", + "markdownDescription": "Denies the set_as_window_menu command without any pre-configured scope." + }, + { + "description": "Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-as-windows-menu-for-nsapp", + "markdownDescription": "Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope." + }, + { + "description": "Denies the set_checked command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-checked", + "markdownDescription": "Denies the set_checked command without any pre-configured scope." + }, + { + "description": "Denies the set_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-enabled", + "markdownDescription": "Denies the set_enabled command without any pre-configured scope." + }, + { + "description": "Denies the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-icon", + "markdownDescription": "Denies the set_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_text command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-set-text", + "markdownDescription": "Denies the set_text command without any pre-configured scope." + }, + { + "description": "Denies the text command without any pre-configured scope.", + "type": "string", + "const": "core:menu:deny-text", + "markdownDescription": "Denies the text command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-resolve-directory`\n- `allow-resolve`\n- `allow-normalize`\n- `allow-join`\n- `allow-dirname`\n- `allow-extname`\n- `allow-basename`\n- `allow-is-absolute`", + "type": "string", + "const": "core:path:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-resolve-directory`\n- `allow-resolve`\n- `allow-normalize`\n- `allow-join`\n- `allow-dirname`\n- `allow-extname`\n- `allow-basename`\n- `allow-is-absolute`" + }, + { + "description": "Enables the basename command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-basename", + "markdownDescription": "Enables the basename command without any pre-configured scope." + }, + { + "description": "Enables the dirname command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-dirname", + "markdownDescription": "Enables the dirname command without any pre-configured scope." + }, + { + "description": "Enables the extname command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-extname", + "markdownDescription": "Enables the extname command without any pre-configured scope." + }, + { + "description": "Enables the is_absolute command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-is-absolute", + "markdownDescription": "Enables the is_absolute command without any pre-configured scope." + }, + { + "description": "Enables the join command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-join", + "markdownDescription": "Enables the join command without any pre-configured scope." + }, + { + "description": "Enables the normalize command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-normalize", + "markdownDescription": "Enables the normalize command without any pre-configured scope." + }, + { + "description": "Enables the resolve command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-resolve", + "markdownDescription": "Enables the resolve command without any pre-configured scope." + }, + { + "description": "Enables the resolve_directory command without any pre-configured scope.", + "type": "string", + "const": "core:path:allow-resolve-directory", + "markdownDescription": "Enables the resolve_directory command without any pre-configured scope." + }, + { + "description": "Denies the basename command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-basename", + "markdownDescription": "Denies the basename command without any pre-configured scope." + }, + { + "description": "Denies the dirname command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-dirname", + "markdownDescription": "Denies the dirname command without any pre-configured scope." + }, + { + "description": "Denies the extname command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-extname", + "markdownDescription": "Denies the extname command without any pre-configured scope." + }, + { + "description": "Denies the is_absolute command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-is-absolute", + "markdownDescription": "Denies the is_absolute command without any pre-configured scope." + }, + { + "description": "Denies the join command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-join", + "markdownDescription": "Denies the join command without any pre-configured scope." + }, + { + "description": "Denies the normalize command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-normalize", + "markdownDescription": "Denies the normalize command without any pre-configured scope." + }, + { + "description": "Denies the resolve command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-resolve", + "markdownDescription": "Denies the resolve command without any pre-configured scope." + }, + { + "description": "Denies the resolve_directory command without any pre-configured scope.", + "type": "string", + "const": "core:path:deny-resolve-directory", + "markdownDescription": "Denies the resolve_directory command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-close`", + "type": "string", + "const": "core:resources:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-close`" + }, + { + "description": "Enables the close command without any pre-configured scope.", + "type": "string", + "const": "core:resources:allow-close", + "markdownDescription": "Enables the close command without any pre-configured scope." + }, + { + "description": "Denies the close command without any pre-configured scope.", + "type": "string", + "const": "core:resources:deny-close", + "markdownDescription": "Denies the close command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-get-by-id`\n- `allow-remove-by-id`\n- `allow-set-icon`\n- `allow-set-menu`\n- `allow-set-tooltip`\n- `allow-set-title`\n- `allow-set-visible`\n- `allow-set-temp-dir-path`\n- `allow-set-icon-as-template`\n- `allow-set-show-menu-on-left-click`", + "type": "string", + "const": "core:tray:default", + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-get-by-id`\n- `allow-remove-by-id`\n- `allow-set-icon`\n- `allow-set-menu`\n- `allow-set-tooltip`\n- `allow-set-title`\n- `allow-set-visible`\n- `allow-set-temp-dir-path`\n- `allow-set-icon-as-template`\n- `allow-set-show-menu-on-left-click`" + }, + { + "description": "Enables the get_by_id command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-get-by-id", + "markdownDescription": "Enables the get_by_id command without any pre-configured scope." + }, + { + "description": "Enables the new command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-new", + "markdownDescription": "Enables the new command without any pre-configured scope." + }, + { + "description": "Enables the remove_by_id command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-remove-by-id", + "markdownDescription": "Enables the remove_by_id command without any pre-configured scope." + }, + { + "description": "Enables the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-icon", + "markdownDescription": "Enables the set_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_icon_as_template command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-icon-as-template", + "markdownDescription": "Enables the set_icon_as_template command without any pre-configured scope." + }, + { + "description": "Enables the set_menu command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-menu", + "markdownDescription": "Enables the set_menu command without any pre-configured scope." + }, + { + "description": "Enables the set_show_menu_on_left_click command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-show-menu-on-left-click", + "markdownDescription": "Enables the set_show_menu_on_left_click command without any pre-configured scope." + }, + { + "description": "Enables the set_temp_dir_path command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-temp-dir-path", + "markdownDescription": "Enables the set_temp_dir_path command without any pre-configured scope." + }, + { + "description": "Enables the set_title command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-title", + "markdownDescription": "Enables the set_title command without any pre-configured scope." + }, + { + "description": "Enables the set_tooltip command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-tooltip", + "markdownDescription": "Enables the set_tooltip command without any pre-configured scope." + }, + { + "description": "Enables the set_visible command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-visible", + "markdownDescription": "Enables the set_visible command without any pre-configured scope." + }, + { + "description": "Denies the get_by_id command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-get-by-id", + "markdownDescription": "Denies the get_by_id command without any pre-configured scope." + }, + { + "description": "Denies the new command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-new", + "markdownDescription": "Denies the new command without any pre-configured scope." + }, + { + "description": "Denies the remove_by_id command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-remove-by-id", + "markdownDescription": "Denies the remove_by_id command without any pre-configured scope." + }, + { + "description": "Denies the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-icon", + "markdownDescription": "Denies the set_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_icon_as_template command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-icon-as-template", + "markdownDescription": "Denies the set_icon_as_template command without any pre-configured scope." + }, + { + "description": "Denies the set_menu command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-menu", + "markdownDescription": "Denies the set_menu command without any pre-configured scope." + }, + { + "description": "Denies the set_show_menu_on_left_click command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-show-menu-on-left-click", + "markdownDescription": "Denies the set_show_menu_on_left_click command without any pre-configured scope." + }, + { + "description": "Denies the set_temp_dir_path command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-temp-dir-path", + "markdownDescription": "Denies the set_temp_dir_path command without any pre-configured scope." + }, + { + "description": "Denies the set_title command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-title", + "markdownDescription": "Denies the set_title command without any pre-configured scope." + }, + { + "description": "Denies the set_tooltip command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-tooltip", + "markdownDescription": "Denies the set_tooltip command without any pre-configured scope." + }, + { + "description": "Denies the set_visible command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-visible", + "markdownDescription": "Denies the set_visible command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-webviews`\n- `allow-webview-position`\n- `allow-webview-size`\n- `allow-internal-toggle-devtools`", + "type": "string", + "const": "core:webview:default", + "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-webviews`\n- `allow-webview-position`\n- `allow-webview-size`\n- `allow-internal-toggle-devtools`" + }, + { + "description": "Enables the clear_all_browsing_data command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-clear-all-browsing-data", + "markdownDescription": "Enables the clear_all_browsing_data command without any pre-configured scope." + }, + { + "description": "Enables the create_webview command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-create-webview", + "markdownDescription": "Enables the create_webview command without any pre-configured scope." + }, + { + "description": "Enables the create_webview_window command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-create-webview-window", + "markdownDescription": "Enables the create_webview_window command without any pre-configured scope." + }, + { + "description": "Enables the get_all_webviews command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-get-all-webviews", + "markdownDescription": "Enables the get_all_webviews command without any pre-configured scope." + }, + { + "description": "Enables the internal_toggle_devtools command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-internal-toggle-devtools", + "markdownDescription": "Enables the internal_toggle_devtools command without any pre-configured scope." + }, + { + "description": "Enables the print command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-print", + "markdownDescription": "Enables the print command without any pre-configured scope." + }, + { + "description": "Enables the reparent command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-reparent", + "markdownDescription": "Enables the reparent command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_auto_resize command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-auto-resize", + "markdownDescription": "Enables the set_webview_auto_resize command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_background_color command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-background-color", + "markdownDescription": "Enables the set_webview_background_color command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_focus command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-focus", + "markdownDescription": "Enables the set_webview_focus command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_position command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-position", + "markdownDescription": "Enables the set_webview_position command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_size command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-size", + "markdownDescription": "Enables the set_webview_size command without any pre-configured scope." + }, + { + "description": "Enables the set_webview_zoom command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-set-webview-zoom", + "markdownDescription": "Enables the set_webview_zoom command without any pre-configured scope." + }, + { + "description": "Enables the webview_close command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-close", + "markdownDescription": "Enables the webview_close command without any pre-configured scope." + }, + { + "description": "Enables the webview_hide command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-hide", + "markdownDescription": "Enables the webview_hide command without any pre-configured scope." + }, + { + "description": "Enables the webview_position command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-position", + "markdownDescription": "Enables the webview_position command without any pre-configured scope." + }, + { + "description": "Enables the webview_show command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-show", + "markdownDescription": "Enables the webview_show command without any pre-configured scope." + }, + { + "description": "Enables the webview_size command without any pre-configured scope.", + "type": "string", + "const": "core:webview:allow-webview-size", + "markdownDescription": "Enables the webview_size command without any pre-configured scope." + }, + { + "description": "Denies the clear_all_browsing_data command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-clear-all-browsing-data", + "markdownDescription": "Denies the clear_all_browsing_data command without any pre-configured scope." + }, + { + "description": "Denies the create_webview command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-create-webview", + "markdownDescription": "Denies the create_webview command without any pre-configured scope." + }, + { + "description": "Denies the create_webview_window command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-create-webview-window", + "markdownDescription": "Denies the create_webview_window command without any pre-configured scope." + }, + { + "description": "Denies the get_all_webviews command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-get-all-webviews", + "markdownDescription": "Denies the get_all_webviews command without any pre-configured scope." + }, + { + "description": "Denies the internal_toggle_devtools command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-internal-toggle-devtools", + "markdownDescription": "Denies the internal_toggle_devtools command without any pre-configured scope." + }, + { + "description": "Denies the print command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-print", + "markdownDescription": "Denies the print command without any pre-configured scope." + }, + { + "description": "Denies the reparent command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-reparent", + "markdownDescription": "Denies the reparent command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_auto_resize command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-auto-resize", + "markdownDescription": "Denies the set_webview_auto_resize command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_background_color command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-background-color", + "markdownDescription": "Denies the set_webview_background_color command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_focus command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-focus", + "markdownDescription": "Denies the set_webview_focus command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_position command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-position", + "markdownDescription": "Denies the set_webview_position command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_size command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-size", + "markdownDescription": "Denies the set_webview_size command without any pre-configured scope." + }, + { + "description": "Denies the set_webview_zoom command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-set-webview-zoom", + "markdownDescription": "Denies the set_webview_zoom command without any pre-configured scope." + }, + { + "description": "Denies the webview_close command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-close", + "markdownDescription": "Denies the webview_close command without any pre-configured scope." + }, + { + "description": "Denies the webview_hide command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-hide", + "markdownDescription": "Denies the webview_hide command without any pre-configured scope." + }, + { + "description": "Denies the webview_position command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-position", + "markdownDescription": "Denies the webview_position command without any pre-configured scope." + }, + { + "description": "Denies the webview_show command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-show", + "markdownDescription": "Denies the webview_show command without any pre-configured scope." + }, + { + "description": "Denies the webview_size command without any pre-configured scope.", + "type": "string", + "const": "core:webview:deny-webview-size", + "markdownDescription": "Denies the webview_size command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-windows`\n- `allow-scale-factor`\n- `allow-inner-position`\n- `allow-outer-position`\n- `allow-inner-size`\n- `allow-outer-size`\n- `allow-is-fullscreen`\n- `allow-is-minimized`\n- `allow-is-maximized`\n- `allow-is-focused`\n- `allow-is-decorated`\n- `allow-is-resizable`\n- `allow-is-maximizable`\n- `allow-is-minimizable`\n- `allow-is-closable`\n- `allow-is-visible`\n- `allow-is-enabled`\n- `allow-title`\n- `allow-current-monitor`\n- `allow-primary-monitor`\n- `allow-monitor-from-point`\n- `allow-available-monitors`\n- `allow-cursor-position`\n- `allow-theme`\n- `allow-is-always-on-top`\n- `allow-internal-toggle-maximize`", + "type": "string", + "const": "core:window:default", + "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-windows`\n- `allow-scale-factor`\n- `allow-inner-position`\n- `allow-outer-position`\n- `allow-inner-size`\n- `allow-outer-size`\n- `allow-is-fullscreen`\n- `allow-is-minimized`\n- `allow-is-maximized`\n- `allow-is-focused`\n- `allow-is-decorated`\n- `allow-is-resizable`\n- `allow-is-maximizable`\n- `allow-is-minimizable`\n- `allow-is-closable`\n- `allow-is-visible`\n- `allow-is-enabled`\n- `allow-title`\n- `allow-current-monitor`\n- `allow-primary-monitor`\n- `allow-monitor-from-point`\n- `allow-available-monitors`\n- `allow-cursor-position`\n- `allow-theme`\n- `allow-is-always-on-top`\n- `allow-internal-toggle-maximize`" + }, + { + "description": "Enables the available_monitors command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-available-monitors", + "markdownDescription": "Enables the available_monitors command without any pre-configured scope." + }, + { + "description": "Enables the center command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-center", + "markdownDescription": "Enables the center command without any pre-configured scope." + }, + { + "description": "Enables the close command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-close", + "markdownDescription": "Enables the close command without any pre-configured scope." + }, + { + "description": "Enables the create command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-create", + "markdownDescription": "Enables the create command without any pre-configured scope." + }, + { + "description": "Enables the current_monitor command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-current-monitor", + "markdownDescription": "Enables the current_monitor command without any pre-configured scope." + }, + { + "description": "Enables the cursor_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-cursor-position", + "markdownDescription": "Enables the cursor_position command without any pre-configured scope." + }, + { + "description": "Enables the destroy command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-destroy", + "markdownDescription": "Enables the destroy command without any pre-configured scope." + }, + { + "description": "Enables the get_all_windows command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-get-all-windows", + "markdownDescription": "Enables the get_all_windows command without any pre-configured scope." + }, + { + "description": "Enables the hide command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-hide", + "markdownDescription": "Enables the hide command without any pre-configured scope." + }, + { + "description": "Enables the inner_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-inner-position", + "markdownDescription": "Enables the inner_position command without any pre-configured scope." + }, + { + "description": "Enables the inner_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-inner-size", + "markdownDescription": "Enables the inner_size command without any pre-configured scope." + }, + { + "description": "Enables the internal_toggle_maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-internal-toggle-maximize", + "markdownDescription": "Enables the internal_toggle_maximize command without any pre-configured scope." + }, + { + "description": "Enables the is_always_on_top command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-always-on-top", + "markdownDescription": "Enables the is_always_on_top command without any pre-configured scope." + }, + { + "description": "Enables the is_closable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-closable", + "markdownDescription": "Enables the is_closable command without any pre-configured scope." + }, + { + "description": "Enables the is_decorated command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-decorated", + "markdownDescription": "Enables the is_decorated command without any pre-configured scope." + }, + { + "description": "Enables the is_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-enabled", + "markdownDescription": "Enables the is_enabled command without any pre-configured scope." + }, + { + "description": "Enables the is_focused command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-focused", + "markdownDescription": "Enables the is_focused command without any pre-configured scope." + }, + { + "description": "Enables the is_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-fullscreen", + "markdownDescription": "Enables the is_fullscreen command without any pre-configured scope." + }, + { + "description": "Enables the is_maximizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-maximizable", + "markdownDescription": "Enables the is_maximizable command without any pre-configured scope." + }, + { + "description": "Enables the is_maximized command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-maximized", + "markdownDescription": "Enables the is_maximized command without any pre-configured scope." + }, + { + "description": "Enables the is_minimizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-minimizable", + "markdownDescription": "Enables the is_minimizable command without any pre-configured scope." + }, + { + "description": "Enables the is_minimized command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-minimized", + "markdownDescription": "Enables the is_minimized command without any pre-configured scope." + }, + { + "description": "Enables the is_resizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-resizable", + "markdownDescription": "Enables the is_resizable command without any pre-configured scope." + }, + { + "description": "Enables the is_visible command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-is-visible", + "markdownDescription": "Enables the is_visible command without any pre-configured scope." + }, + { + "description": "Enables the maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-maximize", + "markdownDescription": "Enables the maximize command without any pre-configured scope." + }, + { + "description": "Enables the minimize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-minimize", + "markdownDescription": "Enables the minimize command without any pre-configured scope." + }, + { + "description": "Enables the monitor_from_point command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-monitor-from-point", + "markdownDescription": "Enables the monitor_from_point command without any pre-configured scope." + }, + { + "description": "Enables the outer_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-outer-position", + "markdownDescription": "Enables the outer_position command without any pre-configured scope." + }, + { + "description": "Enables the outer_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-outer-size", + "markdownDescription": "Enables the outer_size command without any pre-configured scope." + }, + { + "description": "Enables the primary_monitor command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-primary-monitor", + "markdownDescription": "Enables the primary_monitor command without any pre-configured scope." + }, + { + "description": "Enables the request_user_attention command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-request-user-attention", + "markdownDescription": "Enables the request_user_attention command without any pre-configured scope." + }, + { + "description": "Enables the scale_factor command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-scale-factor", + "markdownDescription": "Enables the scale_factor command without any pre-configured scope." + }, + { + "description": "Enables the set_always_on_bottom command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-always-on-bottom", + "markdownDescription": "Enables the set_always_on_bottom command without any pre-configured scope." + }, + { + "description": "Enables the set_always_on_top command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-always-on-top", + "markdownDescription": "Enables the set_always_on_top command without any pre-configured scope." + }, + { + "description": "Enables the set_background_color command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-background-color", + "markdownDescription": "Enables the set_background_color command without any pre-configured scope." + }, + { + "description": "Enables the set_badge_count command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-badge-count", + "markdownDescription": "Enables the set_badge_count command without any pre-configured scope." + }, + { + "description": "Enables the set_badge_label command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-badge-label", + "markdownDescription": "Enables the set_badge_label command without any pre-configured scope." + }, + { + "description": "Enables the set_closable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-closable", + "markdownDescription": "Enables the set_closable command without any pre-configured scope." + }, + { + "description": "Enables the set_content_protected command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-content-protected", + "markdownDescription": "Enables the set_content_protected command without any pre-configured scope." + }, + { + "description": "Enables the set_cursor_grab command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-cursor-grab", + "markdownDescription": "Enables the set_cursor_grab command without any pre-configured scope." + }, + { + "description": "Enables the set_cursor_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-cursor-icon", + "markdownDescription": "Enables the set_cursor_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_cursor_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-cursor-position", + "markdownDescription": "Enables the set_cursor_position command without any pre-configured scope." + }, + { + "description": "Enables the set_cursor_visible command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-cursor-visible", + "markdownDescription": "Enables the set_cursor_visible command without any pre-configured scope." + }, + { + "description": "Enables the set_decorations command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-decorations", + "markdownDescription": "Enables the set_decorations command without any pre-configured scope." + }, + { + "description": "Enables the set_effects command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-effects", + "markdownDescription": "Enables the set_effects command without any pre-configured scope." + }, + { + "description": "Enables the set_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-enabled", + "markdownDescription": "Enables the set_enabled command without any pre-configured scope." + }, + { + "description": "Enables the set_focus command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-focus", + "markdownDescription": "Enables the set_focus command without any pre-configured scope." + }, + { + "description": "Enables the set_focusable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-focusable", + "markdownDescription": "Enables the set_focusable command without any pre-configured scope." + }, + { + "description": "Enables the set_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-fullscreen", + "markdownDescription": "Enables the set_fullscreen command without any pre-configured scope." + }, + { + "description": "Enables the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-icon", + "markdownDescription": "Enables the set_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_ignore_cursor_events command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-ignore-cursor-events", + "markdownDescription": "Enables the set_ignore_cursor_events command without any pre-configured scope." + }, + { + "description": "Enables the set_max_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-max-size", + "markdownDescription": "Enables the set_max_size command without any pre-configured scope." + }, + { + "description": "Enables the set_maximizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-maximizable", + "markdownDescription": "Enables the set_maximizable command without any pre-configured scope." + }, + { + "description": "Enables the set_min_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-min-size", + "markdownDescription": "Enables the set_min_size command without any pre-configured scope." + }, + { + "description": "Enables the set_minimizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-minimizable", + "markdownDescription": "Enables the set_minimizable command without any pre-configured scope." + }, + { + "description": "Enables the set_overlay_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-overlay-icon", + "markdownDescription": "Enables the set_overlay_icon command without any pre-configured scope." + }, + { + "description": "Enables the set_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-position", + "markdownDescription": "Enables the set_position command without any pre-configured scope." + }, + { + "description": "Enables the set_progress_bar command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-progress-bar", + "markdownDescription": "Enables the set_progress_bar command without any pre-configured scope." + }, + { + "description": "Enables the set_resizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-resizable", + "markdownDescription": "Enables the set_resizable command without any pre-configured scope." + }, + { + "description": "Enables the set_shadow command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-shadow", + "markdownDescription": "Enables the set_shadow command without any pre-configured scope." + }, + { + "description": "Enables the set_simple_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-simple-fullscreen", + "markdownDescription": "Enables the set_simple_fullscreen command without any pre-configured scope." + }, + { + "description": "Enables the set_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-size", + "markdownDescription": "Enables the set_size command without any pre-configured scope." + }, + { + "description": "Enables the set_size_constraints command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-size-constraints", + "markdownDescription": "Enables the set_size_constraints command without any pre-configured scope." + }, + { + "description": "Enables the set_skip_taskbar command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-skip-taskbar", + "markdownDescription": "Enables the set_skip_taskbar command without any pre-configured scope." + }, + { + "description": "Enables the set_theme command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-theme", + "markdownDescription": "Enables the set_theme command without any pre-configured scope." + }, + { + "description": "Enables the set_title command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-title", + "markdownDescription": "Enables the set_title command without any pre-configured scope." + }, + { + "description": "Enables the set_title_bar_style command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-title-bar-style", + "markdownDescription": "Enables the set_title_bar_style command without any pre-configured scope." + }, + { + "description": "Enables the set_visible_on_all_workspaces command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-set-visible-on-all-workspaces", + "markdownDescription": "Enables the set_visible_on_all_workspaces command without any pre-configured scope." + }, + { + "description": "Enables the show command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-show", + "markdownDescription": "Enables the show command without any pre-configured scope." + }, + { + "description": "Enables the start_dragging command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-start-dragging", + "markdownDescription": "Enables the start_dragging command without any pre-configured scope." + }, + { + "description": "Enables the start_resize_dragging command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-start-resize-dragging", + "markdownDescription": "Enables the start_resize_dragging command without any pre-configured scope." + }, + { + "description": "Enables the theme command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-theme", + "markdownDescription": "Enables the theme command without any pre-configured scope." + }, + { + "description": "Enables the title command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-title", + "markdownDescription": "Enables the title command without any pre-configured scope." + }, + { + "description": "Enables the toggle_maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-toggle-maximize", + "markdownDescription": "Enables the toggle_maximize command without any pre-configured scope." + }, + { + "description": "Enables the unmaximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-unmaximize", + "markdownDescription": "Enables the unmaximize command without any pre-configured scope." + }, + { + "description": "Enables the unminimize command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-unminimize", + "markdownDescription": "Enables the unminimize command without any pre-configured scope." + }, + { + "description": "Denies the available_monitors command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-available-monitors", + "markdownDescription": "Denies the available_monitors command without any pre-configured scope." + }, + { + "description": "Denies the center command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-center", + "markdownDescription": "Denies the center command without any pre-configured scope." + }, + { + "description": "Denies the close command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-close", + "markdownDescription": "Denies the close command without any pre-configured scope." + }, + { + "description": "Denies the create command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-create", + "markdownDescription": "Denies the create command without any pre-configured scope." + }, + { + "description": "Denies the current_monitor command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-current-monitor", + "markdownDescription": "Denies the current_monitor command without any pre-configured scope." + }, + { + "description": "Denies the cursor_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-cursor-position", + "markdownDescription": "Denies the cursor_position command without any pre-configured scope." + }, + { + "description": "Denies the destroy command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-destroy", + "markdownDescription": "Denies the destroy command without any pre-configured scope." + }, + { + "description": "Denies the get_all_windows command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-get-all-windows", + "markdownDescription": "Denies the get_all_windows command without any pre-configured scope." + }, + { + "description": "Denies the hide command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-hide", + "markdownDescription": "Denies the hide command without any pre-configured scope." + }, + { + "description": "Denies the inner_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-inner-position", + "markdownDescription": "Denies the inner_position command without any pre-configured scope." + }, + { + "description": "Denies the inner_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-inner-size", + "markdownDescription": "Denies the inner_size command without any pre-configured scope." + }, + { + "description": "Denies the internal_toggle_maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-internal-toggle-maximize", + "markdownDescription": "Denies the internal_toggle_maximize command without any pre-configured scope." + }, + { + "description": "Denies the is_always_on_top command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-always-on-top", + "markdownDescription": "Denies the is_always_on_top command without any pre-configured scope." + }, + { + "description": "Denies the is_closable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-closable", + "markdownDescription": "Denies the is_closable command without any pre-configured scope." + }, + { + "description": "Denies the is_decorated command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-decorated", + "markdownDescription": "Denies the is_decorated command without any pre-configured scope." + }, + { + "description": "Denies the is_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-enabled", + "markdownDescription": "Denies the is_enabled command without any pre-configured scope." + }, + { + "description": "Denies the is_focused command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-focused", + "markdownDescription": "Denies the is_focused command without any pre-configured scope." + }, + { + "description": "Denies the is_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-fullscreen", + "markdownDescription": "Denies the is_fullscreen command without any pre-configured scope." + }, + { + "description": "Denies the is_maximizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-maximizable", + "markdownDescription": "Denies the is_maximizable command without any pre-configured scope." + }, + { + "description": "Denies the is_maximized command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-maximized", + "markdownDescription": "Denies the is_maximized command without any pre-configured scope." + }, + { + "description": "Denies the is_minimizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-minimizable", + "markdownDescription": "Denies the is_minimizable command without any pre-configured scope." + }, + { + "description": "Denies the is_minimized command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-minimized", + "markdownDescription": "Denies the is_minimized command without any pre-configured scope." + }, + { + "description": "Denies the is_resizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-resizable", + "markdownDescription": "Denies the is_resizable command without any pre-configured scope." + }, + { + "description": "Denies the is_visible command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-is-visible", + "markdownDescription": "Denies the is_visible command without any pre-configured scope." + }, + { + "description": "Denies the maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-maximize", + "markdownDescription": "Denies the maximize command without any pre-configured scope." + }, + { + "description": "Denies the minimize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-minimize", + "markdownDescription": "Denies the minimize command without any pre-configured scope." + }, + { + "description": "Denies the monitor_from_point command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-monitor-from-point", + "markdownDescription": "Denies the monitor_from_point command without any pre-configured scope." + }, + { + "description": "Denies the outer_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-outer-position", + "markdownDescription": "Denies the outer_position command without any pre-configured scope." + }, + { + "description": "Denies the outer_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-outer-size", + "markdownDescription": "Denies the outer_size command without any pre-configured scope." + }, + { + "description": "Denies the primary_monitor command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-primary-monitor", + "markdownDescription": "Denies the primary_monitor command without any pre-configured scope." + }, + { + "description": "Denies the request_user_attention command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-request-user-attention", + "markdownDescription": "Denies the request_user_attention command without any pre-configured scope." + }, + { + "description": "Denies the scale_factor command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-scale-factor", + "markdownDescription": "Denies the scale_factor command without any pre-configured scope." + }, + { + "description": "Denies the set_always_on_bottom command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-always-on-bottom", + "markdownDescription": "Denies the set_always_on_bottom command without any pre-configured scope." + }, + { + "description": "Denies the set_always_on_top command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-always-on-top", + "markdownDescription": "Denies the set_always_on_top command without any pre-configured scope." + }, + { + "description": "Denies the set_background_color command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-background-color", + "markdownDescription": "Denies the set_background_color command without any pre-configured scope." + }, + { + "description": "Denies the set_badge_count command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-badge-count", + "markdownDescription": "Denies the set_badge_count command without any pre-configured scope." + }, + { + "description": "Denies the set_badge_label command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-badge-label", + "markdownDescription": "Denies the set_badge_label command without any pre-configured scope." + }, + { + "description": "Denies the set_closable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-closable", + "markdownDescription": "Denies the set_closable command without any pre-configured scope." + }, + { + "description": "Denies the set_content_protected command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-content-protected", + "markdownDescription": "Denies the set_content_protected command without any pre-configured scope." + }, + { + "description": "Denies the set_cursor_grab command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-cursor-grab", + "markdownDescription": "Denies the set_cursor_grab command without any pre-configured scope." + }, + { + "description": "Denies the set_cursor_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-cursor-icon", + "markdownDescription": "Denies the set_cursor_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_cursor_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-cursor-position", + "markdownDescription": "Denies the set_cursor_position command without any pre-configured scope." + }, + { + "description": "Denies the set_cursor_visible command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-cursor-visible", + "markdownDescription": "Denies the set_cursor_visible command without any pre-configured scope." + }, + { + "description": "Denies the set_decorations command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-decorations", + "markdownDescription": "Denies the set_decorations command without any pre-configured scope." + }, + { + "description": "Denies the set_effects command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-effects", + "markdownDescription": "Denies the set_effects command without any pre-configured scope." + }, + { + "description": "Denies the set_enabled command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-enabled", + "markdownDescription": "Denies the set_enabled command without any pre-configured scope." + }, + { + "description": "Denies the set_focus command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-focus", + "markdownDescription": "Denies the set_focus command without any pre-configured scope." + }, + { + "description": "Denies the set_focusable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-focusable", + "markdownDescription": "Denies the set_focusable command without any pre-configured scope." + }, + { + "description": "Denies the set_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-fullscreen", + "markdownDescription": "Denies the set_fullscreen command without any pre-configured scope." + }, + { + "description": "Denies the set_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-icon", + "markdownDescription": "Denies the set_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_ignore_cursor_events command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-ignore-cursor-events", + "markdownDescription": "Denies the set_ignore_cursor_events command without any pre-configured scope." + }, + { + "description": "Denies the set_max_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-max-size", + "markdownDescription": "Denies the set_max_size command without any pre-configured scope." + }, + { + "description": "Denies the set_maximizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-maximizable", + "markdownDescription": "Denies the set_maximizable command without any pre-configured scope." + }, + { + "description": "Denies the set_min_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-min-size", + "markdownDescription": "Denies the set_min_size command without any pre-configured scope." + }, + { + "description": "Denies the set_minimizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-minimizable", + "markdownDescription": "Denies the set_minimizable command without any pre-configured scope." + }, + { + "description": "Denies the set_overlay_icon command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-overlay-icon", + "markdownDescription": "Denies the set_overlay_icon command without any pre-configured scope." + }, + { + "description": "Denies the set_position command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-position", + "markdownDescription": "Denies the set_position command without any pre-configured scope." + }, + { + "description": "Denies the set_progress_bar command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-progress-bar", + "markdownDescription": "Denies the set_progress_bar command without any pre-configured scope." + }, + { + "description": "Denies the set_resizable command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-resizable", + "markdownDescription": "Denies the set_resizable command without any pre-configured scope." + }, + { + "description": "Denies the set_shadow command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-shadow", + "markdownDescription": "Denies the set_shadow command without any pre-configured scope." + }, + { + "description": "Denies the set_simple_fullscreen command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-simple-fullscreen", + "markdownDescription": "Denies the set_simple_fullscreen command without any pre-configured scope." + }, + { + "description": "Denies the set_size command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-size", + "markdownDescription": "Denies the set_size command without any pre-configured scope." + }, + { + "description": "Denies the set_size_constraints command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-size-constraints", + "markdownDescription": "Denies the set_size_constraints command without any pre-configured scope." + }, + { + "description": "Denies the set_skip_taskbar command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-skip-taskbar", + "markdownDescription": "Denies the set_skip_taskbar command without any pre-configured scope." + }, + { + "description": "Denies the set_theme command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-theme", + "markdownDescription": "Denies the set_theme command without any pre-configured scope." + }, + { + "description": "Denies the set_title command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-title", + "markdownDescription": "Denies the set_title command without any pre-configured scope." + }, + { + "description": "Denies the set_title_bar_style command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-title-bar-style", + "markdownDescription": "Denies the set_title_bar_style command without any pre-configured scope." + }, + { + "description": "Denies the set_visible_on_all_workspaces command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-set-visible-on-all-workspaces", + "markdownDescription": "Denies the set_visible_on_all_workspaces command without any pre-configured scope." + }, + { + "description": "Denies the show command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-show", + "markdownDescription": "Denies the show command without any pre-configured scope." + }, + { + "description": "Denies the start_dragging command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-start-dragging", + "markdownDescription": "Denies the start_dragging command without any pre-configured scope." + }, + { + "description": "Denies the start_resize_dragging command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-start-resize-dragging", + "markdownDescription": "Denies the start_resize_dragging command without any pre-configured scope." + }, + { + "description": "Denies the theme command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-theme", + "markdownDescription": "Denies the theme command without any pre-configured scope." + }, + { + "description": "Denies the title command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-title", + "markdownDescription": "Denies the title command without any pre-configured scope." + }, + { + "description": "Denies the toggle_maximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-toggle-maximize", + "markdownDescription": "Denies the toggle_maximize command without any pre-configured scope." + }, + { + "description": "Denies the unmaximize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-unmaximize", + "markdownDescription": "Denies the unmaximize command without any pre-configured scope." + }, + { + "description": "Denies the unminimize command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-unminimize", + "markdownDescription": "Denies the unminimize command without any pre-configured scope." + } + ] + }, + "Value": { + "description": "All supported ACL values.", + "anyOf": [ + { + "description": "Represents a null JSON value.", + "type": "null" + }, + { + "description": "Represents a [`bool`].", + "type": "boolean" + }, + { + "description": "Represents a valid ACL [`Number`].", + "allOf": [ + { + "$ref": "#/definitions/Number" + } + ] + }, + { + "description": "Represents a [`String`].", + "type": "string" + }, + { + "description": "Represents a list of other [`Value`]s.", + "type": "array", + "items": { + "$ref": "#/definitions/Value" + } + }, + { + "description": "Represents a map of [`String`] keys to [`Value`]s.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/Value" + } + } + ] + }, + "Number": { + "description": "A valid ACL number.", + "anyOf": [ + { + "description": "Represents an [`i64`].", + "type": "integer", + "format": "int64" + }, + { + "description": "Represents a [`f64`].", + "type": "number", + "format": "double" + } + ] + }, + "Target": { + "description": "Platform target.", + "oneOf": [ + { + "description": "MacOS.", + "type": "string", + "enum": ["macOS"] + }, + { + "description": "Windows.", + "type": "string", + "enum": ["windows"] + }, + { + "description": "Linux.", + "type": "string", + "enum": ["linux"] + }, + { + "description": "Android.", + "type": "string", + "enum": ["android"] + }, + { + "description": "iOS.", + "type": "string", + "enum": ["iOS"] + } + ] + } + } +} diff --git a/foundry/packages/desktop/src-tauri/icons/128x128.png b/foundry/packages/desktop/src-tauri/icons/128x128.png index 40cb79f9..26ce45a2 100644 Binary files a/foundry/packages/desktop/src-tauri/icons/128x128.png and b/foundry/packages/desktop/src-tauri/icons/128x128.png differ diff --git a/foundry/packages/desktop/src-tauri/icons/128x128@2x.png b/foundry/packages/desktop/src-tauri/icons/128x128@2x.png index de99a947..3c7824a1 100644 Binary files a/foundry/packages/desktop/src-tauri/icons/128x128@2x.png and b/foundry/packages/desktop/src-tauri/icons/128x128@2x.png differ diff --git a/foundry/packages/desktop/src-tauri/icons/32x32.png b/foundry/packages/desktop/src-tauri/icons/32x32.png index 0b9b8d90..73c7711d 100644 Binary files a/foundry/packages/desktop/src-tauri/icons/32x32.png and b/foundry/packages/desktop/src-tauri/icons/32x32.png differ diff --git a/foundry/packages/desktop/src-tauri/icons/64x64.png b/foundry/packages/desktop/src-tauri/icons/64x64.png index 4849c59b..5134ebb9 100644 Binary files a/foundry/packages/desktop/src-tauri/icons/64x64.png and b/foundry/packages/desktop/src-tauri/icons/64x64.png differ diff --git a/foundry/packages/desktop/src-tauri/icons/icon-layer-background.svg b/foundry/packages/desktop/src-tauri/icons/icon-layer-background.svg new file mode 100644 index 00000000..bef9c492 --- /dev/null +++ b/foundry/packages/desktop/src-tauri/icons/icon-layer-background.svg @@ -0,0 +1,4 @@ + + + + diff --git a/foundry/packages/desktop/src-tauri/icons/icon-layer-border.svg b/foundry/packages/desktop/src-tauri/icons/icon-layer-border.svg new file mode 100644 index 00000000..bd95e5e7 --- /dev/null +++ b/foundry/packages/desktop/src-tauri/icons/icon-layer-border.svg @@ -0,0 +1,5 @@ + + + + diff --git a/foundry/packages/desktop/src-tauri/icons/icon-layer-logo.svg b/foundry/packages/desktop/src-tauri/icons/icon-layer-logo.svg new file mode 100644 index 00000000..7ef6a223 --- /dev/null +++ b/foundry/packages/desktop/src-tauri/icons/icon-layer-logo.svg @@ -0,0 +1,8 @@ + + + + + + diff --git a/foundry/packages/desktop/src-tauri/icons/icon-source.svg b/foundry/packages/desktop/src-tauri/icons/icon-source.svg index 7db083d6..0acc14f2 100644 --- a/foundry/packages/desktop/src-tauri/icons/icon-source.svg +++ b/foundry/packages/desktop/src-tauri/icons/icon-source.svg @@ -16,7 +16,7 @@ "/> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - - + - - - - - + + + + - - - - - - + + + diff --git a/foundry/packages/desktop/src-tauri/icons/icon.icns b/foundry/packages/desktop/src-tauri/icons/icon.icns index 5757cea2..d6406e2b 100644 Binary files a/foundry/packages/desktop/src-tauri/icons/icon.icns and b/foundry/packages/desktop/src-tauri/icons/icon.icns differ diff --git a/foundry/packages/desktop/src-tauri/icons/icon.ico b/foundry/packages/desktop/src-tauri/icons/icon.ico index 2dc83065..7174e096 100644 Binary files a/foundry/packages/desktop/src-tauri/icons/icon.ico and b/foundry/packages/desktop/src-tauri/icons/icon.ico differ diff --git a/foundry/packages/desktop/src-tauri/icons/icon.png b/foundry/packages/desktop/src-tauri/icons/icon.png index c11a109e..d8cf29be 100644 Binary files a/foundry/packages/desktop/src-tauri/icons/icon.png and b/foundry/packages/desktop/src-tauri/icons/icon.png differ diff --git a/foundry/packages/desktop/src-tauri/src/lib.rs b/foundry/packages/desktop/src-tauri/src/lib.rs index f8117bc0..eda4761c 100644 --- a/foundry/packages/desktop/src-tauri/src/lib.rs +++ b/foundry/packages/desktop/src-tauri/src/lib.rs @@ -1,28 +1,44 @@ use std::sync::Mutex; -use tauri::{AppHandle, LogicalPosition, Manager, WebviewUrl, WebviewWindowBuilder}; + +#[cfg(not(mobile))] +use tauri::{LogicalPosition, Manager, WebviewUrl, WebviewWindowBuilder}; + +#[cfg(not(mobile))] use tauri_plugin_shell::process::CommandChild; +#[cfg(not(mobile))] use tauri_plugin_shell::ShellExt; struct BackendState { + #[cfg(not(mobile))] child: Mutex>, + backend_url: Mutex, +} + +#[tauri::command] +fn get_backend_url(state: tauri::State) -> String { + state.backend_url.lock().unwrap().clone() } #[tauri::command] -fn get_backend_url() -> String { - "http://127.0.0.1:7741".to_string() +fn set_backend_url(url: String, state: tauri::State) { + *state.backend_url.lock().unwrap() = url; } #[tauri::command] -async fn backend_health() -> Result { - match reqwest::get("http://127.0.0.1:7741/api/rivet/metadata").await { +async fn backend_health(state: tauri::State<'_, BackendState>) -> Result { + let base = state.backend_url.lock().unwrap().clone(); + let url = format!("{}/api/rivet/metadata", base); + match reqwest::get(&url).await { Ok(resp) => Ok(resp.status().is_success()), Err(_) => Ok(false), } } -async fn wait_for_backend(timeout_secs: u64) -> Result<(), String> { +#[cfg(not(mobile))] +async fn wait_for_backend(base_url: String, timeout_secs: u64) -> Result<(), String> { let start = std::time::Instant::now(); let timeout = std::time::Duration::from_secs(timeout_secs); + let url = format!("{}/api/rivet/metadata", base_url); loop { if start.elapsed() > timeout { @@ -32,7 +48,7 @@ async fn wait_for_backend(timeout_secs: u64) -> Result<(), String> { )); } - match reqwest::get("http://127.0.0.1:7741/api/rivet/metadata").await { + match reqwest::get(&url).await { Ok(resp) if resp.status().is_success() => return Ok(()), _ => {} } @@ -41,7 +57,8 @@ async fn wait_for_backend(timeout_secs: u64) -> Result<(), String> { } } -fn spawn_backend(app: &AppHandle) -> Result<(), String> { +#[cfg(not(mobile))] +fn spawn_backend(app: &tauri::AppHandle) -> Result<(), String> { let sidecar = app .shell() .sidecar("sidecars/foundry-backend") @@ -88,65 +105,95 @@ fn spawn_backend(app: &AppHandle) -> Result<(), String> { #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { - tauri::Builder::default() - .plugin(tauri_plugin_shell::init()) + let builder = tauri::Builder::default(); + + // Shell plugin is desktop-only (used for sidecar spawning) + #[cfg(not(mobile))] + let builder = builder.plugin(tauri_plugin_shell::init()); + + builder .manage(BackendState { + #[cfg(not(mobile))] child: Mutex::new(None), + backend_url: Mutex::new("http://127.0.0.1:7741".to_string()), }) - .invoke_handler(tauri::generate_handler![get_backend_url, backend_health]) - .setup(|app| { - // Create main window programmatically so we can set traffic light position - let url = if cfg!(debug_assertions) { - WebviewUrl::External("http://localhost:4173".parse().unwrap()) - } else { - WebviewUrl::default() - }; - - let mut builder = WebviewWindowBuilder::new(app, "main", url) - .title("Foundry") - .inner_size(1280.0, 800.0) - .min_inner_size(900.0, 600.0) - .resizable(true) - .theme(Some(tauri::Theme::Dark)) - .title_bar_style(tauri::TitleBarStyle::Overlay) - .hidden_title(true); - - #[cfg(target_os = "macos")] + .invoke_handler(tauri::generate_handler![ + get_backend_url, + set_backend_url, + backend_health + ]) + .setup(|_app| { + #[cfg(not(mobile))] + let app = _app; + // On desktop, create window programmatically for traffic light position + #[cfg(not(mobile))] { - builder = builder.traffic_light_position(LogicalPosition::new(14.0, 14.0)); - } - - builder.build()?; + let url = if cfg!(debug_assertions) { + WebviewUrl::External("http://localhost:4173".parse().unwrap()) + } else { + WebviewUrl::default() + }; + + let mut win_builder = WebviewWindowBuilder::new(app, "main", url) + .title("Foundry") + .inner_size(1280.0, 800.0) + .min_inner_size(900.0, 600.0) + .resizable(true) + .theme(Some(tauri::Theme::Dark)) + .title_bar_style(tauri::TitleBarStyle::Overlay) + .hidden_title(true); + + #[cfg(target_os = "macos")] + { + win_builder = + win_builder.traffic_light_position(LogicalPosition::new(14.0, 14.0)); + } - // In debug mode, assume the developer is running the backend externally - if cfg!(debug_assertions) { - eprintln!("[foundry-desktop] Dev mode: skipping sidecar spawn. Run the backend separately."); - return Ok(()); + win_builder.build()?; } - let handle = app.handle().clone(); - tauri::async_runtime::spawn(async move { - if let Err(e) = spawn_backend(&handle) { - eprintln!("[foundry-desktop] Failed to start backend: {}", e); - return; - } + // On mobile, Tauri creates the webview automatically — no window setup needed. + // The backend URL will be set by the frontend via set_backend_url. - match wait_for_backend(30).await { - Ok(()) => eprintln!("[foundry-desktop] Backend is ready."), - Err(e) => eprintln!("[foundry-desktop] {}", e), + // Sidecar spawning is desktop-only + #[cfg(not(mobile))] + { + // In debug mode, assume the developer is running the backend externally + if cfg!(debug_assertions) { + eprintln!( + "[foundry] Dev mode: skipping sidecar spawn. Run the backend separately." + ); + return Ok(()); } - }); + + let handle = app.handle().clone(); + tauri::async_runtime::spawn(async move { + if let Err(e) = spawn_backend(&handle) { + eprintln!("[foundry] Failed to start backend: {}", e); + return; + } + + match wait_for_backend("http://127.0.0.1:7741".to_string(), 30).await { + Ok(()) => eprintln!("[foundry] Backend is ready."), + Err(e) => eprintln!("[foundry] {}", e), + } + }); + } Ok(()) }) .on_window_event(|window, event| { if let tauri::WindowEvent::Destroyed = event { - let state = window.state::(); - let child = state.child.lock().unwrap().take(); - if let Some(child) = child { - let _ = child.kill(); - eprintln!("[foundry-desktop] Backend sidecar killed."); + #[cfg(not(mobile))] + { + let state = window.state::(); + let child = state.child.lock().unwrap().take(); + if let Some(child) = child { + let _ = child.kill(); + eprintln!("[foundry] Backend sidecar killed."); + } } + let _ = window; // suppress unused warning on mobile } }) .run(tauri::generate_context!()) diff --git a/foundry/packages/desktop/src-tauri/tauri.android.conf.json b/foundry/packages/desktop/src-tauri/tauri.android.conf.json new file mode 100644 index 00000000..3020e366 --- /dev/null +++ b/foundry/packages/desktop/src-tauri/tauri.android.conf.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://raw.githubusercontent.com/tauri-apps/tauri/dev/crates/tauri-cli/schema.json", + "build": { + "beforeDevCommand": "FOUNDRY_FRONTEND_CLIENT_MODE=mock VITE_MOBILE=1 pnpm --filter @sandbox-agent/foundry-frontend dev --host 0.0.0.0 --port 4173" + }, + "bundle": { + "externalBin": [] + }, + "plugins": {} +} diff --git a/foundry/packages/desktop/src-tauri/tauri.ios.conf.json b/foundry/packages/desktop/src-tauri/tauri.ios.conf.json new file mode 100644 index 00000000..8a13e6d2 --- /dev/null +++ b/foundry/packages/desktop/src-tauri/tauri.ios.conf.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://raw.githubusercontent.com/tauri-apps/tauri/dev/crates/tauri-cli/schema.json", + "build": { + "beforeDevCommand": "FOUNDRY_FRONTEND_CLIENT_MODE=mock VITE_MOBILE=1 pnpm --filter @sandbox-agent/foundry-frontend dev --host 0.0.0.0 --port 4173", + "devUrl": "http://localhost:4173" + }, + "bundle": { + "externalBin": [] + }, + "plugins": {} +} diff --git a/foundry/packages/frontend/index.html b/foundry/packages/frontend/index.html index dc0af739..f0e8694c 100644 --- a/foundry/packages/frontend/index.html +++ b/foundry/packages/frontend/index.html @@ -13,7 +13,7 @@ - + Foundry diff --git a/foundry/packages/frontend/public/sounds/notification-1.mp3 b/foundry/packages/frontend/public/sounds/notification-1.mp3 new file mode 100644 index 00000000..d678983c Binary files /dev/null and b/foundry/packages/frontend/public/sounds/notification-1.mp3 differ diff --git a/foundry/packages/frontend/public/sounds/notification-2.mp3 b/foundry/packages/frontend/public/sounds/notification-2.mp3 new file mode 100644 index 00000000..677a5810 Binary files /dev/null and b/foundry/packages/frontend/public/sounds/notification-2.mp3 differ diff --git a/foundry/packages/frontend/src/components/mock-layout.tsx b/foundry/packages/frontend/src/components/mock-layout.tsx index 213109ee..0c4c2b11 100644 --- a/foundry/packages/frontend/src/components/mock-layout.tsx +++ b/foundry/packages/frontend/src/components/mock-layout.tsx @@ -2,8 +2,10 @@ import { memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useStat import { useNavigate } from "@tanstack/react-router"; import { useStyletron } from "baseui"; +import type { WorkbenchPresence } from "@sandbox-agent/foundry-shared"; import { PanelLeft, PanelRight } from "lucide-react"; import { useFoundryTokens } from "../app/theme"; +import { useAgentDoneNotification } from "../lib/notification-sound"; import { DiffContent } from "./mock-layout/diff-content"; import { MessageList } from "./mock-layout/message-list"; @@ -11,15 +13,17 @@ import { PromptComposer } from "./mock-layout/prompt-composer"; import { RightSidebar } from "./mock-layout/right-sidebar"; import { Sidebar } from "./mock-layout/sidebar"; import { TabStrip } from "./mock-layout/tab-strip"; -import { TerminalPane } from "./mock-layout/terminal-pane"; +import { TerminalPane, type ProcessTab } from "./mock-layout/terminal-pane"; import { TranscriptHeader } from "./mock-layout/transcript-header"; -import { PROMPT_TEXTAREA_MAX_HEIGHT, PROMPT_TEXTAREA_MIN_HEIGHT, SPanel, ScrollBody, Shell } from "./mock-layout/ui"; +import { PROMPT_TEXTAREA_MAX_HEIGHT, PROMPT_TEXTAREA_MIN_HEIGHT, SPanel, ScrollBody, Shell, Tooltip } from "./mock-layout/ui"; import { buildDisplayMessages, diffPath, diffTabId, formatThinkingDuration, isDiffTab, + isTerminalTab, + terminalTabId, buildHistoryEvents, type Task, type HistoryEvent, @@ -27,8 +31,10 @@ import { type Message, type ModelId, } from "./mock-layout/view-model"; -import { activeMockOrganization, useMockAppSnapshot } from "../lib/mock-app"; +import { activeMockOrganization, activeMockUser, useMockAppSnapshot } from "../lib/mock-app"; +import { useIsMobile } from "../lib/platform"; import { getTaskWorkbenchClient } from "../lib/workbench"; +import { MobileLayout } from "./mock-layout/mobile-layout"; function firstAgentTabId(task: Task): string | null { return task.tabs[0]?.id ?? null; @@ -58,12 +64,127 @@ function sanitizeActiveTabId(task: Task, tabId: string | null | undefined, openD if (isDiffTab(tabId) && openDiffs.includes(diffPath(tabId))) { return tabId; } + if (isTerminalTab(tabId)) { + return tabId; + } } return openDiffs.length > 0 ? diffTabId(openDiffs[openDiffs.length - 1]!) : lastAgentTabId; } +function TypingIndicator({ presence, currentUserId }: { presence: WorkbenchPresence[]; currentUserId: string | null }) { + const [css] = useStyletron(); + const t = useFoundryTokens(); + const typingMembers = presence.filter((member) => member.typing && member.memberId !== currentUserId); + const isTyping = typingMembers.length > 0; + const [animState, setAnimState] = useState<"in" | "out" | "hidden">(isTyping ? "in" : "hidden"); + const lastMembersRef = useRef(typingMembers); + + if (isTyping) { + lastMembersRef.current = typingMembers; + } + + useEffect(() => { + if (isTyping) { + setAnimState("in"); + } else if (lastMembersRef.current.length > 0) { + setAnimState("out"); + } + }, [isTyping]); + + if (animState === "hidden") return null; + + const members = lastMembersRef.current; + if (members.length === 0) return null; + const label = + members.length === 1 + ? `${members[0]!.name} is typing` + : members.length === 2 + ? `${members[0]!.name} & ${members[1]!.name} are typing` + : `${members[0]!.name} & ${members.length - 1} others are typing`; + + return ( +
{ + if (animState === "out") setAnimState("hidden"); + }} + > +
+ {members.slice(0, 3).map((member) => + member.avatarUrl ? ( + + ) : ( +
+ {member.name.charAt(0).toUpperCase()} +
+ ), + )} +
+ + {label} + {[0, 1, 2].map((i) => ( + + . + + ))} + +
+ ); +} + const TranscriptPanel = memo(function TranscriptPanel({ + workspaceId, taskWorkbenchClient, task, activeTabId, @@ -80,7 +201,18 @@ const TranscriptPanel = memo(function TranscriptPanel({ rightSidebarCollapsed, onToggleRightSidebar, onNavigateToUsage, + terminalTabOpen, + onOpenTerminalTab, + onCloseTerminalTab, + terminalProcessTabs, + onTerminalProcessTabsChange, + terminalActiveTabId, + onTerminalActiveTabIdChange, + terminalCustomNames, + onTerminalCustomNamesChange, + mobile, }: { + workspaceId: string; taskWorkbenchClient: ReturnType; task: Task; activeTabId: string | null; @@ -97,8 +229,20 @@ const TranscriptPanel = memo(function TranscriptPanel({ rightSidebarCollapsed?: boolean; onToggleRightSidebar?: () => void; onNavigateToUsage?: () => void; + terminalTabOpen?: boolean; + onOpenTerminalTab?: () => void; + onCloseTerminalTab?: () => void; + terminalProcessTabs?: ProcessTab[]; + onTerminalProcessTabsChange?: (tabs: ProcessTab[]) => void; + terminalActiveTabId?: string | null; + onTerminalActiveTabIdChange?: (id: string | null) => void; + terminalCustomNames?: Record; + onTerminalCustomNamesChange?: (names: Record) => void; + mobile?: boolean; }) { const t = useFoundryTokens(); + const transcriptAppSnapshot = useMockAppSnapshot(); + const currentUser = activeMockUser(transcriptAppSnapshot); const [defaultModel, setDefaultModel] = useState("claude-sonnet-4"); const [editingField, setEditingField] = useState<"title" | "branch" | null>(null); const [editValue, setEditValue] = useState(""); @@ -111,9 +255,11 @@ const TranscriptPanel = memo(function TranscriptPanel({ const textareaRef = useRef(null); const messageRefs = useRef(new Map()); const activeDiff = activeTabId && isDiffTab(activeTabId) ? diffPath(activeTabId) : null; - const activeAgentTab = activeDiff ? null : (task.tabs.find((candidate) => candidate.id === activeTabId) ?? task.tabs[0] ?? null); + const activeTerminal = activeTabId && isTerminalTab(activeTabId) ? true : false; + const activeAgentTab = activeDiff || activeTerminal ? null : (task.tabs.find((candidate) => candidate.id === activeTabId) ?? task.tabs[0] ?? null); const promptTab = task.tabs.find((candidate) => candidate.id === lastAgentTabId) ?? task.tabs[0] ?? null; const isTerminal = task.status === "archived"; + useAgentDoneNotification(promptTab?.status); const historyEvents = useMemo(() => buildHistoryEvents(task.tabs), [task.tabs]); const activeMessages = useMemo(() => buildDisplayMessages(activeAgentTab), [activeAgentTab]); const draft = promptTab?.draft.text ?? ""; @@ -271,7 +417,7 @@ const TranscriptPanel = memo(function TranscriptPanel({ (tabId: string) => { onSetActiveTabId(tabId); - if (!isDiffTab(tabId)) { + if (!isDiffTab(tabId) && !isTerminalTab(tabId)) { onSetLastAgentTabId(tabId); const tab = task.tabs.find((candidate) => candidate.id === tabId); if (tab?.unread) { @@ -448,28 +594,30 @@ const TranscriptPanel = memo(function TranscriptPanel({ return ( - { - if (activeAgentTab) { - setTabUnread(activeAgentTab.id, unread); - } - }} - sidebarCollapsed={sidebarCollapsed} - onToggleSidebar={onToggleSidebar} - onSidebarPeekStart={onSidebarPeekStart} - onSidebarPeekEnd={onSidebarPeekEnd} - rightSidebarCollapsed={rightSidebarCollapsed} - onToggleRightSidebar={onToggleRightSidebar} - onNavigateToUsage={onNavigateToUsage} - /> + {!mobile && ( + { + if (activeAgentTab) { + setTabUnread(activeAgentTab.id, unread); + } + }} + sidebarCollapsed={sidebarCollapsed} + onToggleSidebar={onToggleSidebar} + onSidebarPeekStart={onSidebarPeekStart} + onSidebarPeekEnd={onSidebarPeekEnd} + rightSidebarCollapsed={rightSidebarCollapsed} + onToggleRightSidebar={onToggleRightSidebar} + onNavigateToUsage={onNavigateToUsage} + /> + )}
- {activeDiff ? ( + {activeTerminal ? ( +
+ +
+ ) : activeDiff ? ( file.path === activeDiff)} @@ -563,25 +732,30 @@ const TranscriptPanel = memo(function TranscriptPanel({ void copyMessage(message); }} thinkingTimerLabel={thinkingTimerLabel} + userName={currentUser?.name ?? null} + userAvatarUrl={currentUser?.avatarUrl ?? null} /> )} - {!isTerminal && promptTab ? ( - updateDraft(value, attachments)} - onSend={sendMessage} - onStop={stopAgent} - onRemoveAttachment={removeAttachment} - onChangeModel={changeModel} - onSetDefaultModel={setDefaultModel} - /> + {!isTerminal && !activeTerminal && promptTab ? ( + <> + + updateDraft(value, attachments)} + onSend={sendMessage} + onStop={stopAgent} + onRemoveAttachment={removeAttachment} + onChangeModel={changeModel} + onSetDefaultModel={setDefaultModel} + /> + ) : null}
@@ -670,6 +844,14 @@ const RightRail = memo(function RightRail({ onRevertFile, onPublishPr, onToggleSidebar, + onOpenTerminalTab, + terminalTabOpen, + terminalProcessTabs, + onTerminalProcessTabsChange, + terminalActiveTabId, + onTerminalActiveTabIdChange, + terminalCustomNames, + onTerminalCustomNamesChange, }: { workspaceId: string; task: Task; @@ -679,6 +861,14 @@ const RightRail = memo(function RightRail({ onRevertFile: (path: string) => void; onPublishPr: () => void; onToggleSidebar?: () => void; + onOpenTerminalTab?: () => void; + terminalTabOpen?: boolean; + terminalProcessTabs?: ProcessTab[]; + onTerminalProcessTabsChange?: (tabs: ProcessTab[]) => void; + terminalActiveTabId?: string | null; + onTerminalActiveTabIdChange?: (id: string | null) => void; + terminalCustomNames?: Record; + onTerminalCustomNamesChange?: (names: Record) => void; }) { const [css] = useStyletron(); const t = useFoundryTokens(); @@ -761,6 +951,13 @@ const RightRail = memo(function RightRail({ minWidth: 0, display: "flex", flexDirection: "column", + ...(terminalTabOpen + ? { + borderBottomRightRadius: "12px", + borderBottom: `1px solid ${t.borderDefault}`, + overflow: "hidden", + } + : {}), })} >
@@ -802,6 +999,13 @@ const RightRail = memo(function RightRail({ onCollapse={() => { setTerminalHeight(43); }} + onOpenTerminalTab={onOpenTerminalTab} + processTabs={terminalProcessTabs} + onProcessTabsChange={onTerminalProcessTabsChange} + activeProcessTabId={terminalActiveTabId} + onActiveProcessTabIdChange={onTerminalActiveTabIdChange} + customTabNames={terminalCustomNames} + onCustomTabNamesChange={onTerminalCustomNamesChange} />
@@ -909,6 +1113,11 @@ export function MockLayout({ workspaceId, selectedTaskId, selectedSessionId }: M void navigate({ to: "/organizations/$organizationId/billing" as never, params: { organizationId: activeOrg.id } }); } }, [activeOrg, navigate]); + const navigateToSettings = useCallback(() => { + if (activeOrg) { + void navigate({ to: "/organizations/$organizationId/settings" as never, params: { organizationId: activeOrg.id } as never }); + } + }, [activeOrg, navigate]); const [projectOrder, setProjectOrder] = useState(null); const projects = useMemo(() => { if (!projectOrder) return rawProjects; @@ -922,6 +1131,10 @@ export function MockLayout({ workspaceId, selectedTaskId, selectedSessionId }: M const [activeTabIdByTask, setActiveTabIdByTask] = useState>({}); const [lastAgentTabIdByTask, setLastAgentTabIdByTask] = useState>({}); const [openDiffsByTask, setOpenDiffsByTask] = useState>({}); + const [terminalTabOpenByTask, setTerminalTabOpenByTask] = useState>({}); + const [terminalProcessTabsByTask, setTerminalProcessTabsByTask] = useState>({}); + const [terminalActiveTabIdByTask, setTerminalActiveTabIdByTask] = useState>({}); + const [terminalCustomNamesByTask, setTerminalCustomNamesByTask] = useState>>({}); const [selectedNewTaskRepoId, setSelectedNewTaskRepoId] = useState(""); const [leftWidth, setLeftWidth] = useState(() => readStoredWidth(LEFT_WIDTH_STORAGE_KEY, LEFT_SIDEBAR_DEFAULT_WIDTH)); const [rightWidth, setRightWidth] = useState(() => readStoredWidth(RIGHT_WIDTH_STORAGE_KEY, RIGHT_SIDEBAR_DEFAULT_WIDTH)); @@ -1021,6 +1234,10 @@ export function MockLayout({ workspaceId, selectedTaskId, selectedSessionId }: M }, [activeTask, tasks, navigate, workspaceId]); const openDiffs = activeTask ? sanitizeOpenDiffs(activeTask, openDiffsByTask[activeTask.id]) : []; + const terminalTabOpen = activeTask ? (terminalTabOpenByTask[activeTask.id] ?? false) : false; + const terminalProcessTabs = activeTask ? (terminalProcessTabsByTask[activeTask.id] ?? []) : []; + const terminalActiveTabId = activeTask ? (terminalActiveTabIdByTask[activeTask.id] ?? null) : null; + const terminalCustomNames = activeTask ? (terminalCustomNamesByTask[activeTask.id] ?? {}) : {}; const lastAgentTabId = activeTask ? sanitizeLastAgentTabId(activeTask, lastAgentTabIdByTask[activeTask.id]) : null; const activeTabId = activeTask ? sanitizeActiveTabId(activeTask, activeTabIdByTask[activeTask.id], openDiffs, lastAgentTabId) : null; @@ -1115,29 +1332,32 @@ export function MockLayout({ workspaceId, selectedTaskId, selectedSessionId }: M })(); }, [activeTask, selectedSessionId, syncRouteSession, taskWorkbenchClient]); - const createTask = useCallback(() => { - void (async () => { - const repoId = selectedNewTaskRepoId; - if (!repoId) { - throw new Error("Cannot create a task without an available repo"); - } + const createTask = useCallback( + (overrideRepoId?: string) => { + void (async () => { + const repoId = overrideRepoId || selectedNewTaskRepoId; + if (!repoId) { + throw new Error("Cannot create a task without an available repo"); + } - const { taskId, tabId } = await taskWorkbenchClient.createTask({ - repoId, - task: "New task", - model: "gpt-4o", - title: "New task", - }); - await navigate({ - to: "/workspaces/$workspaceId/tasks/$taskId", - params: { - workspaceId, - taskId, - }, - search: { sessionId: tabId ?? undefined }, - }); - })(); - }, [navigate, selectedNewTaskRepoId, workspaceId]); + const { taskId, tabId } = await taskWorkbenchClient.createTask({ + repoId, + task: "New task", + model: "gpt-4o", + title: "New task", + }); + await navigate({ + to: "/workspaces/$workspaceId/tasks/$taskId", + params: { + workspaceId, + taskId, + }, + search: { sessionId: tabId ?? undefined }, + }); + })(); + }, + [navigate, selectedNewTaskRepoId, workspaceId], + ); const openDiffTab = useCallback( (path: string) => { @@ -1163,6 +1383,46 @@ export function MockLayout({ workspaceId, selectedTaskId, selectedSessionId }: M [activeTask], ); + const openTerminalTab = useCallback(() => { + if (!activeTask) return; + setTerminalTabOpenByTask((current) => ({ ...current, [activeTask.id]: true })); + setActiveTabIdByTask((current) => ({ ...current, [activeTask.id]: terminalTabId() })); + }, [activeTask]); + + const closeTerminalTab = useCallback(() => { + if (!activeTask) return; + setTerminalTabOpenByTask((current) => ({ ...current, [activeTask.id]: false })); + const currentActive = activeTabIdByTask[activeTask.id]; + if (currentActive && isTerminalTab(currentActive)) { + const fallback = lastAgentTabIdByTask[activeTask.id] ?? activeTask.tabs[0]?.id ?? null; + setActiveTabIdByTask((current) => ({ ...current, [activeTask.id]: fallback })); + } + }, [activeTask, activeTabIdByTask, lastAgentTabIdByTask]); + + const setTerminalProcessTabs = useCallback( + (tabs: ProcessTab[]) => { + if (!activeTask) return; + setTerminalProcessTabsByTask((current) => ({ ...current, [activeTask.id]: tabs })); + }, + [activeTask], + ); + + const setTerminalActiveTabId = useCallback( + (id: string | null) => { + if (!activeTask) return; + setTerminalActiveTabIdByTask((current) => ({ ...current, [activeTask.id]: id })); + }, + [activeTask], + ); + + const setTerminalCustomNames = useCallback( + (names: Record) => { + if (!activeTask) return; + setTerminalCustomNamesByTask((current) => ({ ...current, [activeTask.id]: names })); + }, + [activeTask], + ); + const selectTask = useCallback( (id: string) => { const task = tasks.find((candidate) => candidate.id === id) ?? null; @@ -1265,6 +1525,8 @@ export function MockLayout({ workspaceId, selectedTaskId, selectedSessionId }: M [activeTask, lastAgentTabIdByTask], ); + const isMobile = useIsMobile(); + const isDesktop = !!import.meta.env.VITE_DESKTOP; const onDragMouseDown = useCallback((event: ReactPointerEvent) => { if (event.button !== 0) return; @@ -1274,6 +1536,58 @@ export function MockLayout({ workspaceId, selectedTaskId, selectedSessionId }: M ipc.invoke("plugin:window|start_dragging").catch(() => {}); } }, []); + + // Mobile layout: single-panel stack navigation with bottom tab bar + if (isMobile && activeTask) { + return ( + setActiveTabIdByTask((current) => ({ ...current, [activeTask.id]: tabId }))} + onSetLastAgentTabId={(tabId) => setLastAgentTabIdByTask((current) => ({ ...current, [activeTask.id]: tabId }))} + onSetOpenDiffs={(paths) => setOpenDiffsByTask((current) => ({ ...current, [activeTask.id]: paths }))} + onNavigateToUsage={navigateToUsage} + mobile + /> + } + onOpenDiff={openDiffTab} + onArchive={archiveTask} + onRevertFile={revertFile} + onPublishPr={publishPr} + terminalProcessTabs={terminalProcessTabs} + onTerminalProcessTabsChange={setTerminalProcessTabs} + terminalActiveTabId={terminalActiveTabId} + onTerminalActiveTabIdChange={setTerminalActiveTabId} + terminalCustomNames={terminalCustomNames} + onTerminalCustomNamesChange={setTerminalCustomNames} + onOpenSettings={navigateToSettings} + /> + ); + } + const dragRegion = isDesktop ? (
{leftSidebarOpen ? null : ( -
setLeftSidebarOpen(true)}> - -
+ +
setLeftSidebarOpen(true)}> + +
+
)}
{rightSidebarOpen ? null : ( -
setRightSidebarOpen(true)}> - -
+ +
setRightSidebarOpen(true)}> + +
+
)}
) : null} @@ -1409,7 +1727,7 @@ export function MockLayout({ workspaceId, selectedTaskId, selectedSessionId }: M

diff --git a/foundry/packages/frontend/src/components/mock-layout/history-minimap.tsx b/foundry/packages/frontend/src/components/mock-layout/history-minimap.tsx index 3c48a274..29ee29ac 100644 --- a/foundry/packages/frontend/src/components/mock-layout/history-minimap.tsx +++ b/foundry/packages/frontend/src/components/mock-layout/history-minimap.tsx @@ -4,6 +4,7 @@ import { LabelXSmall } from "baseui/typography"; import { History } from "lucide-react"; import { useFoundryTokens } from "../../app/theme"; +import { Tooltip } from "./ui"; import { formatMessageTimestamp, type HistoryEvent } from "./view-model"; export const HistoryMinimap = memo(function HistoryMinimap({ events, onSelect }: { events: HistoryEvent[]; onSelect: (event: HistoryEvent) => void }) { @@ -41,29 +42,31 @@ export const HistoryMinimap = memo(function HistoryMinimap({ events, onSelect }: gap: "6px", })} > -
setOpen((prev) => !prev)} - onKeyDown={(e) => { - if (e.key === "Enter" || e.key === " ") setOpen((prev) => !prev); - }} - className={css({ - width: "26px", - height: "26px", - borderRadius: "6px", - display: "flex", - alignItems: "center", - justifyContent: "center", - cursor: "pointer", - color: open ? t.textSecondary : t.textTertiary, - backgroundColor: open ? t.interactiveHover : "transparent", - transition: "background 200ms ease, color 200ms ease", - ":hover": { color: t.textSecondary, backgroundColor: t.interactiveHover }, - })} - > - -
+ +
setOpen((prev) => !prev)} + onKeyDown={(e) => { + if (e.key === "Enter" || e.key === " ") setOpen((prev) => !prev); + }} + className={css({ + width: "26px", + height: "26px", + borderRadius: "6px", + display: "flex", + alignItems: "center", + justifyContent: "center", + cursor: "pointer", + color: open ? t.textSecondary : t.textTertiary, + backgroundColor: open ? t.interactiveHover : "transparent", + transition: "background 200ms ease, color 200ms ease", + ":hover": { color: t.textSecondary, backgroundColor: t.interactiveHover }, + })} + > + +
+
{open ? (
>; copiedMessageId: string | null; onCopyMessage: (message: Message) => void; + userName?: string | null; + userAvatarUrl?: string | null; }) { const [css] = useStyletron(); const t = useFoundryTokens(); @@ -81,12 +85,52 @@ const TranscriptMessageBody = memo(function TranscriptMessageBody({ className={css({ display: "flex", alignItems: "center", - gap: "10px", + gap: "6px", justifyContent: isUser ? "flex-end" : "flex-start", minHeight: "16px", paddingLeft: isUser ? undefined : "2px", })} > + {isUser && (userAvatarUrl || userName) ? ( + <> + {userAvatarUrl ? ( + + ) : userName ? ( +
+ {userName.charAt(0).toUpperCase()} +
+ ) : null} + {userName ? ( + + {userName} + + ) : null} + + ) : null} {displayFooter ? ( {displayFooter} @@ -130,6 +174,8 @@ export const MessageList = memo(function MessageList({ copiedMessageId, onCopyMessage, thinkingTimerLabel, + userName, + userAvatarUrl, }: { tab: AgentTab | null | undefined; scrollRef: Ref; @@ -139,6 +185,8 @@ export const MessageList = memo(function MessageList({ copiedMessageId: string | null; onCopyMessage: (message: Message) => void; thinkingTimerLabel: string | null; + userName?: string | null; + userAvatarUrl?: string | null; }) { const [css] = useStyletron(); const t = useFoundryTokens(); @@ -238,7 +286,16 @@ export const MessageList = memo(function MessageList({ return null; } - return ; + return ( + + ); }} isThinking={Boolean(tab && tab.status === "running" && transcriptEntries.length > 0)} renderThinkingState={() => ( diff --git a/foundry/packages/frontend/src/components/mock-layout/mobile-layout.tsx b/foundry/packages/frontend/src/components/mock-layout/mobile-layout.tsx new file mode 100644 index 00000000..0d071d73 --- /dev/null +++ b/foundry/packages/frontend/src/components/mock-layout/mobile-layout.tsx @@ -0,0 +1,338 @@ +import { memo, useCallback, useRef, useState } from "react"; +import { useStyletron } from "baseui"; +import { FileText, List, MessageSquare, Settings, Terminal as TerminalIcon } from "lucide-react"; +import { useFoundryTokens } from "../../app/theme"; + +import type { WorkbenchProjectSection, WorkbenchRepo } from "@sandbox-agent/foundry-shared"; +import { RightSidebar } from "./right-sidebar"; +import { Sidebar } from "./sidebar"; +import { TerminalPane, type ProcessTab } from "./terminal-pane"; +import type { Task } from "./view-model"; + +type MobileView = "tasks" | "chat" | "changes" | "terminal"; +const VIEW_ORDER: MobileView[] = ["tasks", "chat", "changes", "terminal"]; + +const SWIPE_THRESHOLD = 50; +const SWIPE_MAX_VERTICAL = 80; + +interface MobileLayoutProps { + workspaceId: string; + task: Task; + tasks: Task[]; + projects: WorkbenchProjectSection[]; + repos: WorkbenchRepo[]; + selectedNewTaskRepoId: string; + onSelectNewTaskRepo: (id: string) => void; + onSelectTask: (id: string) => void; + onCreateTask: (repoId?: string) => void; + onMarkUnread: (id: string) => void; + onRenameTask: (id: string) => void; + onRenameBranch: (id: string) => void; + onReorderProjects: (from: number, to: number) => void; + taskOrderByProject: Record; + onReorderTasks: (projectId: string, from: number, to: number) => void; + // Transcript panel (rendered by parent) + transcriptPanel: React.ReactNode; + // Diff/file actions + onOpenDiff: (path: string) => void; + onArchive: () => void; + onRevertFile: (path: string) => void; + onPublishPr: () => void; + // Tab state + activeTabId: string | null; + // Terminal state + terminalProcessTabs: ProcessTab[]; + onTerminalProcessTabsChange: (tabs: ProcessTab[]) => void; + terminalActiveTabId: string | null; + onTerminalActiveTabIdChange: (id: string | null) => void; + terminalCustomNames: Record; + onTerminalCustomNamesChange: (names: Record) => void; + onOpenSettings?: () => void; +} + +export const MobileLayout = memo(function MobileLayout(props: MobileLayoutProps) { + const [css] = useStyletron(); + const t = useFoundryTokens(); + const [activeView, setActiveView] = useState("tasks"); + + // Swipe gesture tracking + const touchStartRef = useRef<{ x: number; y: number } | null>(null); + + const handleTouchStart = useCallback((e: React.TouchEvent) => { + const touch = e.touches[0]; + if (touch) { + touchStartRef.current = { x: touch.clientX, y: touch.clientY }; + } + }, []); + + const handleTouchEnd = useCallback( + (e: React.TouchEvent) => { + const start = touchStartRef.current; + const touch = e.changedTouches[0]; + if (!start || !touch) return; + touchStartRef.current = null; + + const dx = touch.clientX - start.x; + const dy = touch.clientY - start.y; + + if (Math.abs(dx) < SWIPE_THRESHOLD || Math.abs(dy) > SWIPE_MAX_VERTICAL) return; + + const currentIndex = VIEW_ORDER.indexOf(activeView); + if (dx > 0 && currentIndex > 0) { + // Swipe right -> go back + setActiveView(VIEW_ORDER[currentIndex - 1]!); + } else if (dx < 0 && currentIndex < VIEW_ORDER.length - 1) { + // Swipe left -> go forward + setActiveView(VIEW_ORDER[currentIndex + 1]!); + } + }, + [activeView], + ); + + const handleSelectTask = useCallback( + (id: string) => { + props.onSelectTask(id); + setActiveView("chat"); + }, + [props.onSelectTask], + ); + + return ( +
+ {/* Header - show task info when not on tasks view */} + {activeView !== "tasks" && } + + {/* Content area */} +
+ {activeView === "tasks" ? ( +
+ +
+ ) : activeView === "chat" ? ( +
{props.transcriptPanel}
+ ) : activeView === "changes" ? ( +
+ +
+ ) : ( +
+ +
+ )} +
+ + {/* Bottom tab bar - always fixed at bottom */} + +
+ ); +}); + +function MobileHeader({ task }: { task: Task }) { + const [css] = useStyletron(); + const t = useFoundryTokens(); + + return ( +
+
+
+ {task.title} +
+
+ {task.repoName} +
+
+
+ ); +} + +function MobileTabBar({ + activeView, + onViewChange, + changesCount, + onOpenSettings, +}: { + activeView: MobileView; + onViewChange: (view: MobileView) => void; + changesCount: number; + onOpenSettings?: () => void; +}) { + const [css] = useStyletron(); + const t = useFoundryTokens(); + + const tabs: { id: MobileView; icon: React.ReactNode; badge?: number }[] = [ + { id: "tasks", icon: }, + { id: "chat", icon: }, + { id: "changes", icon: , badge: changesCount > 0 ? changesCount : undefined }, + { id: "terminal", icon: }, + ]; + + const iconButtonClass = css({ + border: "none", + background: "transparent", + display: "flex", + alignItems: "center", + justifyContent: "center", + width: "42px", + height: "42px", + borderRadius: "12px", + cursor: "pointer", + position: "relative", + transition: "background 150ms ease, color 150ms ease", + }); + + return ( +
+ {/* Pill container */} +
+ {tabs.map((tab) => { + const isActive = activeView === tab.id; + return ( + + ); + })} + {onOpenSettings && ( + + )} +
+
+ ); +} diff --git a/foundry/packages/frontend/src/components/mock-layout/right-sidebar.tsx b/foundry/packages/frontend/src/components/mock-layout/right-sidebar.tsx index d3c67f37..e2e7ebea 100644 --- a/foundry/packages/frontend/src/components/mock-layout/right-sidebar.tsx +++ b/foundry/packages/frontend/src/components/mock-layout/right-sidebar.tsx @@ -4,7 +4,7 @@ import { LabelSmall } from "baseui/typography"; import { Archive, ArrowUpFromLine, ChevronRight, FileCode, FilePlus, FileX, FolderOpen, GitPullRequest, PanelRight } from "lucide-react"; import { useFoundryTokens } from "../../app/theme"; -import { type ContextMenuItem, ContextMenuOverlay, PanelHeaderBar, SPanel, ScrollBody, useContextMenu } from "./ui"; +import { type ContextMenuItem, ContextMenuOverlay, PanelHeaderBar, SPanel, ScrollBody, Tooltip, useContextMenu } from "./ui"; import { type FileTreeNode, type Task, diffTabId } from "./view-model"; const FileTree = memo(function FileTree({ @@ -96,6 +96,7 @@ export const RightSidebar = memo(function RightSidebar({ onRevertFile, onPublishPr, onToggleSidebar, + mobile, }: { task: Task; activeTabId: string | null; @@ -104,6 +105,7 @@ export const RightSidebar = memo(function RightSidebar({ onRevertFile: (path: string) => void; onPublishPr: () => void; onToggleSidebar?: () => void; + mobile?: boolean; }) { const [css] = useStyletron(); const t = useFoundryTokens(); @@ -151,128 +153,138 @@ export const RightSidebar = memo(function RightSidebar({ return ( - -
- {!isTerminal ? ( -
- - - -
- ) : null} - {onToggleSidebar ? ( -
{ - if (event.key === "Enter" || event.key === " ") onToggleSidebar(); - }} - className={css({ - width: "26px", - height: "26px", - borderRadius: "6px", - color: t.textTertiary, - cursor: "pointer", - display: "flex", - alignItems: "center", - justifyContent: "center", - flexShrink: 0, - ":hover": { color: t.textSecondary, backgroundColor: t.interactiveHover }, - })} - > - -
- ) : null} -
-
+ onPublishPr(); + }} + className={css({ + appearance: "none", + WebkitAppearance: "none", + background: "none", + border: "none", + margin: "0", + boxSizing: "border-box", + display: "inline-flex", + alignItems: "center", + gap: "5px", + padding: compact ? "4px 6px" : "4px 10px", + borderRadius: "6px", + fontSize: "11px", + fontWeight: 500, + lineHeight: 1, + whiteSpace: "nowrap", + flexShrink: 0, + color: t.textSecondary, + cursor: "pointer", + transition: "all 200ms ease", + ":hover": { backgroundColor: t.interactiveHover, color: t.textPrimary }, + })} + > + + {!compact && {pullRequestUrl ? "Open PR" : "Publish PR"}} + + + + + + + + +
+ ) : null} + {onToggleSidebar ? ( + +
{ + if (event.key === "Enter" || event.key === " ") onToggleSidebar(); + }} + className={css({ + width: "26px", + height: "26px", + borderRadius: "6px", + color: t.textTertiary, + cursor: "pointer", + display: "flex", + alignItems: "center", + justifyContent: "center", + flexShrink: 0, + ":hover": { color: t.textSecondary, backgroundColor: t.interactiveHover }, + })} + > + +
+
+ ) : null} + + + )}
@@ -296,7 +312,7 @@ export const RightSidebar = memo(function RightSidebar({ height: "41px", minHeight: "41px", flexShrink: 0, - borderTopRightRadius: "12px", + ...(mobile ? {} : { borderTopRightRadius: "12px" }), })} >
+ ); +}); + +const PresenceAvatars = memo(function PresenceAvatars({ presence }: { presence: WorkbenchPresence[] }) { + const [css] = useStyletron(); + const t = useFoundryTokens(); + const maxShow = 3; + const visible = presence.slice(0, maxShow); + const overflow = presence.length - maxShow; + const now = Date.now(); + + return ( +
+
+ {visible.map((member, idx) => { + const isAway = now - member.lastSeenAtMs > AWAY_THRESHOLD_MS; + return ; + })} + {overflow > 0 && ( +
div:last-child": { + opacity: 1, + transform: "translateX(-50%) translateY(0)", + pointerEvents: "auto", + }, + })} + > +
+ +{overflow} +
+
+ {presence + .slice(maxShow) + .map((m) => m.name) + .join(", ")} +
+
+ )} +
+ {presence.length <= 2 && ( + + {presence.map((m) => m.name).join(", ")} + + )} +
+ ); +}); + function projectInitial(label: string): string { const parts = label.split("/"); const name = parts[parts.length - 1] ?? label; @@ -55,13 +207,15 @@ export const Sidebar = memo(function Sidebar({ taskOrderByProject, onReorderTasks, onToggleSidebar, + hideSettings, + panelStyle, }: { projects: ProjectSection[]; newTaskRepos: Array<{ id: string; label: string }>; selectedNewTaskRepoId: string; activeId: string; onSelect: (id: string) => void; - onCreate: () => void; + onCreate: (repoId?: string) => void; onSelectNewTaskRepo: (repoId: string) => void; onMarkUnread: (id: string) => void; onRenameTask: (id: string) => void; @@ -70,6 +224,8 @@ export const Sidebar = memo(function Sidebar({ taskOrderByProject: Record; onReorderTasks: (projectId: string, fromIndex: number, toIndex: number) => void; onToggleSidebar?: () => void; + hideSettings?: boolean; + panelStyle?: Record; }) { const [css] = useStyletron(); const t = useFoundryTokens(); @@ -90,6 +246,7 @@ export const Sidebar = memo(function Sidebar({ // Attach global mousemove/mouseup when dragging useEffect(() => { if (!drag) return; + document.body.style.cursor = "grabbing"; const onMove = (e: MouseEvent) => { // Detect which element is under the cursor using data attributes const el = document.elementFromPoint(e.clientX, e.clientY); @@ -132,6 +289,7 @@ export const Sidebar = memo(function Sidebar({ document.addEventListener("mousemove", onMove); document.addEventListener("mouseup", onUp); return () => { + document.body.style.cursor = ""; document.removeEventListener("mousemove", onMove); document.removeEventListener("mouseup", onUp); }; @@ -152,12 +310,12 @@ export const Sidebar = memo(function Sidebar({ }, [createMenuOpen]); return ( - + @@ -175,6 +333,43 @@ export const Sidebar = memo(function Sidebar({ })} > {onToggleSidebar ? ( + +
{ + if (event.key === "Enter" || event.key === " ") onToggleSidebar(); + }} + className={css({ + width: "26px", + height: "26px", + borderRadius: "6px", + color: t.textTertiary, + cursor: "pointer", + display: "flex", + alignItems: "center", + justifyContent: "center", + flexShrink: 0, + ":hover": { color: t.textSecondary, backgroundColor: t.interactiveHover }, + })} + > + +
+
+ ) : null} + + ) : null} + + + + Tasks + + {!import.meta.env.VITE_DESKTOP && onToggleSidebar ? ( +
- ) : null} - - ) : null} - - - - Tasks - - {!import.meta.env.VITE_DESKTOP && onToggleSidebar ? ( -
{ - if (event.key === "Enter" || event.key === " ") onToggleSidebar(); - }} - className={css({ - width: "26px", - height: "26px", - borderRadius: "6px", - color: t.textTertiary, - cursor: "pointer", - display: "flex", - alignItems: "center", - justifyContent: "center", - flexShrink: 0, - ":hover": { color: t.textSecondary, backgroundColor: t.interactiveHover }, - })} - > - -
+
) : null}
-
{ - if (newTaskRepos.length === 0) return; - if (newTaskRepos.length === 1) { - onSelectNewTaskRepo(newTaskRepos[0]!.id); - onCreate(); - } else { - setCreateMenuOpen((prev) => !prev); - } - }} - onKeyDown={(event) => { - if (newTaskRepos.length === 0) return; - if (event.key === "Enter" || event.key === " ") { + +
{ + if (newTaskRepos.length === 0) return; if (newTaskRepos.length === 1) { onSelectNewTaskRepo(newTaskRepos[0]!.id); - onCreate(); + onCreate(newTaskRepos[0]!.id); } else { setCreateMenuOpen((prev) => !prev); } - } - }} - className={css({ - width: "26px", - height: "26px", - borderRadius: "8px", - backgroundColor: newTaskRepos.length > 0 ? t.borderMedium : t.interactiveHover, - color: t.textPrimary, - cursor: newTaskRepos.length > 0 ? "pointer" : "not-allowed", - display: "flex", - alignItems: "center", - justifyContent: "center", - transition: "background 200ms ease", - flexShrink: 0, - opacity: newTaskRepos.length > 0 ? 1 : 0.6, - ":hover": newTaskRepos.length > 0 ? { backgroundColor: "rgba(255, 255, 255, 0.20)" } : undefined, - })} - > - -
+ }} + onKeyDown={(event) => { + if (newTaskRepos.length === 0) return; + if (event.key === "Enter" || event.key === " ") { + if (newTaskRepos.length === 1) { + onSelectNewTaskRepo(newTaskRepos[0]!.id); + onCreate(newTaskRepos[0]!.id); + } else { + setCreateMenuOpen((prev) => !prev); + } + } + }} + className={css({ + width: "26px", + height: "26px", + borderRadius: "8px", + backgroundColor: newTaskRepos.length > 0 ? t.borderMedium : t.interactiveHover, + color: t.textPrimary, + cursor: newTaskRepos.length > 0 ? "pointer" : "not-allowed", + display: "flex", + alignItems: "center", + justifyContent: "center", + transition: "background 200ms ease", + flexShrink: 0, + opacity: newTaskRepos.length > 0 ? 1 : 0.6, + ":hover": newTaskRepos.length > 0 ? { backgroundColor: "rgba(255, 255, 255, 0.20)" } : undefined, + })} + > + +
+ {createMenuOpen && newTaskRepos.length > 1 ? (
{ onSelectNewTaskRepo(repo.id); setCreateMenuOpen(false); - onCreate(); + onCreate(repo.id); }} className={css({ display: "flex", @@ -442,9 +606,31 @@ export const Sidebar = memo(function Sidebar({ > {projectInitial(project.label)} - +
e.stopPropagation()} className={css({ @@ -543,7 +729,7 @@ export const Sidebar = memo(function Sidebar({ position: "relative", backgroundColor: isActive ? t.interactiveHover : "transparent", opacity: isTaskBeingDragged ? 0.4 : 1, - cursor: "pointer", + cursor: drag?.type === "task" ? "grabbing" : "pointer", transition: "all 150ms ease", "::before": { content: '""', @@ -607,6 +793,7 @@ export const Sidebar = memo(function Sidebar({ {formatRelativeAge(task.updatedAtMs)}
+ {task.presence.length > 0 && } ); })} @@ -658,7 +845,7 @@ export const Sidebar = memo(function Sidebar({ /> - + {!hideSettings && } {contextMenu.menu ? : null}
); @@ -945,34 +1132,36 @@ function SidebarFooter() { ) : null}
- + + +
); diff --git a/foundry/packages/frontend/src/components/mock-layout/tab-strip.tsx b/foundry/packages/frontend/src/components/mock-layout/tab-strip.tsx index e96989ea..7dd4e738 100644 --- a/foundry/packages/frontend/src/components/mock-layout/tab-strip.tsx +++ b/foundry/packages/frontend/src/components/mock-layout/tab-strip.tsx @@ -1,11 +1,11 @@ import { memo } from "react"; import { useStyletron } from "baseui"; import { LabelXSmall } from "baseui/typography"; -import { FileCode, Plus, X } from "lucide-react"; +import { FileCode, Plus, SquareTerminal, X } from "lucide-react"; import { useFoundryTokens } from "../../app/theme"; -import { ContextMenuOverlay, TabAvatar, useContextMenu } from "./ui"; -import { diffTabId, fileName, type Task } from "./view-model"; +import { ContextMenuOverlay, TabAvatar, Tooltip, useContextMenu } from "./ui"; +import { diffTabId, fileName, terminalTabId, type Task } from "./view-model"; export const TabStrip = memo(function TabStrip({ task, @@ -22,6 +22,8 @@ export const TabStrip = memo(function TabStrip({ onCloseTab, onCloseDiffTab, onAddTab, + terminalTabOpen, + onCloseTerminalTab, sidebarCollapsed, }: { task: Task; @@ -38,6 +40,8 @@ export const TabStrip = memo(function TabStrip({ onCloseTab: (tabId: string) => void; onCloseDiffTab: (path: string) => void; onAddTab: () => void; + terminalTabOpen?: boolean; + onCloseTerminalTab?: () => void; sidebarCollapsed?: boolean; }) { const [css] = useStyletron(); @@ -216,21 +220,71 @@ export const TabStrip = memo(function TabStrip({ ); })} -
- -
+ {terminalTabOpen + ? (() => { + const tabId = terminalTabId(); + const isActive = tabId === activeTabId; + return ( +
onSwitchTab(tabId)} + onMouseDown={(event) => { + if (event.button === 1) { + event.preventDefault(); + onCloseTerminalTab?.(); + } + }} + data-tab + className={css({ + display: "flex", + alignItems: "center", + gap: "6px", + padding: "4px 12px", + marginTop: "6px", + marginBottom: "6px", + borderRadius: "8px", + backgroundColor: isActive ? t.interactiveHover : "transparent", + cursor: "pointer", + transition: "color 200ms ease, background-color 200ms ease", + flexShrink: 0, + ":hover": { color: t.textPrimary, backgroundColor: isActive ? t.interactiveHover : t.interactiveSubtle }, + })} + > + + + Terminal + + { + event.stopPropagation(); + onCloseTerminalTab?.(); + }} + /> +
+ ); + })() + : null} + +
+ +
+
{contextMenu.menu ? : null} diff --git a/foundry/packages/frontend/src/components/mock-layout/terminal-pane.tsx b/foundry/packages/frontend/src/components/mock-layout/terminal-pane.tsx index d0e011d2..6098c999 100644 --- a/foundry/packages/frontend/src/components/mock-layout/terminal-pane.tsx +++ b/foundry/packages/frontend/src/components/mock-layout/terminal-pane.tsx @@ -3,7 +3,7 @@ import { ProcessTerminal } from "@sandbox-agent/react"; import { useQuery } from "@tanstack/react-query"; import { useStyletron } from "baseui"; import { useFoundryTokens } from "../../app/theme"; -import { ChevronDown, ChevronUp, Plus, SquareTerminal, Trash2 } from "lucide-react"; +import { ArrowUpLeft, ChevronDown, ChevronUp, Plus, SquareTerminal, Trash2 } from "lucide-react"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { SandboxAgent } from "sandbox-agent"; import { backendClient } from "../../lib/backend"; @@ -12,11 +12,21 @@ interface TerminalPaneProps { workspaceId: string; taskId: string | null; isExpanded?: boolean; + hideHeader?: boolean; onExpand?: () => void; onCollapse?: () => void; onStartResize?: (e: React.PointerEvent) => void; + onOpenTerminalTab?: () => void; + processTabs?: ProcessTab[]; + onProcessTabsChange?: (tabs: ProcessTab[]) => void; + activeProcessTabId?: string | null; + onActiveProcessTabIdChange?: (id: string | null) => void; + customTabNames?: Record; + onCustomTabNamesChange?: (names: Record) => void; } +export type { ProcessTab }; + interface ProcessTab { id: string; processId: string; @@ -94,15 +104,66 @@ function HeaderIconButton({ ); } -export function TerminalPane({ workspaceId, taskId, isExpanded, onExpand, onCollapse, onStartResize }: TerminalPaneProps) { +export function TerminalPane({ + workspaceId, + taskId, + isExpanded, + hideHeader, + onExpand, + onCollapse, + onStartResize, + onOpenTerminalTab, + processTabs: controlledProcessTabs, + onProcessTabsChange, + activeProcessTabId: controlledActiveTabId, + onActiveProcessTabIdChange, + customTabNames: controlledCustomTabNames, + onCustomTabNamesChange, +}: TerminalPaneProps) { const [css] = useStyletron(); const t = useFoundryTokens(); - const [activeTabId, setActiveTabId] = useState(null); - const [processTabs, setProcessTabs] = useState([]); + const [internalActiveTabId, setInternalActiveTabId] = useState(null); + const [internalProcessTabs, setInternalProcessTabs] = useState([]); const [creatingProcess, setCreatingProcess] = useState(false); const [hoveredTabId, setHoveredTabId] = useState(null); const [terminalClient, setTerminalClient] = useState(null); - const [customTabNames, setCustomTabNames] = useState>({}); + const [internalCustomTabNames, setInternalCustomTabNames] = useState>({}); + + const processTabs = controlledProcessTabs ?? internalProcessTabs; + const setProcessTabs = useCallback( + (update: ProcessTab[] | ((prev: ProcessTab[]) => ProcessTab[])) => { + if (onProcessTabsChange) { + const next = typeof update === "function" ? update(controlledProcessTabs ?? []) : update; + onProcessTabsChange(next); + } else { + setInternalProcessTabs(update); + } + }, + [onProcessTabsChange, controlledProcessTabs], + ); + const activeTabId = controlledActiveTabId !== undefined ? controlledActiveTabId : internalActiveTabId; + const setActiveTabId = useCallback( + (id: string | null) => { + if (onActiveProcessTabIdChange) { + onActiveProcessTabIdChange(id); + } else { + setInternalActiveTabId(id); + } + }, + [onActiveProcessTabIdChange], + ); + const customTabNames = controlledCustomTabNames ?? internalCustomTabNames; + const setCustomTabNames = useCallback( + (update: Record | ((prev: Record) => Record)) => { + if (onCustomTabNamesChange) { + const next = typeof update === "function" ? update(controlledCustomTabNames ?? {}) : update; + onCustomTabNamesChange(next); + } else { + setInternalCustomTabNames(update); + } + }, + [onCustomTabNamesChange, controlledCustomTabNames], + ); const [editingTabId, setEditingTabId] = useState(null); const editInputRef = useRef(null); @@ -135,7 +196,7 @@ export function TerminalPane({ workspaceId, taskId, isExpanded, onExpand, onColl setProcessTabs((prev) => { const next = [...prev]; const [moved] = next.splice(d.fromIdx, 1); - next.splice(d.overIdx!, 0, moved); + if (moved) next.splice(d.overIdx!, 0, moved); return next; }); } @@ -306,43 +367,48 @@ export function TerminalPane({ workspaceId, taskId, isExpanded, onExpand, onColl }; }, [terminalClient]); + // Only reset on taskId change when using internal (uncontrolled) state. + // When controlled, the parent (MockLayout) owns per-task state via keyed records. useEffect(() => { - setActiveTabId(null); - setProcessTabs([]); - }, [taskId]); + if (!controlledProcessTabs) { + setActiveTabId(null); + setProcessTabs([]); + } + }, [taskId]); // eslint-disable-line react-hooks/exhaustive-deps const processes = processesQuery.data?.processes ?? []; - const openTerminalTab = useCallback((process: SandboxProcessRecord) => { - setProcessTabs((current) => { - const existing = current.find((tab) => tab.processId === process.id); - if (existing) { - setActiveTabId(existing.id); - return current; - } - - const nextTab: ProcessTab = { - id: `terminal:${process.id}`, - processId: process.id, - title: formatProcessTabTitle(process, current.length + 1), - }; - setActiveTabId(nextTab.id); - return [...current, nextTab]; - }); - }, []); - - const closeTerminalTab = useCallback((tabId: string) => { - setProcessTabs((current) => { - const next = current.filter((tab) => tab.id !== tabId); - setActiveTabId((currentActive) => { - if (currentActive === tabId) { - return next.length > 0 ? next[next.length - 1]!.id : null; + const openTerminalTab = useCallback( + (process: SandboxProcessRecord) => { + setProcessTabs((current) => { + const existing = current.find((tab) => tab.processId === process.id); + if (existing) { + setActiveTabId(existing.id); + return current; } - return currentActive; + + const nextTab: ProcessTab = { + id: `terminal:${process.id}`, + processId: process.id, + title: formatProcessTabTitle(process, current.length + 1), + }; + setActiveTabId(nextTab.id); + return [...current, nextTab]; }); - return next; - }); - }, []); + }, + [setProcessTabs, setActiveTabId], + ); + + const closeTerminalTab = useCallback( + (tabId: string) => { + const next = processTabs.filter((tab) => tab.id !== tabId); + setProcessTabs(next); + if (activeTabId === tabId) { + setActiveTabId(next.length > 0 ? next[next.length - 1]!.id : null); + } + }, + [processTabs, activeTabId, setProcessTabs, setActiveTabId], + ); const spawnTerminal = useCallback(async () => { if (!activeSandbox?.sandboxId) { @@ -527,25 +593,27 @@ export function TerminalPane({ workspaceId, taskId, isExpanded, onExpand, onColl overflow: "hidden", })} > - {/* Resize handle */} -
- {/* Full-width header bar */} + {/* Resize handle — hidden when in tab view */} + {!hideHeader && ( +
+ )} + {/* Header bar — in tab view, only show action buttons (no title/expand/chevron) */}
- - Terminal + {!hideHeader && ( + <> + + Terminal + + )}
- - {isExpanded ? : } - + {!hideHeader && onOpenTerminalTab ? ( + + + + ) : null} + {!hideHeader && ( + + {isExpanded ? : } + + )}
- {/* Two-column body: terminal left, list right — hidden when no tabs */} - {processTabs.length > 0 && ( + {/* Two-column body: terminal left, list right — visible when expanded or when tabs exist */} + {(processTabs.length > 0 || hideHeader) && (
{/* Left: terminal content */}
{renderBody()}
diff --git a/foundry/packages/frontend/src/components/mock-layout/transcript-header.tsx b/foundry/packages/frontend/src/components/mock-layout/transcript-header.tsx index 00e8b0c0..17a40232 100644 --- a/foundry/packages/frontend/src/components/mock-layout/transcript-header.tsx +++ b/foundry/packages/frontend/src/components/mock-layout/transcript-header.tsx @@ -4,7 +4,7 @@ import { LabelSmall } from "baseui/typography"; import { Clock, PanelLeft, PanelRight } from "lucide-react"; import { useFoundryTokens } from "../../app/theme"; -import { PanelHeaderBar } from "./ui"; +import { PanelHeaderBar, Tooltip } from "./ui"; import { type AgentTab, type Task } from "./view-model"; export const TranscriptHeader = memo(function TranscriptHeader({ @@ -50,25 +50,27 @@ export const TranscriptHeader = memo(function TranscriptHeader({ return ( {sidebarCollapsed && onToggleSidebar ? ( -
- -
+ +
+ +
+
) : null} {editingField === "title" ? ( {task.minutesUsed ?? 0} min used
{rightSidebarCollapsed && onToggleRightSidebar ? ( -
- -
+ +
+ +
+
) : null} ); diff --git a/foundry/packages/frontend/src/components/mock-layout/ui.tsx b/foundry/packages/frontend/src/components/mock-layout/ui.tsx index 66722f10..824ee16d 100644 --- a/foundry/packages/frontend/src/components/mock-layout/ui.tsx +++ b/foundry/packages/frontend/src/components/mock-layout/ui.tsx @@ -1,4 +1,5 @@ -import { memo, useCallback, useEffect, useState, type MouseEvent } from "react"; +import { memo, useCallback, useEffect, useRef, useState, type MouseEvent, type ReactNode } from "react"; +import { createPortal } from "react-dom"; import { styled, useStyletron } from "baseui"; import { GitPullRequest, GitPullRequestDraft } from "lucide-react"; @@ -210,6 +211,115 @@ export const ScrollBody = styled("div", () => ({ flexDirection: "column" as const, })); +export const Tooltip = memo(function Tooltip({ + label, + children, + placement = "bottom", +}: { + label: string; + children: ReactNode; + placement?: "top" | "bottom" | "left" | "right"; +}) { + const [css] = useStyletron(); + const t = useFoundryTokens(); + const triggerRef = useRef(null); + const tooltipRef = useRef(null); + const [pos, setPos] = useState<{ top: number; left: number } | null>(null); + + const show = useCallback(() => { + const el = triggerRef.current; + if (!el) return; + const rect = el.getBoundingClientRect(); + let top: number; + let left: number; + if (placement === "bottom") { + top = rect.bottom + 6; + left = rect.left + rect.width / 2; + } else if (placement === "top") { + top = rect.top - 6; + left = rect.left + rect.width / 2; + } else if (placement === "left") { + top = rect.top + rect.height / 2; + left = rect.left - 6; + } else { + top = rect.top + rect.height / 2; + left = rect.right + 6; + } + setPos({ top, left }); + }, [placement]); + + const hide = useCallback(() => setPos(null), []); + + // Clamp tooltip position after it renders so it stays within the viewport + useEffect(() => { + if (!pos) return; + const tip = tooltipRef.current; + if (!tip) return; + const tipRect = tip.getBoundingClientRect(); + const pad = 8; + let adjustLeft = 0; + let adjustTop = 0; + if (tipRect.right > window.innerWidth - pad) { + adjustLeft = window.innerWidth - pad - tipRect.right; + } + if (tipRect.left < pad) { + adjustLeft = pad - tipRect.left; + } + if (tipRect.bottom > window.innerHeight - pad) { + adjustTop = window.innerHeight - pad - tipRect.bottom; + } + if (tipRect.top < pad) { + adjustTop = pad - tipRect.top; + } + if (adjustLeft !== 0 || adjustTop !== 0) { + setPos((prev) => prev && { top: prev.top + adjustTop, left: prev.left + adjustLeft }); + } + }, [pos]); + + const transform = + placement === "bottom" + ? "translateX(-50%)" + : placement === "top" + ? "translateX(-50%) translateY(-100%)" + : placement === "left" + ? "translateX(-100%) translateY(-50%)" + : "translateY(-50%)"; + + return ( +
+ {children} + {pos && + createPortal( +
+ {label} +
, + document.body, + )} +
+ ); +}); + export const HEADER_HEIGHT = "42px"; export const PROMPT_TEXTAREA_MIN_HEIGHT = 56; export const PROMPT_TEXTAREA_MAX_HEIGHT = 100; diff --git a/foundry/packages/frontend/src/components/mock-layout/view-model.ts b/foundry/packages/frontend/src/components/mock-layout/view-model.ts index d22ea5ce..edf8e2e6 100644 --- a/foundry/packages/frontend/src/components/mock-layout/view-model.ts +++ b/foundry/packages/frontend/src/components/mock-layout/view-model.ts @@ -102,6 +102,7 @@ export function providerAgent(provider: string): AgentKind { } const DIFF_PREFIX = "diff:"; +const TERMINAL_PREFIX = "terminal:"; export function isDiffTab(id: string): boolean { return id.startsWith(DIFF_PREFIX); @@ -115,6 +116,14 @@ export function diffTabId(path: string): string { return `${DIFF_PREFIX}${path}`; } +export function isTerminalTab(id: string): boolean { + return id.startsWith(TERMINAL_PREFIX); +} + +export function terminalTabId(): string { + return `${TERMINAL_PREFIX}main`; +} + export function fileName(path: string): string { return path.split("/").pop() ?? path; } diff --git a/foundry/packages/frontend/src/components/mock-onboarding.tsx b/foundry/packages/frontend/src/components/mock-onboarding.tsx index f583397d..07adea0d 100644 --- a/foundry/packages/frontend/src/components/mock-onboarding.tsx +++ b/foundry/packages/frontend/src/components/mock-onboarding.tsx @@ -1,9 +1,11 @@ -import { useCallback, useEffect, useMemo, useState } from "react"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { type FoundryBillingPlanId, type FoundryOrganization, type FoundryOrganizationMember, type FoundryUser } from "@sandbox-agent/foundry-shared"; import { useNavigate } from "@tanstack/react-router"; -import { ArrowLeft, Clock, CreditCard, FileText, Github, LogOut, Moon, Settings, Sun, Users } from "lucide-react"; +import { ArrowLeft, Clock, CreditCard, FileText, Github, LogOut, Moon, Settings, Sun, Users, Volume2 } from "lucide-react"; +import { NOTIFICATION_SOUND_OPTIONS, previewNotificationSound, useNotificationSound } from "../lib/notification-sound"; import { activeMockUser, eligibleOrganizations, useMockAppClient, useMockAppSnapshot } from "../lib/mock-app"; import { isMockFrontendClient } from "../lib/env"; +import { useIsMobile } from "../lib/platform"; import { useColorMode, useFoundryTokens } from "../app/theme"; import type { FoundryTokens } from "../styles/tokens"; import { appSurfaceStyle, primaryButtonStyle, secondaryButtonStyle, subtleButtonStyle, cardStyle, badgeStyle, inputStyle } from "../styles/shared-styles"; @@ -124,7 +126,7 @@ function statusBadge(t: FoundryTokens, organization: FoundryOrganization) { function githubBadge(t: FoundryTokens, organization: FoundryOrganization) { if (organization.github.installationStatus === "connected") { - return GitHub connected; + return GitHub connected; } if (organization.github.installationStatus === "reconnect_required") { return Reconnect required; @@ -164,9 +166,42 @@ function MemberRow({ member }: { member: FoundryOrganizationMember }) { alignItems: "center", }} > -
-
{member.name}
-
{member.email}
+
+ {member.avatarUrl ? ( + {member.name} + ) : ( +
+ {member.name.charAt(0).toUpperCase()} +
+ )} +
+
{member.name}
+
{member.email}
+
{member.role}
@@ -284,7 +319,7 @@ export function MockSignInPage() { {/* Footer */} = [ { section: "settings", icon: , label: "Settings" }, { section: "members", icon: , label: "Members" }, - { section: "billing", icon: , label: "Billing & Invoices" }, + { section: "billing", icon: , label: "Billing" }, { section: "docs", icon: , label: "Docs" }, ]; + const goBack = () => { + void (async () => { + await client.selectOrganization(organization.id); + await navigate({ to: workspacePath(organization) }); + })(); + }; + + const handleNavClick = (item: (typeof navSections)[0]) => { + if (item.section === "billing") { + void navigate({ to: billingPath(organization) }); + } else if (onSectionChange) { + onSectionChange(item.section); + } else { + void navigate({ to: settingsPath(organization) }); + } + }; + + if (isMobile) { + return ( +
+ {/* Mobile header */} +
+ +
+
{organization.settings.displayName}
+
{planCatalog[organization.billing.planId]?.label ?? "Free"} Plan
+
+
+ + {/* Mobile tab strip */} +
+ {navSections.map((item) => { + const isActive = activeSection === item.section; + return ( + + ); + })} +
+ + {/* Content */} +
+
{children}
+
+
+ ); + } + return ( -
+
{/* Left nav */} @@ -579,12 +728,7 @@ function SettingsLayout({ {/* Back to workspace */}
@@ -692,6 +828,8 @@ export function MockOrganizationSettingsPage({ organization }: { organization: F + + +
+

Account

+

Manage your personal account settings.

+
+ + +
+ {user?.avatarUrl ? ( + {user.name} + ) : ( +
+ {(user?.name ?? "U").charAt(0).toUpperCase()} +
+ )} +
+
{user?.name ?? "User"}
+
@{user?.githubLogin ?? ""}
+
+
+ + + +
+ +
+
+ + + + + + +
+ +
+
+ + + + Delete + + } + /> + +
+ ); + + if (isMobile) { + return ( +
+ {/* Mobile header */} +
+ +
Account
+
+ + {/* Content */} +
+
{accountContent}
+
+
+ ); + } + return ( -
+
{/* Left nav */} @@ -1131,9 +1430,32 @@ export function MockAccountSettingsPage() { Back to workspace -
- {user?.name ?? "User"} - {user?.email ?? ""} +
+ {user?.avatarUrl ? ( + {user.name} + ) : ( +
+ {(user?.name ?? "U").charAt(0).toUpperCase()} +
+ )} +
+ {user?.name ?? "User"} + {user?.email ?? ""} +
} label="General" active onClick={() => {}} /> @@ -1141,77 +1463,7 @@ export function MockAccountSettingsPage() { {/* Content */}
-
-
-
-

Account

-

Manage your personal account settings.

-
- - - - - -
- -
-
- - - - - - -
- -
-
- - - - Delete - - } - /> - -
-
+
{accountContent}
@@ -1238,7 +1490,7 @@ function AppearanceSection() { height: "20px", borderRadius: "10px", border: "1px solid rgba(128, 128, 128, 0.3)", - background: isDark ? t.borderDefault : t.accent, + background: isDark ? t.borderDefault : t.textPrimary, cursor: "pointer", padding: 0, transition: "background 0.2s", @@ -1260,7 +1512,7 @@ function AppearanceSection() { justifyContent: "center", }} > - {isDark ? : } + {isDark ? : }
} @@ -1268,3 +1520,130 @@ function AppearanceSection() { ); } + +function NotificationSoundSection() { + const t = useFoundryTokens(); + const [selected, setSelected] = useNotificationSound(); + const [open, setOpen] = useState(false); + const containerRef = useRef(null); + const selectedLabel = NOTIFICATION_SOUND_OPTIONS.find((o) => o.id === selected)?.label ?? "None"; + + useEffect(() => { + if (!open) return; + const handler = (e: MouseEvent) => { + if (containerRef.current && !containerRef.current.contains(e.target as Node)) { + setOpen(false); + } + }; + document.addEventListener("mousedown", handler); + return () => document.removeEventListener("mousedown", handler); + }, [open]); + + return ( + + + + {open && ( +
+ {NOTIFICATION_SOUND_OPTIONS.map((option) => { + const isActive = option.id === selected; + return ( + + ); + })} +
+ )} +
+ } + /> + + ); +} diff --git a/foundry/packages/frontend/src/lib/notification-sound.ts b/foundry/packages/frontend/src/lib/notification-sound.ts new file mode 100644 index 00000000..f78b9551 --- /dev/null +++ b/foundry/packages/frontend/src/lib/notification-sound.ts @@ -0,0 +1,77 @@ +import { useCallback, useEffect, useRef, useSyncExternalStore } from "react"; + +export type NotificationSoundId = "none" | "chime" | "ping"; + +const SOUNDS: Record, { label: string; src: string }> = { + chime: { label: "Chime", src: "/sounds/notification-1.mp3" }, + ping: { label: "Ping", src: "/sounds/notification-2.mp3" }, +}; + +const STORAGE_KEY = "foundry:notification-sound"; + +let currentValue: NotificationSoundId = (localStorage.getItem(STORAGE_KEY) as NotificationSoundId) || "none"; +const listeners = new Set<() => void>(); + +function notify() { + for (const listener of listeners) { + listener(); + } +} + +function getSnapshot(): NotificationSoundId { + return currentValue; +} + +function subscribe(listener: () => void): () => void { + listeners.add(listener); + return () => listeners.delete(listener); +} + +export function setNotificationSound(id: NotificationSoundId) { + currentValue = id; + localStorage.setItem(STORAGE_KEY, id); + notify(); +} + +export function useNotificationSound(): [NotificationSoundId, (id: NotificationSoundId) => void] { + const value = useSyncExternalStore(subscribe, getSnapshot); + return [value, setNotificationSound]; +} + +export function playNotificationSound() { + const id = getSnapshot(); + if (id === "none") return; + const sound = SOUNDS[id]; + if (!sound) return; + const audio = new Audio(sound.src); + audio.volume = 0.6; + audio.play().catch(() => {}); +} + +export function previewNotificationSound(id: NotificationSoundId) { + if (id === "none") return; + const sound = SOUNDS[id]; + if (!sound) return; + const audio = new Audio(sound.src); + audio.volume = 0.6; + audio.play().catch(() => {}); +} + +export function useAgentDoneNotification(status: "running" | "idle" | "error" | undefined) { + const prevStatus = useRef(status); + + useEffect(() => { + const prev = prevStatus.current; + prevStatus.current = status; + + if (prev === "running" && status === "idle") { + playNotificationSound(); + } + }, [status]); +} + +export const NOTIFICATION_SOUND_OPTIONS: { id: NotificationSoundId; label: string }[] = [ + { id: "none", label: "None" }, + { id: "chime", label: "Chime" }, + { id: "ping", label: "Ping" }, +]; diff --git a/foundry/packages/frontend/src/lib/platform.ts b/foundry/packages/frontend/src/lib/platform.ts new file mode 100644 index 00000000..1952133b --- /dev/null +++ b/foundry/packages/frontend/src/lib/platform.ts @@ -0,0 +1,55 @@ +import { useSyncExternalStore } from "react"; + +const MOBILE_BREAKPOINT = 768; + +/** True when built with VITE_MOBILE=1 (Tauri mobile build) */ +export const isNativeMobile = !!import.meta.env.VITE_MOBILE; + +/** True when built with VITE_DESKTOP=1 (Tauri desktop build) */ +export const isNativeDesktop = !!import.meta.env.VITE_DESKTOP; + +/** True when running inside any Tauri shell */ +export const isNativeApp = isNativeMobile || isNativeDesktop; + +function getIsMobileViewport(): boolean { + if (typeof window === "undefined") return false; + return window.innerWidth < MOBILE_BREAKPOINT; +} + +let currentIsMobile = isNativeMobile || getIsMobileViewport(); + +const listeners = new Set<() => void>(); + +if (typeof window !== "undefined") { + const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`); + mql.addEventListener("change", (e) => { + const next = isNativeMobile || e.matches; + if (next !== currentIsMobile) { + currentIsMobile = next; + for (const fn of listeners) fn(); + } + }); +} + +function subscribe(cb: () => void) { + listeners.add(cb); + return () => { + listeners.delete(cb); + }; +} + +function getSnapshot() { + return currentIsMobile; +} + +/** + * Returns true when the app should render in mobile layout. + * This is true when: + * - Built with VITE_MOBILE=1 (always mobile), OR + * - Viewport width is below 768px (responsive web) + * + * Re-renders when the viewport crosses the breakpoint. + */ +export function useIsMobile(): boolean { + return useSyncExternalStore(subscribe, getSnapshot, () => false); +} diff --git a/foundry/packages/frontend/src/styles.css b/foundry/packages/frontend/src/styles.css index 9967938f..a9567e6e 100644 --- a/foundry/packages/frontend/src/styles.css +++ b/foundry/packages/frontend/src/styles.css @@ -5,6 +5,10 @@ font-family: "IBM Plex Sans", "Segoe UI", sans-serif; background: var(--f-surface-primary, #000000); color: var(--f-text-primary, #ffffff); + --safe-area-top: env(safe-area-inset-top, 0px); + --safe-area-bottom: env(safe-area-inset-bottom, 0px); + --safe-area-left: env(safe-area-inset-left, 0px); + --safe-area-right: env(safe-area-inset-right, 0px); } html, @@ -44,6 +48,41 @@ a { } } +@keyframes hf-dot-fade { + 0%, 80%, 100% { + opacity: 0.2; + } + 40% { + opacity: 1; + } +} + +@keyframes hf-typing-in { + from { + opacity: 0; + max-height: 0; + transform: translateY(8px); + } + to { + opacity: 1; + max-height: 40px; + transform: translateY(0); + } +} + +@keyframes hf-typing-out { + from { + opacity: 1; + max-height: 40px; + transform: translateY(0); + } + to { + opacity: 0; + max-height: 0; + transform: translateY(8px); + } +} + button, input, textarea, diff --git a/foundry/packages/shared/src/app-shell.ts b/foundry/packages/shared/src/app-shell.ts index 8e757c59..f309b0e4 100644 --- a/foundry/packages/shared/src/app-shell.ts +++ b/foundry/packages/shared/src/app-shell.ts @@ -10,6 +10,7 @@ export interface FoundryUser { name: string; email: string; githubLogin: string; + avatarUrl: string | null; roleLabel: string; eligibleOrganizationIds: string[]; } @@ -20,6 +21,8 @@ export interface FoundryOrganizationMember { email: string; role: "owner" | "admin" | "member"; state: "active" | "invited"; + avatarUrl: string | null; + githubLogin: string | null; } export interface FoundryInvoice { diff --git a/foundry/packages/shared/src/workbench.ts b/foundry/packages/shared/src/workbench.ts index 21118b71..d4898fc7 100644 --- a/foundry/packages/shared/src/workbench.ts +++ b/foundry/packages/shared/src/workbench.ts @@ -76,6 +76,14 @@ export interface WorkbenchPullRequestSummary { status: "draft" | "ready"; } +export interface WorkbenchPresence { + memberId: string; + name: string; + avatarUrl: string | null; + lastSeenAtMs: number; + typing?: boolean; +} + export interface WorkbenchTask { id: string; repoId: string; @@ -90,6 +98,7 @@ export interface WorkbenchTask { diffs: Record; fileTree: WorkbenchFileTreeNode[]; minutesUsed: number; + presence: WorkbenchPresence[]; } export interface WorkbenchRepo {