@songsid/agend 2.3.0-beta.9 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -8
- package/README.zh-TW.md +16 -8
- package/dist/adapter-world.js.map +1 -1
- package/dist/agend-home.d.ts +5 -0
- package/dist/agend-home.js +7 -0
- package/dist/agend-home.js.map +1 -0
- package/dist/agent-cli-instructions.md +7 -1
- package/dist/agent-cli.js +41 -0
- package/dist/agent-cli.js.map +1 -1
- package/dist/agent-endpoint.d.ts +9 -0
- package/dist/agent-endpoint.js +23 -0
- package/dist/agent-endpoint.js.map +1 -1
- package/dist/agent-file-read.js +1 -1
- package/dist/agent-file-read.js.map +1 -1
- package/dist/agent-whats-new.d.ts +16 -0
- package/dist/agent-whats-new.js +53 -12
- package/dist/agent-whats-new.js.map +1 -1
- package/dist/apply-job.js.map +1 -1
- package/dist/atomic-write.js.map +1 -1
- package/dist/auth-api.d.ts +12 -0
- package/dist/auth-api.js +77 -22
- package/dist/auth-api.js.map +1 -1
- package/dist/authority/authority-state.d.ts +4 -0
- package/dist/authority/authority-state.js +17 -8
- package/dist/authority/authority-state.js.map +1 -1
- package/dist/authority/session-authorizations.js.map +1 -1
- package/dist/authority/web-authority.d.ts +16 -8
- package/dist/authority/web-authority.js +19 -5
- package/dist/authority/web-authority.js.map +1 -1
- package/dist/backend/antigravity.d.ts +2 -2
- package/dist/backend/antigravity.js +2 -1
- package/dist/backend/antigravity.js.map +1 -1
- package/dist/backend/claude-code.js +13 -4
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/codex-metadata.d.ts +8 -0
- package/dist/backend/codex-metadata.js +74 -17
- package/dist/backend/codex-metadata.js.map +1 -1
- package/dist/backend/codex-package.d.ts +30 -0
- package/dist/backend/codex-package.js +133 -0
- package/dist/backend/codex-package.js.map +1 -0
- package/dist/backend/codex-session-lookup.js.map +1 -1
- package/dist/backend/codex.d.ts +2 -0
- package/dist/backend/codex.js +25 -5
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/credential-profile.d.ts +2 -0
- package/dist/backend/credential-profile.js +2 -0
- package/dist/backend/credential-profile.js.map +1 -1
- package/dist/backend/effort-metadata.js.map +1 -1
- package/dist/backend/grok.js +58 -3
- package/dist/backend/grok.js.map +1 -1
- package/dist/backend/kiro-engine-ledger.js.map +1 -1
- package/dist/backend/kiro-kas-store.js.map +1 -1
- package/dist/backend/kiro-v2-store.js.map +1 -1
- package/dist/backend/kiro-v3-identity.js.map +1 -1
- package/dist/backend/kiro.d.ts +9 -1
- package/dist/backend/kiro.js +102 -1
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/launch-effort.js.map +1 -1
- package/dist/backend/mock.js.map +1 -1
- package/dist/backend/muse.js.map +1 -1
- package/dist/backend/opencode-permission.js +1 -1
- package/dist/backend/opencode-permission.js.map +1 -1
- package/dist/backend/opencode.js +2 -1
- package/dist/backend/opencode.js.map +1 -1
- package/dist/backend/session-signals.js.map +1 -1
- package/dist/backend-availability.js.map +1 -1
- package/dist/backend-command.d.ts +2 -0
- package/dist/backend-command.js +3 -1
- package/dist/backend-command.js.map +1 -1
- package/dist/backend-outage.js.map +1 -1
- package/dist/binary-probe.js +1 -1
- package/dist/binary-probe.js.map +1 -1
- package/dist/bug-report-cli.d.ts +30 -0
- package/dist/bug-report-cli.js +139 -0
- package/dist/bug-report-cli.js.map +1 -0
- package/dist/bug-report.d.ts +47 -0
- package/dist/bug-report.js +137 -0
- package/dist/bug-report.js.map +1 -0
- package/dist/bundled-skills.d.ts +18 -0
- package/dist/bundled-skills.js +38 -0
- package/dist/bundled-skills.js.map +1 -0
- package/dist/cache-service.js +1 -1
- package/dist/cache-service.js.map +1 -1
- package/dist/channel/adapters/discord-client-retirement.d.ts +5 -0
- package/dist/channel/adapters/discord-client-retirement.js +57 -0
- package/dist/channel/adapters/discord-client-retirement.js.map +1 -0
- package/dist/channel/adapters/discord.d.ts +4 -0
- package/dist/channel/adapters/discord.js +57 -12
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +6 -0
- package/dist/channel/adapters/telegram.js +54 -14
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/mcp-server.js +21 -4
- package/dist/channel/mcp-server.js.map +1 -1
- package/dist/channel/mcp-tools.d.ts +3 -1
- package/dist/channel/mcp-tools.js +41 -4
- package/dist/channel/mcp-tools.js.map +1 -1
- package/dist/channel/message-queue.js.map +1 -1
- package/dist/channel/sticker-download.js.map +1 -1
- package/dist/channel/tool-router.js.map +1 -1
- package/dist/child-process.d.ts +21 -0
- package/dist/child-process.js +54 -0
- package/dist/child-process.js.map +1 -0
- package/dist/classic-channel-manager.js +3 -2
- package/dist/classic-channel-manager.js.map +1 -1
- package/dist/cli-entry.js.map +1 -1
- package/dist/cli-flags.js.map +1 -1
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +443 -311
- package/dist/cli.js.map +1 -1
- package/dist/command-table.d.ts +1 -1
- package/dist/command-table.js +1 -1
- package/dist/command-table.js.map +1 -1
- package/dist/compact-watch.js.map +1 -1
- package/dist/completion-install.js.map +1 -1
- package/dist/completion.js.map +1 -1
- package/dist/config-validator.d.ts +6 -0
- package/dist/config-validator.js +81 -8
- package/dist/config-validator.js.map +1 -1
- package/dist/config.d.ts +15 -3
- package/dist/config.js +41 -10
- package/dist/config.js.map +1 -1
- package/dist/connection-secrets.js.map +1 -1
- package/dist/context-guardian.js.map +1 -1
- package/dist/coredump-filter.js.map +1 -1
- package/dist/cpu-profile.js.map +1 -1
- package/dist/cross-instance-envelope.js.map +1 -1
- package/dist/cross-instance-notice.d.ts +7 -0
- package/dist/cross-instance-notice.js +10 -0
- package/dist/cross-instance-notice.js.map +1 -1
- package/dist/daemon.d.ts +39 -1
- package/dist/daemon.js +234 -15
- package/dist/daemon.js.map +1 -1
- package/dist/daily-summary.js.map +1 -1
- package/dist/darwin-memory.js +1 -1
- package/dist/darwin-memory.js.map +1 -1
- package/dist/dashboard-live.d.ts +8 -0
- package/dist/dashboard-live.js +35 -0
- package/dist/dashboard-live.js.map +1 -0
- package/dist/dashboard-permissions.d.ts +69 -0
- package/dist/dashboard-permissions.js +138 -0
- package/dist/dashboard-permissions.js.map +1 -0
- package/dist/decision-list.js.map +1 -1
- package/dist/delivery-consumed-watch.js.map +1 -1
- package/dist/delivery-outbox.js +5 -0
- package/dist/delivery-outbox.js.map +1 -1
- package/dist/delivery-outbox.test.js.map +1 -1
- package/dist/delivery-reconciliation.test.js.map +1 -1
- package/dist/diagnostic-redaction.d.ts +10 -0
- package/dist/diagnostic-redaction.js +167 -0
- package/dist/diagnostic-redaction.js.map +1 -0
- package/dist/doctor.d.ts +8 -0
- package/dist/doctor.js +52 -0
- package/dist/doctor.js.map +1 -1
- package/dist/e2e-isolation.js.map +1 -1
- package/dist/event-log.js.map +1 -1
- package/dist/export-import.js +7 -5
- package/dist/export-import.js.map +1 -1
- package/dist/fleet-control-audit.js.map +1 -1
- package/dist/fleet-label.js.map +1 -1
- package/dist/fleet-level-config.d.ts +1 -1
- package/dist/fleet-level-config.js +2 -0
- package/dist/fleet-level-config.js.map +1 -1
- package/dist/fleet-lock.js +3 -2
- package/dist/fleet-lock.js.map +1 -1
- package/dist/fleet-manager.d.ts +249 -13
- package/dist/fleet-manager.js +1561 -292
- package/dist/fleet-manager.js.map +1 -1
- package/dist/fleet-process-handlers.d.ts +18 -0
- package/dist/fleet-process-handlers.js +70 -0
- package/dist/fleet-process-handlers.js.map +1 -0
- package/dist/fleet-startup.d.ts +14 -0
- package/dist/fleet-startup.js +30 -0
- package/dist/fleet-startup.js.map +1 -0
- package/dist/fleet-traffic.js.map +1 -1
- package/dist/forged-envelope-scan.d.ts +0 -20
- package/dist/forged-envelope-scan.js +3 -2
- package/dist/forged-envelope-scan.js.map +1 -1
- package/dist/full-restart.d.ts +5 -5
- package/dist/full-restart.js +5 -5
- package/dist/full-restart.js.map +1 -1
- package/dist/general-knowledge/skills/bug-report/SKILL.md +31 -0
- package/dist/general-knowledge/skills/credential-profiles/SKILL.md +52 -11
- package/dist/general-knowledge/skills/cross-instance-messaging/SKILL.md +5 -1
- package/dist/general-knowledge/skills/fleet-config/SKILL.md +3 -1
- package/dist/general-knowledge/skills/fleet-restart/SKILL.md +8 -9
- package/dist/general-knowledge/skills/multi-channel/SKILL.md +1 -1
- package/dist/general-knowledge/skills/persona-emoji/SKILL.md +1 -1
- package/dist/general-knowledge/skills/scheduling/SKILL.md +4 -0
- package/dist/general-knowledge/skills/web-appearance/SKILL.canvas-worker-off.md +321 -0
- package/dist/general-knowledge/skills/web-appearance/SKILL.md +24 -4
- package/dist/general-knowledge/skills/web-dashboard/SKILL.canvas-worker-off.md +553 -0
- package/dist/general-knowledge/skills/web-dashboard/SKILL.md +154 -31
- package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +1 -1
- package/dist/general-knowledge/steering/core-rules.md +1 -1
- package/dist/host-memory.js.map +1 -1
- package/dist/idle-gate-log.d.ts +19 -0
- package/dist/idle-gate-log.js +15 -0
- package/dist/idle-gate-log.js.map +1 -0
- package/dist/instance-config-impact.js +25 -4
- package/dist/instance-config-impact.js.map +1 -1
- package/dist/instance-lifecycle.d.ts +10 -1
- package/dist/instance-lifecycle.js +86 -25
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/instructions.d.ts +12 -6
- package/dist/instructions.js +19 -10
- package/dist/instructions.js.map +1 -1
- package/dist/kiro-compact-pane.js.map +1 -1
- package/dist/kiro-db-reader.js.map +1 -1
- package/dist/kiro-engine-status.js.map +1 -1
- package/dist/kiro-log-gate.js.map +1 -1
- package/dist/kiro-transcript-lane.js.map +1 -1
- package/dist/locale.js +428 -20
- package/dist/locale.js.map +1 -1
- package/dist/log-service.js.map +1 -1
- package/dist/log-steps.d.ts +1 -0
- package/dist/log-steps.js +15 -0
- package/dist/log-steps.js.map +1 -1
- package/dist/logger.js +3 -2
- package/dist/logger.js.map +1 -1
- package/dist/login-controller.d.ts +45 -0
- package/dist/login-controller.js +101 -5
- package/dist/login-controller.js.map +1 -1
- package/dist/login-flows.js +1 -1
- package/dist/login-manager.js.map +1 -1
- package/dist/login-shell.js +3 -1
- package/dist/login-shell.js.map +1 -1
- package/dist/ls-attach-resolve.d.ts +96 -0
- package/dist/ls-attach-resolve.js +180 -0
- package/dist/ls-attach-resolve.js.map +1 -0
- package/dist/ls-rows.d.ts +12 -0
- package/dist/ls-rows.js +83 -4
- package/dist/ls-rows.js.map +1 -1
- package/dist/memory-pressure.js.map +1 -1
- package/dist/muse-usage-relay.js.map +1 -1
- package/dist/needs-you-hub.d.ts +98 -1
- package/dist/needs-you-hub.js +313 -44
- package/dist/needs-you-hub.js.map +1 -1
- package/dist/needs-you-live.d.ts +5 -2
- package/dist/needs-you-live.js +6 -3
- package/dist/needs-you-live.js.map +1 -1
- package/dist/needs-you.d.ts +68 -3
- package/dist/needs-you.js +38 -4
- package/dist/needs-you.js.map +1 -1
- package/dist/network-family.js.map +1 -1
- package/dist/operator-control-paths.js +3 -4
- package/dist/operator-control-paths.js.map +1 -1
- package/dist/outbound-handlers.d.ts +3 -0
- package/dist/outbound-handlers.js +76 -19
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +106 -60
- package/dist/outbound-schemas.js +33 -10
- package/dist/outbound-schemas.js.map +1 -1
- package/dist/outbox-open-error.js.map +1 -1
- package/dist/pane-context-cache.js.map +1 -1
- package/dist/paths.js.map +1 -1
- package/dist/private-dir.js.map +1 -1
- package/dist/probe-worker-pool.js.map +1 -1
- package/dist/profile-control.js.map +1 -1
- package/dist/prompt-file-ref.js.map +1 -1
- package/dist/provider-probe.js.map +1 -1
- package/dist/provider-secret-registry.d.ts +5 -3
- package/dist/provider-secret-registry.js +8 -2
- package/dist/provider-secret-registry.js.map +1 -1
- package/dist/public-link-auto-open.d.ts +32 -0
- package/dist/public-link-auto-open.js +86 -0
- package/dist/public-link-auto-open.js.map +1 -0
- package/dist/public-link-owner.d.ts +10 -0
- package/dist/public-link-owner.js +36 -0
- package/dist/public-link-owner.js.map +1 -0
- package/dist/public-link-progress.d.ts +12 -1
- package/dist/public-link-progress.js +5 -10
- package/dist/public-link-progress.js.map +1 -1
- package/dist/public-preview.js.map +1 -1
- package/dist/public-tunnel-config.d.ts +11 -0
- package/dist/public-tunnel-config.js +68 -0
- package/dist/public-tunnel-config.js.map +1 -0
- package/dist/public-web-gateway.d.ts +2 -0
- package/dist/public-web-gateway.js +19 -6
- package/dist/public-web-gateway.js.map +1 -1
- package/dist/public-web-link.d.ts +48 -3
- package/dist/public-web-link.js +177 -51
- package/dist/public-web-link.js.map +1 -1
- package/dist/quickstart-api.d.ts +9 -0
- package/dist/quickstart-api.js +82 -0
- package/dist/quickstart-api.js.map +1 -1
- package/dist/quickstart.d.ts +5 -0
- package/dist/quickstart.js +40 -25
- package/dist/quickstart.js.map +1 -1
- package/dist/reply-buttons-controller.js.map +1 -1
- package/dist/reply-dedup.js.map +1 -1
- package/dist/resource-report.js +1 -1
- package/dist/resource-report.js.map +1 -1
- package/dist/restart-guard.js.map +1 -1
- package/dist/restart-progress.d.ts +80 -1
- package/dist/restart-progress.js +306 -21
- package/dist/restart-progress.js.map +1 -1
- package/dist/rollout-index.js.map +1 -1
- package/dist/runtime-cpu-profile.js.map +1 -1
- package/dist/scheduler/db.d.ts +40 -13
- package/dist/scheduler/db.js +123 -89
- package/dist/scheduler/db.js.map +1 -1
- package/dist/scheduler/scheduler.js.map +1 -1
- package/dist/scheduler/task-board-text.d.ts +26 -0
- package/dist/scheduler/task-board-text.js +140 -0
- package/dist/scheduler/task-board-text.js.map +1 -0
- package/dist/scheduler/task-board.d.ts +730 -0
- package/dist/scheduler/task-board.js +2179 -0
- package/dist/scheduler/task-board.js.map +1 -0
- package/dist/scheduler/types.d.ts +6 -1
- package/dist/sd-notify.js +2 -1
- package/dist/sd-notify.js.map +1 -1
- package/dist/search/search-docs.d.ts +58 -0
- package/dist/search/search-docs.js +63 -0
- package/dist/search/search-docs.js.map +1 -0
- package/dist/search/search-index.d.ts +141 -0
- package/dist/search/search-index.js +440 -0
- package/dist/search/search-index.js.map +1 -0
- package/dist/search/search-store.d.ts +122 -0
- package/dist/search/search-store.js +236 -0
- package/dist/search/search-store.js.map +1 -0
- package/dist/search/search-worker.d.ts +1 -0
- package/dist/search/search-worker.js +163 -0
- package/dist/search/search-worker.js.map +1 -0
- package/dist/secret-file.js.map +1 -1
- package/dist/secret-store.d.ts +2 -0
- package/dist/secret-store.js +21 -0
- package/dist/secret-store.js.map +1 -1
- package/dist/service-installer.d.ts +75 -0
- package/dist/service-installer.js +206 -0
- package/dist/service-installer.js.map +1 -1
- package/dist/service-owner.d.ts +44 -0
- package/dist/service-owner.js +48 -0
- package/dist/service-owner.js.map +1 -0
- package/dist/service-plan.d.ts +39 -2
- package/dist/service-plan.js +188 -6
- package/dist/service-plan.js.map +1 -1
- package/dist/session-oom.d.ts +21 -0
- package/dist/session-oom.js +139 -0
- package/dist/session-oom.js.map +1 -0
- package/dist/settings-api.d.ts +13 -0
- package/dist/settings-api.js +73 -12
- package/dist/settings-api.js.map +1 -1
- package/dist/settings-baseline.js.map +1 -1
- package/dist/settings-change.d.ts +5 -0
- package/dist/settings-change.js +167 -6
- package/dist/settings-change.js.map +1 -1
- package/dist/settings-confirmation.d.ts +9 -1
- package/dist/settings-confirmation.js +18 -8
- package/dist/settings-confirmation.js.map +1 -1
- package/dist/settings-control.js +2 -1
- package/dist/settings-control.js.map +1 -1
- package/dist/settings-effect.js +29 -4
- package/dist/settings-effect.js.map +1 -1
- package/dist/settings-http-confirmation.d.ts +13 -0
- package/dist/settings-http-confirmation.js +15 -3
- package/dist/settings-http-confirmation.js.map +1 -1
- package/dist/settings-instance-patch.js +13 -1
- package/dist/settings-instance-patch.js.map +1 -1
- package/dist/settings-request-capability.d.ts +4 -1
- package/dist/settings-request-capability.js +11 -3
- package/dist/settings-request-capability.js.map +1 -1
- package/dist/settings-transaction.js.map +1 -1
- package/dist/setup-auth.d.ts +1 -0
- package/dist/setup-auth.js +2 -1
- package/dist/setup-auth.js.map +1 -1
- package/dist/setup-form.d.ts +1 -1
- package/dist/setup-form.js +23 -7
- package/dist/setup-form.js.map +1 -1
- package/dist/setup-host.d.ts +6 -1
- package/dist/setup-host.js +15 -4
- package/dist/setup-host.js.map +1 -1
- package/dist/setup-wizard.js +6 -3
- package/dist/setup-wizard.js.map +1 -1
- package/dist/spawn-gate.d.ts +5 -0
- package/dist/spawn-gate.js +28 -8
- package/dist/spawn-gate.js.map +1 -1
- package/dist/start-attempt.d.ts +1 -0
- package/dist/start-attempt.js +18 -0
- package/dist/start-attempt.js.map +1 -0
- package/dist/start-failure-notice.d.ts +4 -0
- package/dist/start-failure-notice.js +20 -0
- package/dist/start-failure-notice.js.map +1 -0
- package/dist/start-failure.d.ts +147 -0
- package/dist/start-failure.js +281 -0
- package/dist/start-failure.js.map +1 -0
- package/dist/startup-memory-deadline.d.ts +23 -0
- package/dist/startup-memory-deadline.js +55 -0
- package/dist/startup-memory-deadline.js.map +1 -0
- package/dist/statusline-watcher.js.map +1 -1
- package/dist/storm-window.js.map +1 -1
- package/dist/systemd-peer-bus.js.map +1 -1
- package/dist/target-queue-worker.js.map +1 -1
- package/dist/task-board-summary.d.ts +101 -0
- package/dist/task-board-summary.js +177 -0
- package/dist/task-board-summary.js.map +1 -0
- package/dist/task-board-tool.d.ts +25 -0
- package/dist/task-board-tool.js +155 -0
- package/dist/task-board-tool.js.map +1 -0
- package/dist/task-board-waker.d.ts +51 -0
- package/dist/task-board-waker.js +141 -0
- package/dist/task-board-waker.js.map +1 -0
- package/dist/tips.js.map +1 -1
- package/dist/tmux-control.js +1 -1
- package/dist/tmux-control.js.map +1 -1
- package/dist/tmux-exec-helper.d.ts +104 -0
- package/dist/tmux-exec-helper.js +412 -0
- package/dist/tmux-exec-helper.js.map +1 -0
- package/dist/tmux-manager.d.ts +1 -0
- package/dist/tmux-manager.js +29 -13
- package/dist/tmux-manager.js.map +1 -1
- package/dist/tmux-read.js +2 -2
- package/dist/tmux-read.js.map +1 -1
- package/dist/tool-permissions.js.map +1 -1
- package/dist/tool-progress.js.map +1 -1
- package/dist/topic-archiver.js.map +1 -1
- package/dist/topic-commands.d.ts +13 -0
- package/dist/topic-commands.js +56 -33
- package/dist/topic-commands.js.map +1 -1
- package/dist/topic-link.js.map +1 -1
- package/dist/transcript-delta-reader.js.map +1 -1
- package/dist/transcript-jsonl.js.map +1 -1
- package/dist/transcript-monitor.js +5 -0
- package/dist/transcript-monitor.js.map +1 -1
- package/dist/transcript-sources.d.ts +2 -0
- package/dist/transcript-sources.js +4 -0
- package/dist/transcript-sources.js.map +1 -1
- package/dist/tunnel/cloudflared-install.js +3 -1
- package/dist/tunnel/cloudflared-install.js.map +1 -1
- package/dist/tunnel/cloudflared.d.ts +7 -16
- package/dist/tunnel/cloudflared.js +100 -13
- package/dist/tunnel/cloudflared.js.map +1 -1
- package/dist/tunnel/lease.js +3 -2
- package/dist/tunnel/lease.js.map +1 -1
- package/dist/tunnel/manager.js.map +1 -1
- package/dist/tunnel/named-diagnostics.d.ts +13 -0
- package/dist/tunnel/named-diagnostics.js +52 -0
- package/dist/tunnel/named-diagnostics.js.map +1 -0
- package/dist/tunnel/public-fetch.js.map +1 -1
- package/dist/tunnel/purpose-lane.js.map +1 -1
- package/dist/tunnel/types.d.ts +4 -1
- package/dist/tunnel/types.js.map +1 -1
- package/dist/types.d.ts +55 -2
- package/dist/ui/app-effects.js +23 -5
- package/dist/ui/app.html +2 -0
- package/dist/ui/backend-signin.js +297 -0
- package/dist/ui/chat-effects.js +10 -3
- package/dist/ui/chat-msg-actions.js +176 -0
- package/dist/ui/chat-render.js +62 -18
- package/dist/ui/chat-store.js +218 -48
- package/dist/ui/chat-strings.js +40 -8
- package/dist/ui/chat-thread.js +119 -10
- package/dist/ui/effect-trial-offer.js +2 -31
- package/dist/ui/effects-waker.js +2 -0
- package/dist/ui/fleet-canvas-layout.js +13 -4
- package/dist/ui/fleet-canvas.js +69 -28
- package/dist/ui/fleet-office-editor.js +149 -0
- package/dist/ui/fleet-office-model.js +358 -0
- package/dist/ui/fleet-office-pack.js +199 -0
- package/dist/ui/fleet-office-skin.js +474 -0
- package/dist/ui/fleet-office-store.js +49 -0
- package/dist/ui/fleet-office-zones.js +177 -0
- package/dist/ui/fleet-office.js +434 -0
- package/dist/ui/fleet-org.js +18 -5
- package/dist/ui/fleet-route-scene.js +272 -0
- package/dist/ui/fleet-route-worker.js +21 -0
- package/dist/ui/fleet-route.js +88 -0
- package/dist/ui/fleet-task-card.js +436 -0
- package/dist/ui/fleet-task-common.js +482 -0
- package/dist/ui/fleet-task-work.js +107 -0
- package/dist/ui/fleet-tasks.js +569 -0
- package/dist/ui/fleet-traffic.js +81 -18
- package/dist/ui/fleet-usage.js +36 -2
- package/dist/ui/guest-refused.html +41 -0
- package/dist/ui/icons/icon-192.png +0 -0
- package/dist/ui/icons/icon-512.png +0 -0
- package/dist/ui/image-lightbox.js +45 -1
- package/dist/ui/image-zoom.js +242 -0
- package/dist/ui/panel-chat.js +200 -56
- package/dist/ui/panel-details.js +2 -0
- package/dist/ui/panel-fleet.js +32 -71
- package/dist/ui/panel-needs.js +23 -6
- package/dist/ui/panel-settings.js +158 -32
- package/dist/ui/preview-panel.js +2 -1
- package/dist/ui/search-dialog.js +350 -0
- package/dist/ui/settings-appearance.js +170 -10
- package/dist/ui/settings-apply.js +3 -3
- package/dist/ui/settings-confirm.js +7 -2
- package/dist/ui/settings-dialogs.js +46 -21
- package/dist/ui/settings-discord.js +6 -2
- package/dist/ui/settings-guests.js +2 -1
- package/dist/ui/settings-learn.js +1 -0
- package/dist/ui/settings-model.js +51 -18
- package/dist/ui/settings-mods.js +8 -3
- package/dist/ui/settings-owner-effects.js +6 -4
- package/dist/ui/settings-strings.js +180 -6
- package/dist/ui/settings-token.js +3 -1
- package/dist/ui/settings-web-authority.js +13 -5
- package/dist/ui/settings-wizard.js +13 -7
- package/dist/ui/shared/agend-auth.js +2 -0
- package/dist/ui/shared/app-i18n.js +12 -5
- package/dist/ui/shared/app-needs.js +2 -2
- package/dist/ui/shared/app-prefs.js +15 -0
- package/dist/ui/shared/app-route.js +18 -0
- package/dist/ui/shared/app-shell.js +172 -28
- package/dist/ui/shared/app-store.js +3 -2
- package/dist/ui/shared/app-stream.js +5 -1
- package/dist/ui/shared/app-themes.js +116 -1
- package/dist/ui/shared/app.css +662 -48
- package/dist/ui/shared/app.js +9 -1
- package/dist/ui/shared/card-strings.js +4 -0
- package/dist/ui/shared/effect-app-runtime.js +7 -5
- package/dist/ui/shared/effect-chat-runtime.js +2 -7
- package/dist/ui/shared/effect-cursor.js +3 -2
- package/dist/ui/shared/effect-display-metadata.js +39 -0
- package/dist/ui/shared/effect-owner-source.js +8 -1
- package/dist/ui/shared/effect-registry.js +14 -4
- package/dist/ui/shared/effect-runtime-loader.js +3 -1
- package/dist/ui/shared/effect-stock-trust.js +5 -5
- package/dist/ui/shared/feature-flags.js +127 -0
- package/dist/ui/shared/guest-refused.js +35 -0
- package/dist/ui/shared/header-tools.js +2 -2
- package/dist/ui/shared/identity-card.js +26 -8
- package/dist/ui/shared/identity-color.js +17 -10
- package/dist/ui/shared/instance-nav.js +183 -28
- package/dist/ui/shared/owner-css.js +30 -1
- package/dist/ui/shared/panel-view.js +14 -29
- package/dist/ui/shared/text-undo.js +210 -0
- package/dist/ui/shared/tokens.css +4 -0
- package/dist/ui/shared/ui-dialog.js +5 -4
- package/dist/ui/shared/ui-icons.js +4 -0
- package/dist/ui/shared/ui-menu.js +20 -7
- package/dist/ui/shared/ui-toast.js +16 -3
- package/dist/ui/shared/usage-dialog.js +206 -16
- package/dist/ui/shared/view-strings.js +68 -4
- package/dist/ui/shared/web-authorize.js +50 -1
- package/dist/ui/signin.html +2 -0
- package/dist/ui/web-terminal/terminal.html +10 -10
- package/dist/ui/web-terminal/terminal.js +58 -12
- package/dist/update-check.js.map +1 -1
- package/dist/update-dispatch.js +1 -1
- package/dist/update-dispatch.js.map +1 -1
- package/dist/update-install.js.map +1 -1
- package/dist/update-launch.d.ts +10 -1
- package/dist/update-launch.js +39 -14
- package/dist/update-launch.js.map +1 -1
- package/dist/update-marker.js.map +1 -1
- package/dist/update-preflight.js +1 -1
- package/dist/update-preflight.js.map +1 -1
- package/dist/update-progress.d.ts +3 -1
- package/dist/update-progress.js +3 -1
- package/dist/update-progress.js.map +1 -1
- package/dist/usage/format-rich.js +6 -3
- package/dist/usage/format-rich.js.map +1 -1
- package/dist/usage/i18n-keys.d.ts +1 -1
- package/dist/usage/i18n-keys.js +2 -1
- package/dist/usage/i18n-keys.js.map +1 -1
- package/dist/usage/i18n.d.ts +13 -1
- package/dist/usage/i18n.js +29 -0
- package/dist/usage/i18n.js.map +1 -1
- package/dist/usage/providers.d.ts +89 -2
- package/dist/usage/providers.js +247 -41
- package/dist/usage/providers.js.map +1 -1
- package/dist/usage/statusline-usage.js.map +1 -1
- package/dist/usage/usage-api.d.ts +5 -1
- package/dist/usage/usage-api.js +185 -58
- package/dist/usage/usage-api.js.map +1 -1
- package/dist/usage-report.js.map +1 -1
- package/dist/usage-rollup.js +1 -1
- package/dist/usage-rollup.js.map +1 -1
- package/dist/user-systemd.d.ts +24 -0
- package/dist/user-systemd.js +75 -0
- package/dist/user-systemd.js.map +1 -0
- package/dist/view-api.d.ts +7 -0
- package/dist/view-api.js +16 -4
- package/dist/view-api.js.map +1 -1
- package/dist/wake-coordinator.js.map +1 -1
- package/dist/web-ambient.js.map +1 -1
- package/dist/web-api.d.ts +57 -10
- package/dist/web-api.js +1103 -70
- package/dist/web-api.js.map +1 -1
- package/dist/web-app-icon-worker.d.ts +1 -0
- package/dist/web-app-icon-worker.js +16 -0
- package/dist/web-app-icon-worker.js.map +1 -0
- package/dist/web-app-icon.d.ts +109 -0
- package/dist/web-app-icon.js +257 -0
- package/dist/web-app-icon.js.map +1 -0
- package/dist/web-appearance-policy.js.map +1 -1
- package/dist/web-appearance-tools.d.ts +1 -0
- package/dist/web-appearance-tools.js +7 -3
- package/dist/web-appearance-tools.js.map +1 -1
- package/dist/web-appearance-view.js.map +1 -1
- package/dist/web-appearance.d.ts +4 -10
- package/dist/web-appearance.js +7 -4
- package/dist/web-appearance.js.map +1 -1
- package/dist/web-auth.d.ts +8 -4
- package/dist/web-auth.js +33 -21
- package/dist/web-auth.js.map +1 -1
- package/dist/web-backend-login.d.ts +130 -0
- package/dist/web-backend-login.js +225 -0
- package/dist/web-backend-login.js.map +1 -0
- package/dist/web-card.js.map +1 -1
- package/dist/web-channel-echo.js.map +1 -1
- package/dist/web-chat-history.d.ts +118 -8
- package/dist/web-chat-history.js +220 -25
- package/dist/web-chat-history.js.map +1 -1
- package/dist/web-commands.d.ts +5 -1
- package/dist/web-commands.js +1 -1
- package/dist/web-commands.js.map +1 -1
- package/dist/web-cookie-names.d.ts +5 -0
- package/dist/web-cookie-names.js +12 -0
- package/dist/web-cookie-names.js.map +1 -0
- package/dist/web-effect-bundle.d.ts +2 -2
- package/dist/web-effect-library.js.map +1 -1
- package/dist/web-effect-playback.js.map +1 -1
- package/dist/web-effect-profiles.d.ts +16 -16
- package/dist/web-effect-profiles.js +3 -2
- package/dist/web-effect-profiles.js.map +1 -1
- package/dist/web-effect-service.js.map +1 -1
- package/dist/web-effect-tools.js.map +1 -1
- package/dist/web-effect-trials.js.map +1 -1
- package/dist/web-effect-upload.js.map +1 -1
- package/dist/web-effect.d.ts +6 -6
- package/dist/web-effect.js.map +1 -1
- package/dist/web-experimental-http.d.ts +2 -0
- package/dist/web-experimental-http.js +12 -0
- package/dist/web-experimental-http.js.map +1 -0
- package/dist/web-experimental.d.ts +11 -0
- package/dist/web-experimental.js +49 -0
- package/dist/web-experimental.js.map +1 -0
- package/dist/web-guest-access.d.ts +4 -2
- package/dist/web-guest-access.js +22 -10
- package/dist/web-guest-access.js.map +1 -1
- package/dist/web-guest-rooms.js.map +1 -1
- package/dist/web-host-guard.d.ts +11 -0
- package/dist/web-host-guard.js +11 -0
- package/dist/web-host-guard.js.map +1 -1
- package/dist/web-icons.d.ts +33 -1
- package/dist/web-icons.js +83 -11
- package/dist/web-icons.js.map +1 -1
- package/dist/web-identity-color.js.map +1 -1
- package/dist/web-image-meta.d.ts +13 -0
- package/dist/web-image-meta.js +62 -0
- package/dist/web-image-meta.js.map +1 -1
- package/dist/web-images.js.map +1 -1
- package/dist/web-libavoid.d.ts +14 -0
- package/dist/web-libavoid.js +46 -0
- package/dist/web-libavoid.js.map +1 -0
- package/dist/web-login.js.map +1 -1
- package/dist/web-mentions.js.map +1 -1
- package/dist/web-mod-agent.js.map +1 -1
- package/dist/web-mod-store.d.ts +2 -0
- package/dist/web-mod-store.js +10 -0
- package/dist/web-mod-store.js.map +1 -1
- package/dist/web-office-store.d.ts +104 -0
- package/dist/web-office-store.js +236 -0
- package/dist/web-office-store.js.map +1 -0
- package/dist/web-owner-css-store.d.ts +44 -1
- package/dist/web-owner-css-store.js +70 -9
- package/dist/web-owner-css-store.js.map +1 -1
- package/dist/web-owner-css.js.map +1 -1
- package/dist/web-png.d.ts +33 -0
- package/dist/web-png.js +329 -0
- package/dist/web-png.js.map +1 -0
- package/dist/web-prefs.d.ts +6 -0
- package/dist/web-prefs.js +29 -3
- package/dist/web-prefs.js.map +1 -1
- package/dist/web-preview.d.ts +2 -0
- package/dist/web-preview.js +2 -0
- package/dist/web-preview.js.map +1 -1
- package/dist/web-profile.js.map +1 -1
- package/dist/web-reactions.d.ts +35 -0
- package/dist/web-reactions.js +47 -0
- package/dist/web-reactions.js.map +1 -0
- package/dist/web-request-context.d.ts +5 -0
- package/dist/web-request-context.js.map +1 -1
- package/dist/web-returning-device.d.ts +4 -2
- package/dist/web-returning-device.js +13 -6
- package/dist/web-returning-device.js.map +1 -1
- package/dist/web-schedules.js.map +1 -1
- package/dist/web-send-dedupe.d.ts +36 -0
- package/dist/web-send-dedupe.js +69 -0
- package/dist/web-send-dedupe.js.map +1 -0
- package/dist/web-session-authorization.js.map +1 -1
- package/dist/web-session.js +1 -1
- package/dist/web-session.js.map +1 -1
- package/dist/web-settings-patch.d.ts +3 -1
- package/dist/web-settings-patch.js +11 -5
- package/dist/web-settings-patch.js.map +1 -1
- package/dist/web-settings-tools.d.ts +6 -0
- package/dist/web-settings-tools.js +52 -17
- package/dist/web-settings-tools.js.map +1 -1
- package/dist/web-terminal-http.js +15 -2
- package/dist/web-terminal-http.js.map +1 -1
- package/dist/web-terminal.js +1 -1
- package/dist/web-terminal.js.map +1 -1
- package/dist/web-theme-store.d.ts +2 -2
- package/dist/web-theme-store.js +6 -3
- package/dist/web-theme-store.js.map +1 -1
- package/dist/web-theme.d.ts +29 -0
- package/dist/web-theme.js +89 -1
- package/dist/web-theme.js.map +1 -1
- package/dist/web-upload.d.ts +18 -1
- package/dist/web-upload.js +45 -7
- package/dist/web-upload.js.map +1 -1
- package/dist/web-widget.js.map +1 -1
- package/dist/webhook-emitter.js.map +1 -1
- package/dist/windows-shortcuts.d.ts +78 -0
- package/dist/windows-shortcuts.js +203 -0
- package/dist/windows-shortcuts.js.map +1 -0
- package/dist/workflow-templates/default.md +3 -0
- package/dist/ws-server.js.map +1 -1
- package/dist/yaml-shared-nodes.d.ts +25 -0
- package/dist/yaml-shared-nodes.js +185 -0
- package/dist/yaml-shared-nodes.js.map +1 -0
- package/launcher/agend-install.cjs +828 -0
- package/launcher/install-admission.cjs +4 -39
- package/launcher/postinstall.cjs +14 -12
- package/launcher/private-home.cjs +43 -0
- package/package.json +16 -13
- package/scripts/preinstall-guard.cjs +2 -5
- package/templates/windows-shortcuts.ps1 +181 -0
- package/launcher/old-updater-note.cjs +0 -48
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
// The Office view's art (fleet-office.js draws with it on a <canvas>). A skin draws a layout that fleet-office-model.js
|
|
2
|
+
// (desks) or fleet-office-zones.js (zones) made. Two skins are built in and draw everything procedurally — little
|
|
3
|
+
// pixel people, desks, lamps — so no art ships: "pixel" (the desks layout: a room per team, a desk per instance) and
|
|
4
|
+
// "studio" (the zones layout: work desks, a lounge, an alert corner and a nap corner; people walk to the area for their
|
|
5
|
+
// state). Every drawing call goes through the OfficeSkin interface below, so a skin pack (pictures from an artist,
|
|
6
|
+
// format v1 in fleet-office-pack.js) can replace any part; a part a pack does not supply falls back to the built-in
|
|
7
|
+
// drawing. No pack can be added yet (no upload): spriteSkin() and checkSkinPack() are the seam a later step plugs into.
|
|
8
|
+
//
|
|
9
|
+
// ── The interface ──
|
|
10
|
+
//
|
|
11
|
+
// @typedef {"working"|"idle"|"paused"|"needs"|"walk"} OfficePose (fleet-office-model.js POSES; "away" draws no one)
|
|
12
|
+
// @typedef {{ pal: OfficePalette, mode: "dark"|"light", labels: { lobby, closed, areas: { [area]: string } } }} OfficeEnv
|
|
13
|
+
// @typedef {{ name: string, label: string, state: string, pose: OfficePose|"away", light: "warn"|"danger"|null,
|
|
14
|
+
// lamp: boolean, sign: "closed"|null, coat: string, work: number, dim: boolean, match: boolean, free: boolean }} OfficeLook
|
|
15
|
+
// (one occupant; `free`: standing in a zone, not behind a desk cell)
|
|
16
|
+
// @typedef {object} OfficeSkin
|
|
17
|
+
// @property {string} id
|
|
18
|
+
// @property {object} [pack] a checked pack (fleet-office-pack.js); with `pack.stateZones` the zones layout is used
|
|
19
|
+
// @property {(ctx, L, env) => void} drawFloor desks: under everything — the stage and the corridors (L.edges)
|
|
20
|
+
// @property {(ctx, room, env) => void} drawRoom desks: a room's floor, wall and name (room: autoLayout's)
|
|
21
|
+
// @property {(ctx, desk, look, env) => void} drawDeskBack desks: behind the character — chair, desk top, screen, lamp
|
|
22
|
+
// @property {(ctx, desk, look, env) => void} drawDeskFront desks: in front — the desk's front, its sign, folders, name tag
|
|
23
|
+
// @property {(ctx, L, env) => void} [drawBackground] zones: the whole 1280×720 background, areas and their names
|
|
24
|
+
// @property {(ctx, item, active, ms, env) => void} [drawFurniture] zones: one furniture item (active: activeWhen holds)
|
|
25
|
+
// @property {(ctx, x, y, look, env) => void} [drawTag] zones: a name tag under feet at (x, y)
|
|
26
|
+
// @property {(ctx, desk, look, ms, env) => void} drawCharacter the occupant in its pose at time `ms` (0: still); in
|
|
27
|
+
// zones `desk` is the character's box at its current position (its feet at desk.seat)
|
|
28
|
+
// @property {(ctx, prop, ms, env) => void} drawProp a traffic item in the air: { kind, hue, x, y, t }
|
|
29
|
+
// @property {(ctx, x, y, text, env, lift?) => void} drawBubble a speech bubble whose tail points at (x, y), its box `lift` px higher
|
|
30
|
+
// The desks layout's back and front layers change only when the fleet does: the renderer keeps them as pictures and
|
|
31
|
+
// draws the characters, props and bubbles each frame. In zones the background is kept; furniture, people (walking
|
|
32
|
+
// along the pack's waypoints), tags, props and bubbles are drawn each frame, furniture by depth around the people.
|
|
33
|
+
import { frameAt, nameHash } from "./fleet-office-model.js";
|
|
34
|
+
import { CHAR_DEPTH, LOGICAL } from "./fleet-office-pack.js";
|
|
35
|
+
|
|
36
|
+
export { nameHash };
|
|
37
|
+
|
|
38
|
+
// ── The palette: the dashboard's tokens, read by the renderer; furniture keeps its own wood and metal ──
|
|
39
|
+
|
|
40
|
+
/** @typedef {{ bg, surface, surface2, border, text, text2, text3, ok, warn, danger, focus, fx: { task, send, report, broadcast } }} OfficePalette */
|
|
41
|
+
export const DEFAULT_PAL = {
|
|
42
|
+
bg: "#212121", surface: "#2f2f2f", surface2: "#3a3a3a", border: "#3d3d3d", text: "#ececec", text2: "#b4b4b4", text3: "#a3a3a3",
|
|
43
|
+
ok: "#4cc38a", warn: "#e3b341", danger: "#ff8a80", focus: "#7ab7ff", fx: { task: "#b794f6", send: "#2dd4bf", report: "#f472b6", broadcast: "#fb923c" },
|
|
44
|
+
};
|
|
45
|
+
/** Light or dark, from the page's own background token (whatever chose it: the person, the system, a theme). */
|
|
46
|
+
export function modeOf(pal) {
|
|
47
|
+
const m = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(String(pal && pal.bg).trim());
|
|
48
|
+
if (!m) return "dark";
|
|
49
|
+
const [r, g, b] = m.slice(1).map((x) => parseInt(x, 16));
|
|
50
|
+
return 0.2126 * r + 0.7152 * g + 0.0722 * b > 140 ? "light" : "dark";
|
|
51
|
+
}
|
|
52
|
+
const ROOM = {
|
|
53
|
+
dark: { floorA: "#2b313b", floorB: "#272c35", wall: "#363d49", wallLine: "#454e5d", lobbyA: "#2f3330", lobbyB: "#2b2f2c", corridor: "#2a2a2a" },
|
|
54
|
+
light: { floorA: "#efe7d8", floorB: "#e8dfcd", wall: "#ddd0b8", wallLine: "#cdbd9f", lobbyA: "#e6eadf", lobbyB: "#dfe4d7", corridor: "#ececec" },
|
|
55
|
+
};
|
|
56
|
+
const WOOD = { top: "#b07a45", edge: "#8a5a30", front: "#7a4f2a", leg: "#5c3b1f" };
|
|
57
|
+
const METAL = { frame: "#2b2f36", screenOff: "#3d4752", screenOn: "#9fe3ff", code: "#2d6f8f", pole: "#6b6f76", shade: "#d9b13b", chair: "#454b57", chairTop: "#545b69" };
|
|
58
|
+
const SKIN_TONES = ["#f2c9a0", "#e5b48a", "#c98e62", "#9a6440"];
|
|
59
|
+
const HAIR = ["#3b2a20", "#6b4423", "#c48a3a", "#1f1f24", "#7a4f8f", "#b9b9c2", "#a8452f"];
|
|
60
|
+
|
|
61
|
+
const P = 3; // one art pixel of a character, in CSS px
|
|
62
|
+
const CX = 44, TOP = 14; // the character's centre and head top in its desk cell
|
|
63
|
+
const px = (ctx, x, y, w, h, c) => { ctx.fillStyle = c; ctx.fillRect(Math.round(x), Math.round(y), Math.round(w), Math.round(h)); };
|
|
64
|
+
/** An art-pixel block of the character at desk `d`: column c, row r (0, 0 is the head's top-left), w×h art px. */
|
|
65
|
+
const art = (ctx, d, c, r, w, h, color, dy = 0) => px(ctx, d.x + CX - 5 * P + c * P, d.y + TOP + dy + r * P, w * P, h * P, color);
|
|
66
|
+
|
|
67
|
+
/** Text shortened to `max` px with an ellipsis (canvas measures; a grapheme cluster is not split). */
|
|
68
|
+
export function fitText(ctx, s, max) {
|
|
69
|
+
const str = String(s);
|
|
70
|
+
if (!ctx.measureText || ctx.measureText(str).width <= max) return str;
|
|
71
|
+
const chars = Array.from(str);
|
|
72
|
+
while (chars.length && ctx.measureText(`${chars.join("")}…`).width > max) chars.pop();
|
|
73
|
+
return `${chars.join("")}…`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ── The built-in pixel skin ──
|
|
77
|
+
|
|
78
|
+
function drawFloor(ctx, L, env) {
|
|
79
|
+
const r = ROOM[env.mode];
|
|
80
|
+
ctx.save();
|
|
81
|
+
ctx.strokeStyle = r.corridor;
|
|
82
|
+
ctx.lineWidth = 10;
|
|
83
|
+
ctx.lineCap = "round";
|
|
84
|
+
const at = new Map(L.waypoints.map((w) => [w.id, w]));
|
|
85
|
+
ctx.beginPath();
|
|
86
|
+
for (const [a, b] of L.edges) { const p = at.get(a), q = at.get(b); if (p && q) { ctx.moveTo(p.x, p.y); ctx.lineTo(q.x, q.y); } }
|
|
87
|
+
ctx.stroke();
|
|
88
|
+
ctx.restore();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function drawRoom(ctx, room, env) {
|
|
92
|
+
const r = ROOM[env.mode], { pal } = env, T = 16;
|
|
93
|
+
const [a, b] = room.lobby ? [r.lobbyA, r.lobbyB] : [r.floorA, r.floorB];
|
|
94
|
+
px(ctx, room.x, room.y, room.w, room.h, a);
|
|
95
|
+
for (let y = room.y + 26; y < room.y + room.h; y += T) for (let x = room.x + (((y - room.y) / T) % 2) * T; x < room.x + room.w; x += 2 * T) {
|
|
96
|
+
px(ctx, x, y, Math.min(T, room.x + room.w - x), Math.min(T, room.y + room.h - y), b);
|
|
97
|
+
}
|
|
98
|
+
px(ctx, room.x, room.y, room.w, 26, r.wall);
|
|
99
|
+
px(ctx, room.x, room.y + 24, room.w, 2, r.wallLine);
|
|
100
|
+
if (room.lobby) { // a plant by the lobby's wall
|
|
101
|
+
const x = room.x + room.w - 22, y = room.y + 4;
|
|
102
|
+
px(ctx, x + 3, y + 12, 10, 8, "#b5653a"); px(ctx, x, y + 4, 6, 8, "#3f8f4f"); px(ctx, x + 6, y, 5, 12, "#4fa65d"); px(ctx, x + 10, y + 5, 6, 7, "#3f8f4f");
|
|
103
|
+
}
|
|
104
|
+
ctx.save();
|
|
105
|
+
ctx.strokeStyle = pal.border;
|
|
106
|
+
ctx.lineWidth = 2;
|
|
107
|
+
ctx.strokeRect(room.x + 1, room.y + 1, room.w - 2, room.h - 2);
|
|
108
|
+
ctx.fillStyle = pal.text;
|
|
109
|
+
ctx.font = "600 12px system-ui, sans-serif";
|
|
110
|
+
ctx.textBaseline = "middle";
|
|
111
|
+
const name = room.lobby ? env.labels.lobby : room.name;
|
|
112
|
+
ctx.fillText(fitText(ctx, name, room.w - (room.lobby ? 48 : 52)), room.x + 10, room.y + 13);
|
|
113
|
+
if (!room.lobby) {
|
|
114
|
+
ctx.fillStyle = pal.text3;
|
|
115
|
+
ctx.font = "11px system-ui, sans-serif";
|
|
116
|
+
ctx.textAlign = "right";
|
|
117
|
+
ctx.fillText(String(room.desks.filter((d) => d.node).length), room.x + room.w - 10, room.y + 13);
|
|
118
|
+
}
|
|
119
|
+
ctx.restore();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function drawDeskBack(ctx, d, look) {
|
|
123
|
+
ctx.save();
|
|
124
|
+
if (look.dim) ctx.globalAlpha = 0.35;
|
|
125
|
+
// The chair (behind the character), the desk top, the screen, the lamp — and its light while it works.
|
|
126
|
+
px(ctx, d.x + 30, d.y + 26, 30, 26, METAL.chair); px(ctx, d.x + 30, d.y + 26, 30, 4, METAL.chairTop);
|
|
127
|
+
px(ctx, d.x + 8, d.y + 48, 80, 6, WOOD.top); px(ctx, d.x + 8, d.y + 53, 80, 1, WOOD.edge);
|
|
128
|
+
if (look.lamp) { // its light, from the shade down onto the desk
|
|
129
|
+
ctx.fillStyle = "rgba(255, 214, 102, 0.5)";
|
|
130
|
+
ctx.beginPath(); ctx.moveTo(d.x + 11, d.y + 31); ctx.lineTo(d.x + 19, d.y + 31); ctx.lineTo(d.x + 30, d.y + 49); ctx.lineTo(d.x + 8, d.y + 49); ctx.closePath(); ctx.fill();
|
|
131
|
+
}
|
|
132
|
+
px(ctx, d.x + 62, d.y + 28, 24, 18, METAL.frame); px(ctx, d.x + 64, d.y + 30, 20, 13, look.lamp ? METAL.screenOn : METAL.screenOff);
|
|
133
|
+
px(ctx, d.x + 72, d.y + 46, 4, 2, METAL.frame);
|
|
134
|
+
px(ctx, d.x + 11, d.y + 46, 8, 2, METAL.pole); px(ctx, d.x + 14, d.y + 31, 2, 15, METAL.pole);
|
|
135
|
+
px(ctx, d.x + 9, d.y + 26, 12, 5, look.lamp ? "#ffd86b" : METAL.shade);
|
|
136
|
+
ctx.restore();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function drawCharacter(ctx, d, look, ms, env) {
|
|
140
|
+
if (look.pose === "away") return;
|
|
141
|
+
const h = nameHash(look.name), skin = SKIN_TONES[h % SKIN_TONES.length], hair = HAIR[(h >>> 3) % HAIR.length];
|
|
142
|
+
const coat = look.coat, shirt = "#f4f1ea", eye = "#1d1d22";
|
|
143
|
+
const f = frameAt(ms, FRAMES[look.pose] || 1, FPS);
|
|
144
|
+
ctx.save();
|
|
145
|
+
if (look.dim) ctx.globalAlpha = 0.35;
|
|
146
|
+
const head = (dy, closed) => {
|
|
147
|
+
art(ctx, d, 2, 0, 6, 2, hair, dy); art(ctx, d, 2, 2, 6, 4, skin, dy); art(ctx, d, 2, 2, 1, 2, hair, dy); art(ctx, d, 7, 2, 1, 2, hair, dy);
|
|
148
|
+
if (closed) { art(ctx, d, 3, 4, 1, 0.34, eye, dy); art(ctx, d, 6, 4, 1, 0.34, eye, dy); }
|
|
149
|
+
else { art(ctx, d, 3, 3, 1, 1, eye, dy); art(ctx, d, 6, 3, 1, 1, eye, dy); }
|
|
150
|
+
art(ctx, d, 2.6, 4.6, 0.7, 0.5, "rgba(255, 120, 120, 0.45)", dy); art(ctx, d, 6.7, 4.6, 0.7, 0.5, "rgba(255, 120, 120, 0.45)", dy);
|
|
151
|
+
};
|
|
152
|
+
const body = (dy) => { art(ctx, d, 1, 6, 8, 5, coat, dy); art(ctx, d, 4, 6, 2, 2, shirt, dy); };
|
|
153
|
+
if (look.pose === "working") {
|
|
154
|
+
head(0, false); body(0);
|
|
155
|
+
// Typing: the hands take turns on the keyboard; the screen's lines change.
|
|
156
|
+
art(ctx, d, 0, 8, 1, 3, coat); art(ctx, d, 9, 8, 1, 3, coat);
|
|
157
|
+
art(ctx, d, 1, f % 2 ? 10.4 : 11, 2, 0.8, skin); art(ctx, d, 7, f % 2 ? 11 : 10.4, 2, 0.8, skin);
|
|
158
|
+
if (!look.free) { // the keyboard and the screen's lines (in zones the desk is furniture)
|
|
159
|
+
px(ctx, d.x + 30, d.y + 47, 28, 3, "#d8d8dc");
|
|
160
|
+
for (let i = 0; i < 3; i++) px(ctx, d.x + 66, d.y + 32 + i * 4, 4 + ((f + i * 3) % 4) * 3, 2, METAL.code);
|
|
161
|
+
}
|
|
162
|
+
} else if (look.pose === "idle") {
|
|
163
|
+
head(0, false); body(0);
|
|
164
|
+
// Tea: the cup comes up to sip on the second half of the loop; steam rises while it is down.
|
|
165
|
+
const up = f >= 2;
|
|
166
|
+
art(ctx, d, 0, 8, 1, 3, coat);
|
|
167
|
+
if (up) { art(ctx, d, 7, 6, 2, 2, coat); art(ctx, d, 6, 4.7, 2, 1.6, "#ffffff"); art(ctx, d, 6, 4.7, 2, 0.4, "#8a5a30"); }
|
|
168
|
+
else {
|
|
169
|
+
art(ctx, d, 9, 8, 1, 2, coat); art(ctx, d, 8.6, 9.6, 2, 1.8, "#ffffff"); art(ctx, d, 8.6, 9.6, 2, 0.4, "#8a5a30");
|
|
170
|
+
art(ctx, d, 9 + (f % 2) * 0.7, 7.6 - f * 0.5, 0.5, 0.8, "rgba(220, 220, 230, 0.7)");
|
|
171
|
+
}
|
|
172
|
+
} else if (look.pose === "paused") {
|
|
173
|
+
// Asleep: head down on the desk, arms folded under it; Zzz rising.
|
|
174
|
+
body(3); art(ctx, d, 1, 9.2, 8, 1.5, coat); head(4, true);
|
|
175
|
+
ctx.fillStyle = env.pal.text2;
|
|
176
|
+
ctx.font = "700 11px system-ui, sans-serif";
|
|
177
|
+
const zs = ms > 0 ? f + 1 : 3;
|
|
178
|
+
for (let i = 0; i < zs; i++) ctx.fillText(i ? "z" : "Z", d.x + CX + 12 + i * 7, d.y + TOP + 6 - i * 6);
|
|
179
|
+
} else if (look.pose === "needs") {
|
|
180
|
+
head(0, false); body(0);
|
|
181
|
+
// A hand up, waving; the call light over the head blinks (warn, or danger when it crashed).
|
|
182
|
+
art(ctx, d, 0, 8, 1, 3, coat); art(ctx, d, 9, 2 + f, 1, 6 - f, coat); art(ctx, d, 9 - f * 0.4, 1 + f, 1.4, 1.2, skin);
|
|
183
|
+
const on = ms <= 0 || f === 0, c = look.light === "danger" ? env.pal.danger : env.pal.warn;
|
|
184
|
+
ctx.globalAlpha = (look.dim ? 0.35 : 1) * (on ? 1 : 0.35);
|
|
185
|
+
if (on) { ctx.fillStyle = c; ctx.globalAlpha *= 0.25; ctx.beginPath(); ctx.arc(d.x + CX, d.y + 6, 9, 0, Math.PI * 2); ctx.fill(); ctx.globalAlpha = look.dim ? 0.35 : 1; }
|
|
186
|
+
px(ctx, d.x + CX - 4, d.y + 2, 8, 7, c); px(ctx, d.x + CX - 3, d.y + 9, 6, 2, METAL.pole);
|
|
187
|
+
} else {
|
|
188
|
+
// Walking: a bob, arms and legs swinging in turn.
|
|
189
|
+
const up = f ? -1 : 0;
|
|
190
|
+
head(up, false); body(up); art(ctx, d, 0, 7 + f * 0.5, 1, 3, coat, up); art(ctx, d, 9, 7.5 - f * 0.5, 1, 3, coat, up);
|
|
191
|
+
}
|
|
192
|
+
if (look.free && look.pose !== "paused") { // standing: legs (behind a desk cell they are hidden)
|
|
193
|
+
const step = look.pose === "walk" ? f : 0, legs = "#3a3f4b";
|
|
194
|
+
art(ctx, d, 2.5, 11, 2, step ? 1.6 : 2, legs); art(ctx, d, 5.5, 11, 2, step ? 2 : 1.6, legs);
|
|
195
|
+
}
|
|
196
|
+
ctx.restore();
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function drawDeskFront(ctx, d, look, env) {
|
|
200
|
+
const { pal } = env;
|
|
201
|
+
ctx.save();
|
|
202
|
+
if (look.dim) ctx.globalAlpha = 0.35;
|
|
203
|
+
if (!look.frontless) { // (a skin pack's desk front drew it already)
|
|
204
|
+
px(ctx, d.x + 10, d.y + 54, 76, 16, WOOD.front); px(ctx, d.x + 10, d.y + 54, 76, 2, WOOD.edge);
|
|
205
|
+
px(ctx, d.x + 12, d.y + 70, 4, 6, WOOD.leg); px(ctx, d.x + 80, d.y + 70, 4, 6, WOOD.leg);
|
|
206
|
+
}
|
|
207
|
+
// The work it was given (a delegation in progress): a folder each, up to three.
|
|
208
|
+
for (let i = 0; i < Math.min(3, look.work); i++) { px(ctx, d.x + 20 - i, d.y + 45 - i * 2, 12, 3, pal.fx.task); px(ctx, d.x + 20 - i, d.y + 44 - i * 2, 5, 1, pal.fx.task); }
|
|
209
|
+
if (look.sign === "closed") {
|
|
210
|
+
px(ctx, d.x + 30, d.y + 57, 36, 11, pal.surface2);
|
|
211
|
+
ctx.strokeStyle = pal.text3; ctx.lineWidth = 1; ctx.strokeRect(d.x + 30.5, d.y + 57.5, 35, 10);
|
|
212
|
+
ctx.fillStyle = pal.text2; ctx.font = "600 8px system-ui, sans-serif"; ctx.textAlign = "center"; ctx.textBaseline = "middle";
|
|
213
|
+
ctx.fillText(fitText(ctx, env.labels.closed, 32), d.x + 48, d.y + 63);
|
|
214
|
+
}
|
|
215
|
+
// The name tag.
|
|
216
|
+
ctx.fillStyle = pal.surface;
|
|
217
|
+
ctx.fillRect(d.x + 6, d.y + 78, d.w - 12, 16);
|
|
218
|
+
ctx.strokeStyle = look.match ? pal.focus : pal.border;
|
|
219
|
+
ctx.lineWidth = look.match ? 2 : 1;
|
|
220
|
+
ctx.strokeRect(d.x + 6.5, d.y + 78.5, d.w - 13, 15);
|
|
221
|
+
ctx.fillStyle = pal.text; ctx.font = "600 11px system-ui, sans-serif"; ctx.textAlign = "center"; ctx.textBaseline = "middle";
|
|
222
|
+
ctx.fillText(fitText(ctx, look.label, d.w - 18), d.x + d.w / 2, d.y + 86.5);
|
|
223
|
+
ctx.restore();
|
|
224
|
+
if (look.match) { ctx.save(); ctx.strokeStyle = pal.focus; ctx.lineWidth = 2; ctx.strokeRect(d.x + 2, d.y + 2, d.w - 4, d.h - 6); ctx.restore(); }
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const Q = 2; // a prop's art pixel
|
|
228
|
+
function drawProp(ctx, it, ms, env) {
|
|
229
|
+
const c = env.pal.fx[it.hue] || env.pal.fx.send, x0 = it.x - 8, y0 = it.y - 8 - Math.sin(Math.PI * it.t) * 10;
|
|
230
|
+
const b = (c2, r, w, h, col) => px(ctx, x0 + c2 * Q, y0 + r * Q, w * Q, h * Q, col);
|
|
231
|
+
ctx.save();
|
|
232
|
+
ctx.fillStyle = "rgba(0, 0, 0, 0.18)";
|
|
233
|
+
ctx.beginPath(); ctx.ellipse(it.x, it.y + 4, 7, 2.5, 0, 0, Math.PI * 2); ctx.fill();
|
|
234
|
+
if (it.hue === "task") { b(0, 0, 4, 2, c); b(0, 1, 8, 6, c); b(0, 2, 8, 1, "rgba(255, 255, 255, 0.35)"); }
|
|
235
|
+
else if (it.hue === "report") { b(1, 0, 6, 8, "#fbfbfb"); b(1, 0, 6, 1, c); b(2, 4, 1, 1, c); b(3, 5, 1, 1, c); b(4, 4, 1, 1, c); b(5, 3, 1, 1, c); }
|
|
236
|
+
else if (it.hue === "broadcast") { b(0, 3, 2, 2, c); b(2, 2, 2, 4, c); b(4, 1, 2, 6, c); if (frameAt(ms, 2, 6)) { b(7, 1, 1, 2, c); b(7, 5, 1, 2, c); } else b(7, 3, 1, 2, c); }
|
|
237
|
+
else { b(0, 1, 8, 6, c); for (const [cc, r] of [[0, 1], [1, 2], [2, 3], [3, 4], [4, 4], [5, 3], [6, 2], [7, 1]]) b(cc, r, 1, 1, "#ffffff"); }
|
|
238
|
+
ctx.restore();
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** Frames per pose and the loop's speed (the built-in strips). */
|
|
242
|
+
export const FRAMES = { working: 4, idle: 4, paused: 3, needs: 2, walk: 2 };
|
|
243
|
+
export const FPS = 4;
|
|
244
|
+
|
|
245
|
+
const BUBBLE_FONT = "600 11px system-ui, sans-serif";
|
|
246
|
+
/**
|
|
247
|
+
* The box a speech bubble with its tail at (x, y) takes for `text` (its tail excluded): what drawBubble draws, and what
|
|
248
|
+
* the Office places so no two overlap (#2431: two neighbours' bubbles covered each other on a phone).
|
|
249
|
+
*/
|
|
250
|
+
export function bubbleBox(ctx, x, y, text, lift = 0) {
|
|
251
|
+
ctx.save();
|
|
252
|
+
ctx.font = BUBBLE_FONT;
|
|
253
|
+
const t = fitText(ctx, text, 150), w = Math.ceil((ctx.measureText ? ctx.measureText(t).width : t.length * 6) + 14), h = 19;
|
|
254
|
+
ctx.restore();
|
|
255
|
+
const bx = Math.round(x - 10), by = Math.round(y - h - 6 - lift);
|
|
256
|
+
return { x: bx, y: by, w, h, text: t };
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/** A speech bubble, its tail at (x, y): short words on light paper in either theme; `lift` raises the box (its tail longer). */
|
|
260
|
+
function drawBubble(ctx, x, y, text, env, lift = 0) {
|
|
261
|
+
if (!text) return;
|
|
262
|
+
const { x: bx, y: by, w, h, text: t } = bubbleBox(ctx, x, y, text, lift);
|
|
263
|
+
ctx.save();
|
|
264
|
+
ctx.font = BUBBLE_FONT;
|
|
265
|
+
ctx.fillStyle = "#fffdf6"; ctx.strokeStyle = env.mode === "light" ? "rgba(0, 0, 0, 0.35)" : "rgba(0, 0, 0, 0.6)"; ctx.lineWidth = 1;
|
|
266
|
+
ctx.beginPath(); ctx.moveTo(bx + 4, by); ctx.lineTo(bx + w - 4, by); ctx.lineTo(bx + w, by + 4); ctx.lineTo(bx + w, by + h - 4); ctx.lineTo(bx + w - 4, by + h);
|
|
267
|
+
ctx.lineTo(x + 6, by + h); ctx.lineTo(x, y); ctx.lineTo(x + 1, by + h); ctx.lineTo(bx + 4, by + h); ctx.lineTo(bx, by + h - 4); ctx.lineTo(bx, by + 4); ctx.closePath();
|
|
268
|
+
ctx.fill(); ctx.stroke();
|
|
269
|
+
ctx.fillStyle = "#1d1d22"; ctx.textBaseline = "middle"; ctx.textAlign = "left";
|
|
270
|
+
ctx.fillText(t, bx + 7, by + h / 2 + 0.5);
|
|
271
|
+
ctx.restore();
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/** Zones: a name tag under someone's feet at (x, y). */
|
|
275
|
+
function drawTag(ctx, x, y, look, env) {
|
|
276
|
+
const { pal } = env;
|
|
277
|
+
ctx.save();
|
|
278
|
+
if (look.dim) ctx.globalAlpha = 0.35;
|
|
279
|
+
ctx.font = "600 10px system-ui, sans-serif";
|
|
280
|
+
const t = fitText(ctx, look.label, 84), w = Math.ceil((ctx.measureText ? ctx.measureText(t).width : t.length * 6) + 10);
|
|
281
|
+
ctx.fillStyle = pal.surface; ctx.fillRect(Math.round(x - w / 2), y + 3, w, 14);
|
|
282
|
+
ctx.strokeStyle = look.match ? pal.focus : pal.border; ctx.lineWidth = look.match ? 2 : 1; ctx.strokeRect(Math.round(x - w / 2) + 0.5, y + 3.5, w - 1, 13);
|
|
283
|
+
ctx.fillStyle = pal.text; ctx.textAlign = "center"; ctx.textBaseline = "middle"; ctx.fillText(t, x, y + 10.5);
|
|
284
|
+
ctx.restore();
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/** @type {OfficeSkin} */
|
|
288
|
+
export const pixelSkin = { id: "pixel", drawFloor, drawRoom, drawDeskBack, drawCharacter, drawDeskFront, drawProp, drawBubble, drawTag };
|
|
289
|
+
|
|
290
|
+
// ── The built-in studio: the zones layout, drawn procedurally ──
|
|
291
|
+
|
|
292
|
+
const grid = (xs, ys) => ys.flatMap((y) => xs.map((x) => ({ x, y })));
|
|
293
|
+
const HALL_X = 676;
|
|
294
|
+
const STUDIO_AREAS = {
|
|
295
|
+
desks: { name: "desks", rect: { x: 24, y: 64, w: 632, h: 448 }, seats: grid([104, 248, 392, 536], [190, 320, 450]) },
|
|
296
|
+
lounge: { name: "lounge", rect: { x: 696, y: 64, w: 560, h: 304 }, seats: grid([748, 824, 900, 976, 1052, 1128, 1204], [250, 340]) },
|
|
297
|
+
alert: { name: "alert", rect: { x: 696, y: 392, w: 300, h: 304 }, seats: grid([744, 814, 884], [530, 600, 670]) },
|
|
298
|
+
nap: { name: "nap", rect: { x: 1020, y: 392, w: 236, h: 304 }, seats: grid([1084, 1184], [530, 600, 670]) },
|
|
299
|
+
};
|
|
300
|
+
/** The studio's walkable graph: an aisle under each row of seats, joined to the hall that runs down the middle. */
|
|
301
|
+
function studioGraph(areas) {
|
|
302
|
+
const waypoints = [], edges = [], hall = new Set([380, 704]);
|
|
303
|
+
for (const a of Object.values(areas)) {
|
|
304
|
+
for (const y of [...new Set(a.seats.map((s) => s.y))]) {
|
|
305
|
+
const ay = y + 22, xs = [...new Set([...a.seats.filter((s) => s.y === y).map((s) => s.x), HALL_X])].sort((p, q) => p - q);
|
|
306
|
+
hall.add(ay);
|
|
307
|
+
const ids = xs.map((x) => { const id = `${a.name}-${ay}-${x}`; waypoints.push({ id, x, y: ay }); return id; });
|
|
308
|
+
ids.forEach((id, k) => { if (k) edges.push([ids[k - 1], id]); });
|
|
309
|
+
const join = ids[xs.indexOf(HALL_X)];
|
|
310
|
+
edges.push([join, `hall-${ay}`]);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
const ys = [...hall].sort((p, q) => p - q);
|
|
314
|
+
ys.forEach((y, k) => { waypoints.push({ id: `hall-${y}`, x: HALL_X, y }); if (k) edges.push([`hall-${ys[k - 1]}`, `hall-${y}`]); });
|
|
315
|
+
return { waypoints, edges };
|
|
316
|
+
}
|
|
317
|
+
const STUDIO_FURNITURE = [
|
|
318
|
+
{ id: "board", shape: "board", x: 340, y: 100, depth: 5 },
|
|
319
|
+
{ id: "rack-work", shape: "rack", tone: "ok", x: 610, y: 160, depth: 6, activeWhen: ["working"] },
|
|
320
|
+
...STUDIO_AREAS.desks.seats.map((s, i) => ({ id: `desk-${i}`, shape: "desk", x: s.x, y: s.y, depth: 1100 })),
|
|
321
|
+
{ id: "sofa", shape: "sofa", x: 900, y: 150, depth: 10 },
|
|
322
|
+
{ id: "coffee", shape: "coffee", x: 1210, y: 130, depth: 20, activeWhen: ["idle"] },
|
|
323
|
+
{ id: "plant-1", shape: "plant", x: 724, y: 120, depth: 20 }, { id: "plant-2", shape: "plant", x: 40, y: 500, depth: 20 },
|
|
324
|
+
{ id: "rack-alert", shape: "rack", tone: "danger", x: 960, y: 460, depth: 900, activeWhen: ["needs", "stuck", "crashed"] },
|
|
325
|
+
{ id: "bug", shape: "bug", x: 760, y: 450, depth: 950, activeWhen: ["crashed"] },
|
|
326
|
+
...STUDIO_AREAS.nap.seats.map((s, i) => ({ id: `bag-${i}`, shape: "beanbag", x: s.x, y: s.y + 4, depth: 990 })),
|
|
327
|
+
].sort((a, b) => a.depth - b.depth);
|
|
328
|
+
/** The studio's pack: the same shape as a checked one (fleet-office-pack.js), furniture by `shape` instead of sprites. */
|
|
329
|
+
export const STUDIO_PACK = {
|
|
330
|
+
format: 1, id: "studio", scale: 1, areas: STUDIO_AREAS, door: { x: HALL_X, y: 704 }, furniture: STUDIO_FURNITURE, ...studioGraph(STUDIO_AREAS),
|
|
331
|
+
stateZones: { working: "desks", idle: "lounge", needs: "alert", crashed: "alert", stuck: "alert", paused: "nap", stopped: "nap", default: "lounge" },
|
|
332
|
+
characters: {}, byInstance: {}, props: {}, bubbles: {},
|
|
333
|
+
};
|
|
334
|
+
const ZONE_FLOOR = {
|
|
335
|
+
dark: { desks: ["#2b313b", "#272c35"], lounge: ["#2c3430", "#28302c"], alert: ["#3a2c2e", "#35282a"], nap: ["#302c3a", "#2c2835"], hall: "#262626" },
|
|
336
|
+
light: { desks: ["#efe7d8", "#e8dfcd"], lounge: ["#e3ecdf", "#dce6d7"], alert: ["#f3e1df", "#eed9d6"], nap: ["#e8e3f1", "#e1dbec"], hall: "#ececec" },
|
|
337
|
+
};
|
|
338
|
+
function drawBackground(ctx, L, env) {
|
|
339
|
+
const { pal } = env, F = ZONE_FLOOR[env.mode], T = 24;
|
|
340
|
+
px(ctx, 0, 0, LOGICAL.w, LOGICAL.h, F.hall);
|
|
341
|
+
for (const a of Object.values(L.areas)) {
|
|
342
|
+
const [c1, c2] = F[a.name] || F.desks, r = a.rect;
|
|
343
|
+
px(ctx, r.x, r.y, r.w, r.h, c1);
|
|
344
|
+
for (let y = r.y; y < r.y + r.h; y += T) for (let x = r.x + (((y - r.y) / T) % 2) * T; x < r.x + r.w; x += 2 * T) px(ctx, x, y, Math.min(T, r.x + r.w - x), Math.min(T, r.y + r.h - y), c2);
|
|
345
|
+
ctx.save();
|
|
346
|
+
ctx.strokeStyle = pal.border; ctx.lineWidth = 2; ctx.strokeRect(r.x + 1, r.y + 1, r.w - 2, r.h - 2);
|
|
347
|
+
ctx.fillStyle = pal.text; ctx.font = "600 16px system-ui, sans-serif"; ctx.textBaseline = "top"; ctx.textAlign = "left";
|
|
348
|
+
ctx.fillText(fitText(ctx, env.labels.areas[a.name] || a.name, r.w - 60), r.x + 12, r.y + 10);
|
|
349
|
+
const crowd = L.crowd && L.crowd.get(a.name);
|
|
350
|
+
if (crowd) { ctx.fillStyle = pal.text2; ctx.textAlign = "right"; ctx.fillText(`+${crowd}`, r.x + r.w - 12, r.y + 10); }
|
|
351
|
+
ctx.restore();
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
function drawFurniture(ctx, f, active, ms, env) {
|
|
355
|
+
const x = f.x, y = f.y;
|
|
356
|
+
switch (f.shape) {
|
|
357
|
+
case "desk":
|
|
358
|
+
px(ctx, x - 40, y - 24, 80, 6, WOOD.top); px(ctx, x - 38, y - 18, 76, 18, WOOD.front); px(ctx, x - 38, y - 18, 76, 2, WOOD.edge);
|
|
359
|
+
px(ctx, x + 12, y - 44, 24, 18, METAL.frame); px(ctx, x + 14, y - 42, 20, 13, METAL.screenOn); px(ctx, x + 22, y - 26, 4, 2, METAL.frame);
|
|
360
|
+
break;
|
|
361
|
+
case "board":
|
|
362
|
+
px(ctx, x - 90, y - 26, 180, 52, "#f4f4f0"); px(ctx, x - 92, y - 28, 184, 3, "#8a8f98"); px(ctx, x - 92, y + 25, 184, 3, "#8a8f98");
|
|
363
|
+
for (let i = 0; i < 4; i++) px(ctx, x - 78, y - 16 + i * 10, 40 + ((i * 37) % 90), 3, ["#4b8bf4", "#d97757", "#3fa58c", "#9b6bff"][i]);
|
|
364
|
+
break;
|
|
365
|
+
case "rack": {
|
|
366
|
+
px(ctx, x - 22, y - 70, 44, 90, "#2b2f36"); px(ctx, x - 20, y - 68, 40, 86, "#363b44");
|
|
367
|
+
const on = env.pal[f.tone] || env.pal.ok;
|
|
368
|
+
for (let r = 0; r < 6; r++) for (let c = 0; c < 3; c++) {
|
|
369
|
+
const lit = active && (ms <= 0 || frameAt(ms + (r * 3 + c) * 170, 2, 3) === 0);
|
|
370
|
+
px(ctx, x - 14 + c * 10, y - 60 + r * 13, 6, 4, lit ? on : "#4a505a");
|
|
371
|
+
}
|
|
372
|
+
break;
|
|
373
|
+
}
|
|
374
|
+
case "sofa":
|
|
375
|
+
px(ctx, x - 110, y - 30, 220, 26, "#3f7286"); px(ctx, x - 118, y - 14, 236, 34, "#4f8aa1"); px(ctx, x - 118, y - 20, 16, 40, "#3f7286"); px(ctx, x + 102, y - 20, 16, 40, "#3f7286");
|
|
376
|
+
break;
|
|
377
|
+
case "coffee":
|
|
378
|
+
px(ctx, x - 18, y - 34, 36, 50, "#5a5f69"); px(ctx, x - 14, y - 28, 28, 12, "#2b2f36"); px(ctx, x - 6, y + 2, 12, 10, "#ffffff");
|
|
379
|
+
if (active) for (let i = 0; i < 3; i++) { const k = frameAt(ms + i * 300, 4, 4); px(ctx, x - 4 + ((i + k) % 2) * 4, y - 6 - i * 7 - k, 2, 4, "rgba(230, 230, 236, 0.7)"); }
|
|
380
|
+
break;
|
|
381
|
+
case "plant":
|
|
382
|
+
px(ctx, x - 9, y, 18, 16, "#b5653a"); px(ctx, x - 14, y - 18, 10, 18, "#3f8f4f"); px(ctx, x - 4, y - 26, 9, 26, "#4fa65d"); px(ctx, x + 5, y - 16, 10, 16, "#3f8f4f");
|
|
383
|
+
break;
|
|
384
|
+
case "bug": {
|
|
385
|
+
const wob = active && ms > 0 ? Math.round(Math.sin(ms / 160) * 26) : 0, c = active ? env.pal.danger : "#6b6f76";
|
|
386
|
+
const bx = x + wob;
|
|
387
|
+
px(ctx, bx - 9, y - 6, 18, 12, c); px(ctx, bx - 5, y - 11, 10, 6, c); px(ctx, bx - 1, y - 6, 2, 12, "#1d1d22");
|
|
388
|
+
for (const k of [-1, 1]) for (const r of [-4, 0, 4]) px(ctx, bx + k * 11 - (k < 0 ? 3 : 0), y + r, 3, 2, "#1d1d22");
|
|
389
|
+
break;
|
|
390
|
+
}
|
|
391
|
+
case "beanbag":
|
|
392
|
+
px(ctx, x - 26, y - 14, 52, 20, "#7a5a8c"); px(ctx, x - 22, y - 20, 44, 8, "#8d6aa0");
|
|
393
|
+
break;
|
|
394
|
+
default:
|
|
395
|
+
break;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
/** @type {OfficeSkin} */
|
|
399
|
+
export const studioSkin = { ...pixelSkin, id: "studio", pack: STUDIO_PACK, drawBackground, drawFurniture };
|
|
400
|
+
|
|
401
|
+
// ── Skin packs (the seam; nothing registers one yet) ──
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* An OfficeSkin from a checked pack (fleet-office-pack.js checkSkinPack) and its loaded pictures (`images`: src → a
|
|
405
|
+
* drawable image). What it lacks, or a picture not loaded, is drawn by the built-in skins.
|
|
406
|
+
*/
|
|
407
|
+
export function spriteSkin(pack, images, base = pixelSkin) {
|
|
408
|
+
const img = (src) => (src && images.get(src)) || null;
|
|
409
|
+
const strip = (ctx, st, ms, x, y, frame = null) => {
|
|
410
|
+
const im = img(st && st.src);
|
|
411
|
+
if (!im) return false;
|
|
412
|
+
const f = frame ?? frameAt(ms, st.frames, st.fps), s = pack.scale;
|
|
413
|
+
ctx.save();
|
|
414
|
+
ctx.imageSmoothingEnabled = false;
|
|
415
|
+
ctx.drawImage(im, f * st.w, 0, st.w, st.h, Math.round(x - st.ax * s), Math.round(y - st.ay * s), st.w * s, st.h * s);
|
|
416
|
+
ctx.restore();
|
|
417
|
+
return true;
|
|
418
|
+
};
|
|
419
|
+
return {
|
|
420
|
+
...base,
|
|
421
|
+
id: pack.id,
|
|
422
|
+
pack,
|
|
423
|
+
drawRoom(ctx, room, env) {
|
|
424
|
+
const floor = img(pack.room.floor), wall = img(pack.room.wall);
|
|
425
|
+
if (!floor) { base.drawRoom(ctx, room, env); return; }
|
|
426
|
+
ctx.save();
|
|
427
|
+
ctx.imageSmoothingEnabled = false;
|
|
428
|
+
const pat = ctx.createPattern(floor, "repeat");
|
|
429
|
+
if (pat) { ctx.fillStyle = pat; ctx.fillRect(room.x, room.y, room.w, room.h); }
|
|
430
|
+
if (wall) ctx.drawImage(wall, room.x, room.y, room.w, 26);
|
|
431
|
+
ctx.fillStyle = env.pal.text; ctx.font = "600 12px system-ui, sans-serif"; ctx.textBaseline = "middle";
|
|
432
|
+
ctx.fillText(fitText(ctx, room.lobby ? env.labels.lobby : room.name, room.w - 20), room.x + 10, room.y + 13);
|
|
433
|
+
ctx.restore();
|
|
434
|
+
},
|
|
435
|
+
drawDeskBack(ctx, d, look, env) {
|
|
436
|
+
const im = img(look.lamp && pack.desk.lit ? pack.desk.lit : pack.desk.back);
|
|
437
|
+
if (!im) { base.drawDeskBack(ctx, d, look, env); return; }
|
|
438
|
+
ctx.save(); ctx.imageSmoothingEnabled = false; if (look.dim) ctx.globalAlpha = 0.35; ctx.drawImage(im, d.x, d.y, d.w, d.h); ctx.restore();
|
|
439
|
+
},
|
|
440
|
+
drawDeskFront(ctx, d, look, env) {
|
|
441
|
+
const im = img(pack.desk.front);
|
|
442
|
+
if (im) { ctx.save(); ctx.imageSmoothingEnabled = false; if (look.dim) ctx.globalAlpha = 0.35; ctx.drawImage(im, d.x, d.y, d.w, d.h); ctx.restore(); }
|
|
443
|
+
// The name tag, the sign and the folders are words and counts: always drawn here.
|
|
444
|
+
base.drawDeskFront(ctx, d, { ...look, frontless: !!im }, env);
|
|
445
|
+
},
|
|
446
|
+
drawBackground(ctx, L, env) {
|
|
447
|
+
const im = img(pack.background);
|
|
448
|
+
if (!im) { drawBackground(ctx, L, env); return; }
|
|
449
|
+
ctx.save(); ctx.imageSmoothingEnabled = false; ctx.drawImage(im, 0, 0, LOGICAL.w, LOGICAL.h); ctx.restore();
|
|
450
|
+
},
|
|
451
|
+
drawFurniture(ctx, f, active, ms, env) {
|
|
452
|
+
if (f.shape) { drawFurniture(ctx, f, active, ms, env); return; }
|
|
453
|
+
// Active: its strip (or activeSprite) plays; otherwise its first frame holds.
|
|
454
|
+
if (active) strip(ctx, f.activeSprite || f.sprite, ms, f.x, f.y);
|
|
455
|
+
else strip(ctx, f.sprite, 0, f.x, f.y, 0);
|
|
456
|
+
},
|
|
457
|
+
drawCharacter(ctx, d, look, ms, env) {
|
|
458
|
+
if (look.pose === "away") return;
|
|
459
|
+
const set = pack.characters[pack.byInstance[look.name]] || pack.characters.default;
|
|
460
|
+
ctx.save();
|
|
461
|
+
if (look.dim) ctx.globalAlpha = 0.35;
|
|
462
|
+
const done = !!set && strip(ctx, set[look.pose] || set.idle, ms, d.seat.x, d.seat.y);
|
|
463
|
+
ctx.restore();
|
|
464
|
+
if (!done) base.drawCharacter(ctx, d, look, ms, env);
|
|
465
|
+
},
|
|
466
|
+
drawProp(ctx, it, ms, env) { if (!strip(ctx, pack.props[it.hue], ms, it.x, it.y)) base.drawProp(ctx, it, ms, env); },
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/** The skins this page has: the built-in ones (a pack would be added here once loaded). */
|
|
471
|
+
export const SKINS = new Map([["pixel", pixelSkin], ["studio", studioSkin]]);
|
|
472
|
+
export const skinFor = (id) => SKINS.get(id) || pixelSkin;
|
|
473
|
+
/** The people's depth in zones (fleet-office-pack.js). */
|
|
474
|
+
export { CHAR_DEPTH };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// The Office view's data, behind one small seam (fleet-office.js uses only these calls):
|
|
2
|
+
// - the offices people made: the host's (GET / PUT /ui/offices, src/web-office-store.ts — one list for every viewer);
|
|
3
|
+
// what comes back is checked again here (fleet-office-model.js officesOk), never trusted;
|
|
4
|
+
// - this browser's own choices (localStorage; blocked storage: this page only, as the canvas's Canvas/List): which
|
|
5
|
+
// office is shown, the auto office's member filter, and its style (skin).
|
|
6
|
+
// TODO(office editor): adding and renaming offices, assigning people, dragging seats and drawing paths call
|
|
7
|
+
// saveOffices() with the whole list and the rev they read (a change in between answers 409).
|
|
8
|
+
import { AUTO_ID, filterOk, officesOk } from "./fleet-office-model.js";
|
|
9
|
+
|
|
10
|
+
const CHOICE_KEY = "agend_org_office", FILTER_KEY = "agend_org_office_filter", SKIN_KEY = "agend_org_office_skin";
|
|
11
|
+
|
|
12
|
+
/** `fetch`: the caller's (a lease's, so an answer after the person moved on is dropped); `storage`: default localStorage. */
|
|
13
|
+
export function createOfficeStore({ fetch: get = globalThis.fetch, storage } = {}) {
|
|
14
|
+
const st = () => { try { return storage || globalThis.localStorage || null; } catch { return null; } };
|
|
15
|
+
const read = (k) => { try { const s = st(); return s ? s.getItem(k) : null; } catch { return null; } };
|
|
16
|
+
const write = (k, v) => { try { const s = st(); if (s) s.setItem(k, v); } catch { /* this page only */ } };
|
|
17
|
+
const headers = { "Content-Type": "application/json" };
|
|
18
|
+
return {
|
|
19
|
+
/** { rev, offices } from the host; null when it could not be read (no offices shown but the auto one). */
|
|
20
|
+
async offices() {
|
|
21
|
+
try {
|
|
22
|
+
const r = await get("/ui/offices", { method: "GET", headers });
|
|
23
|
+
if (!r || !r.ok) return null;
|
|
24
|
+
const d = await r.json();
|
|
25
|
+
return { rev: Number.isSafeInteger(d && d.rev) ? d.rev : 0, offices: officesOk(d && d.offices) };
|
|
26
|
+
} catch { return null; }
|
|
27
|
+
},
|
|
28
|
+
/**
|
|
29
|
+
* Replace the host's list (an admin session; `rev`: the one read — required: the host refuses a save without it,
|
|
30
|
+
* so two editors never overwrite each other unseen). { ok, rev, offices } or { ok: false, status, error }.
|
|
31
|
+
*/
|
|
32
|
+
async saveOffices(list, rev) {
|
|
33
|
+
if (!Number.isSafeInteger(rev)) return { ok: false, status: 0, error: "offices_rev_required" };
|
|
34
|
+
try {
|
|
35
|
+
const r = await get("/ui/offices", { method: "PUT", headers, body: JSON.stringify({ offices: list, rev }) });
|
|
36
|
+
const d = await r.json().catch(() => ({}));
|
|
37
|
+
return r.ok ? { ok: true, rev: d.rev, offices: officesOk(d.offices) } : { ok: false, status: r.status, error: d.error || "offices_failed" };
|
|
38
|
+
} catch { return { ok: false, status: 0, error: "offices_failed" }; }
|
|
39
|
+
},
|
|
40
|
+
/** The office shown here: an id (one the host no longer has falls back to the auto office where it is used). */
|
|
41
|
+
choice: () => { const v = read(CHOICE_KEY); return typeof v === "string" && v && v.length <= 40 ? v : AUTO_ID; },
|
|
42
|
+
saveChoice: (id) => write(CHOICE_KEY, String(id)),
|
|
43
|
+
filter: () => { const s = read(FILTER_KEY); try { return filterOk(s ? JSON.parse(s) : null); } catch { return filterOk(null); } },
|
|
44
|
+
saveFilter: (f) => write(FILTER_KEY, JSON.stringify(filterOk(f))),
|
|
45
|
+
/** The whole fleet's style here: a skin id ("pixel": desks, "studio": zones); an unknown one is the default where used. */
|
|
46
|
+
skin: () => { const v = read(SKIN_KEY); return typeof v === "string" && /^[A-Za-z0-9_-]{1,40}$/.test(v) ? v : "pixel"; },
|
|
47
|
+
saveSkin: (id) => write(SKIN_KEY, String(id)),
|
|
48
|
+
};
|
|
49
|
+
}
|