Skip to content

fix(viewer): guide users to load the model before a BCF's viewpoints resolve (#4099) - #4133

Open
BIMvoice wants to merge 3 commits into
mainfrom
fix-4099-bcf-load-order-guidance
Open

fix(viewer): guide users to load the model before a BCF's viewpoints resolve (#4099)#4133
BIMvoice wants to merge 3 commits into
mainfrom
fix-4099-bcf-load-order-guidance

Conversation

@BIMvoice

@BIMvoice BIMvoice commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

Refs #4099 — load-order guidance is done; the discoverability half (landing-page/README framing naming BCF viewing as a standalone use case) is intentionally left to the maintainer, not implemented here.

Context

The issue has two halves. This PR addresses the concrete, substantive one (load order) and does the defensible low-risk part of the discoverability half; it deliberately leaves the rest of discoverability to the maintainer.

(a) Load-order guidance — implemented

A BCF's topics reference GlobalIds in the model they were captured from. readBCF never checks this, so importing a BCF succeeds regardless of what — if anything — is loaded in the viewport. With no model loaded, every viewpoint then silently fails to resolve later (nothing to zoom to or select), with no error explaining why.

  • BCFPanel.tsx's handleImportFile now calls warnIfNoModelLoaded(models.size) right after a successful import, which shows a toast.info ("BCF imported. Load the model this BCF refers to, to view its topics' viewpoints in 3D.") when no model is loaded. No toast when a model is already loaded (normal path untouched).
  • Separately, dropping a .bcfzip file directly onto the main viewport used to do nothing at all: .bcfzip matches neither isSupportedModelFile (it's not a model) nor the .zip branch of the unsupported-format explainer — the string "bcfzip" has no literal dot before "zip", so endsWith('.zip') is false. This is exactly the confusion quoted in the issue ("Maybe it should be unzipped? Isn't it .bcf format?"). describeUnsupportedFormat now recognizes .bcf/.bcfzip and names the fix: use the BCF panel's Import button, load the model first if you haven't.
  • docs/guide/bcf.md's Viewer Integration section claimed "Drag and drop a .bcf or .bcfzip file" works. It doesn't — there is no drop handler in BCFPanel.tsx or its subcomponents (verified: no onDrop/DragEvent/dataTransfer anywhere in that tree). Corrected to describe the actual Import-button flow and the load-order requirement.

Refactor note

describeUnsupportedFormat moved out of pointCloudIngest.ts into a new sibling module unsupportedFormat.tspointCloudIngest.ts was sitting at its module-size budget (line-count, zero headroom) and this function has no dependency on the point-cloud pipeline it lived next to. ViewportContainer.tsx's import updated accordingly.

Tests + mutation

  • apps/viewer/src/hooks/ingest/unsupportedFormat.bcf.test.ts — asserts .bcf/.bcfzip get a BCF-specific message, and don't fall through to the generic "extract first" ZIP message.
  • apps/viewer/src/components/viewer/BCFPanel.import-load-order.test.tsx — drives the real BCFPanel component (real readBCF/writeBCF round trip, not mocked) via its actual file-input change event, against an empty store: asserts exactly one toast.info guidance call, and separately asserts no toast when a model is already loaded (regression check on the normal path).
  • Mutated both fixes out (removed the toast call; removed the .bcf/.bcfzip branch) and confirmed all 5 new/touched assertions go RED, then restored and confirmed GREEN.

(b) Discoverability — not unilaterally redesigned

The issue's core observation — people ask for a free BCF viewer without knowing ifc-lite is one — is a landing-page/marketing/positioning question. That's the maintainer's call, and I have not touched any landing-page copy or invented product claims.

What I did verify and confirm is already true:

  • docs/guide/bcf.md already states plainly, in its first paragraph, that @ifc-lite/bcf implements BCF 2.1 and 3.0 — confirmed against packages/bcf/src/writer.ts, which branches on version: '2.1' | '3.0' throughout (writeVersionFile, writeProjectFile, markup-writing) with version-specific schema handling for both.
  • The same doc's "Viewer Integration" section already describes browsing topics, navigating viewpoints, and rendering markers in 3D (packages/bcf's computeMarkerPositions + DOM renderer, wired into BCFOverlay).
  • docs/guide/bcf.md is already linked from mkdocs.yml's nav (User Guide > BCF Collaboration), and README.md already links to it and lists "BCF topic tracking" as a feature.

So the docs-side ask in the issue ("state clearly that the viewer opens BCF 2.1/3.0 and renders topics with viewpoints, and make sure the doc is discoverable") was already true before this PR, apart from the drag-and-drop overclaim fixed in (a) above.

Suggestion for the maintainer, not implemented here: if there's appetite to be the visible answer to "free BCF viewer" queries, that likely means landing-page copy or README framing naming BCF viewing as a standalone use case — a product/positioning decision I've left alone.

#4097 conflict check

Checked PR #4097 (BCF panel "issues" → "topics" terminology rename) before starting. It is already merged into upstream/main (commit f48b803ee), which this branch is based on — so there's no live conflict to manage. None of my changes touch renamed strings; the panel heading, registry title, and BCFPanel's topic vocabulary are all untouched by this PR.

Gates

  • node scripts/check-module-size.mjs — OK, 0 new over budget (both edited files brought back to/under their line budgets via the extraction above)
  • node scripts/check-test-wiring.mjs — OK
  • node scripts/check-source-text-assertions.mjs — OK, 0 new
  • turbo run typecheck --filter=@ifc-lite/viewer — 41/41 tasks successful
  • turbo run test --filter=@ifc-lite/viewer — 7146 tests, 7140 pass, 0 fail, 6 skipped (5 of the 7146 are the new tests added by this PR; no regressions)

What I ran vs. skipped

Ran the full viewer suite via turbo (not pnpm --filter) per AGENTS.md. Skipped running the full monorepo test matrix (other packages untouched by this diff) — only @ifc-lite/viewer files changed plus docs.

git status --porcelain is clean.

…resolve (#4099)

A BCF's topics reference GlobalIds in the model they were captured from,
which readBCF never checks — importing succeeds regardless of what (if
anything) is loaded, so a BCF's viewpoints silently fail to resolve later
with nothing to explain why. BCFPanel now warns at import time when no
model is loaded.

Separately, dropping a .bcfzip file onto the main viewport matched neither
a supported model extension nor the .zip branch of the unsupported-format
explainer (".bcfzip" has no literal dot before "zip"), so the drop did
nothing at all — exactly the "maybe it should be unzipped?" confusion
quoted in the issue. describeUnsupportedFormat now names BCF archives and
points at the BCF panel's Import button.

describeUnsupportedFormat moved out of pointCloudIngest.ts (at its
module-size budget) into a new sibling module, unsupportedFormat.ts, since
it has no dependency on the point-cloud pipeline.

docs/guide/bcf.md's Viewer Integration section claimed drag-and-drop BCF
import works; it doesn't (no drop handler exists in BCFPanel or its
subcomponents) — corrected to describe the Import button and the load
order.

Closes #4099

Discoverability (the issue's other half) is left to the maintainer: a
free BCF viewer isn't obviously findable outside this repo, and that's a
landing-page/marketing/positioning call, not one to make unilaterally
from the viewer codebase. docs/guide/bcf.md already states BCF 2.1/3.0
support and topic/viewpoint rendering, and is linked from mkdocs.yml's
nav, so the docs side is already discoverable once someone is in the
docs; broader discoverability (e.g. landing-page copy) is a suggestion
for the maintainer to weigh, not something this PR changes.
@BIMvoice
BIMvoice requested a review from louistrue as a code owner September 8, 2026 04:30
@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown

Warning

Review limit reached

  • Run on-demand review

This review includes 9 billable files and costs up to $2.25.

Or wait 59 minutes for your next included review.

Check out review usage here.

View limit details

Limit details: You’ve used all 2 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 189fcc22-e8be-4739-9d97-48d33699f298

📥 Commits

Reviewing files that changed from the base of the PR and between 1791e64 and 9dd70f0.

📒 Files selected for processing (9)
  • .changeset/bcf-import-load-order-guidance.md
  • apps/viewer/src/components/viewer/BCFPanel.import-load-order.test.tsx
  • apps/viewer/src/components/viewer/BCFPanel.tsx
  • apps/viewer/src/components/viewer/ViewportContainer.tsx
  • apps/viewer/src/components/viewer/bcf/bcfImportGuidance.ts
  • apps/viewer/src/hooks/ingest/pointCloudIngest.ts
  • apps/viewer/src/hooks/ingest/unsupportedFormat.bcf.test.ts
  • apps/viewer/src/hooks/ingest/unsupportedFormat.ts
  • docs/guide/bcf.md

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Claude review - no findings for 38d6c9c83

Reviewed this diff and found nothing to flag.

@github-actions github-actions Bot added the llm-reviewed A review was verified as posted for this PR's head. label Sep 8, 2026
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Viewer benchmark

✅ No threshold regressions detected.

01_Snowdon_Towers_Sample_Structural(1).ifc

Baseline recorded 2026-07-01T20:31:05.538Z on github-actions ubuntu-latest, viewer-benchmark-ci (headless Chrome, SwiftShader ANGLE), production build.

Metric Current Baseline Delta Threshold Status
firstBatchWaitMs 1283ms 2905ms -55.8% +50%
firstVisibleGeometryMs 1727ms 3652ms -52.7% +50%
streamCompleteMs 2237ms 3598ms -37.8% +50%
spatialReadyMs 811ms 1032ms -21.4% +50%
metadataCompleteMs 1161ms 3063ms -62.1% +50%
totalWallClockMs 2300ms 3700ms -37.8% +50%

AC20-FZK-Haus.ifc

Baseline recorded 2026-07-01T20:30:59.972Z on github-actions ubuntu-latest, viewer-benchmark-ci (headless Chrome, SwiftShader ANGLE), production build.

Metric Current Baseline Delta Threshold Status
firstBatchWaitMs 308ms 1075ms -71.3% +50%
firstVisibleGeometryMs 885ms 1572ms -43.7% +50%
streamCompleteMs 1047ms 1980ms -47.1% +50%
spatialReadyMs 753ms 915ms -17.7% +50%
metadataCompleteMs 951ms 1392ms -31.7% +50%
totalWallClockMs 1100ms 3300ms -66.7% +50%

Refresh the baseline from a CI run: dispatch the Benchmark workflow with record_baseline, download the benchmark-baseline artifact, and commit baseline.json (see tests/benchmark/README.md).

@BIMvoice

BIMvoice commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator Author

#4133 partially addresses #4099. The issue has two asks:

  1. Load-order guidance ("if a BCF is dropped in with no model loaded, saying so plainly ... would resolve most of the confusion") — done: warnIfNoModelLoaded toast on import with no model loaded, .bcf/.bcfzip recognized by describeUnsupportedFormat (previously fell through to a generic ZIP message), and docs/guide/bcf.md's incorrect drag-and-drop claim corrected.
  2. Discoverability ("nothing obvious tells a user that the viewer opens BCF archives, or that it is a viable free alternative") — not done. The PR verified existing docs already describe BCF 2.1/3.0 support, but made no landing-page or README change naming BCF viewing as a standalone use case, which is the actual gap the issue flags. The PR body says this is deliberately left to the maintainer's call.

Since only one of the two items is delivered, I've changed the PR description from Closes #4099 to Refs #4099 so the issue doesn't auto-close on merge — same pattern as #4082 and #4114/#4139 today.

@louistrue — requesting the unqueued label (or your call on how to track the remaining discoverability item).

@louistrue louistrue added the unqueued Maintainer waiver: this PR may merge without closing a ready issue. label Sep 8, 2026
@louistrue

Copy link
Copy Markdown
Collaborator

Applying unqueued, with the reason on the record rather than as a silent label.

Issue queue is red here because the PR declares no closing issue. It deliberately says Refs #N instead, because it is an honest partial slice: the linked issue stays open afterwards, so Closes would be a false claim about what merging this achieves.

That is the right call by the author, and I am not going to ask for it to be changed. Writing Closes on a partial slice would satisfy the gate by lying to it, and the auto-close would then shut an issue whose remaining work is real. The gate reads closingIssuesReferences, which is exactly the field GitHub acts on at merge time, so a keyword here has consequences beyond the check.

The work itself is queue-approved: the referenced issue carries ready. What is missing is a closing reference, not maintainer approval, so the queue's actual purpose is already satisfied.

Label applied by the maintainer account, not by the PR author, so it is not the self-applied shape the gate is written to reject.

Filed the underlying tension separately: a gate that demands a closing reference pressures an author toward either over-claiming or getting blocked, and honest partial work is the population it punishes. That is worth fixing in the gate rather than fixing in every PR.

@vercel

vercel Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Actions Updated
ifc-lite-dev Ignored Ignored Sep 8, 2026 11:41am UTC
ifc-lite-viewer-embed Ignored Ignored Sep 8, 2026 11:41am UTC

@github-actions github-actions Bot removed the llm-reviewed A review was verified as posted for this PR's head. label Sep 8, 2026
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Claude review - no findings for e02ce7813

Reviewed this diff and found nothing to flag.

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Claude review - no findings for 9dd70f00a

Reviewed this diff and found nothing to flag.

@github-actions github-actions Bot added the llm-reviewed A review was verified as posted for this PR's head. label Sep 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

llm-reviewed A review was verified as posted for this PR's head. unqueued Maintainer waiver: this PR may merge without closing a ready issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants