Skip to content

Support selecting label in with alt click and styles#7334

Merged
lanzhenw merged 10 commits into
developfrom
alt-selected-labels-v2
Apr 9, 2026
Merged

Support selecting label in with alt click and styles#7334
lanzhenw merged 10 commits into
developfrom
alt-selected-labels-v2

Conversation

@lanzhenw
Copy link
Copy Markdown
Member

@lanzhenw lanzhenw commented Apr 8, 2026

🔗 Related Issues

closes FOEPD-3357

📋 What changes are proposed in this pull request?

Summary

  • Add support for alt-clicking labels to assign them a different selection type ("default" vs "alt"), mirroring the existing alt-selected samples pattern from PR Support alternative selecting samples #7109
  • Each selection type can be configured with a distinct visual style: dashed (cyan, default), dashed-green, or dashed-red
  • Label selection visuals are applied across all overlay types: detection, polyline, keypoint, segmentation, heatmap, and classification

Changes

Python SDK

  • session.set_label_selection_style(default="dashed", alt="dashed-red") — configure visual styles per selection type
  • session.clear_label_selection_style() — reset to defaults
  • session.label_selection_style — get/set the style config
  • session.selected_labels now includes a type key ("default" or "alt")

Operators

  • ctx.label_selection_style — read label selection style in operator context
  • ctx.ops.set_label_selection_style(default, alt) / ctx.ops.clear_label_selection_style()

Frontend

  • Alt+Click on a label assigns it the "alt" selection type
  • resolveLabelSelectionVisuals() resolves per-label color based on type and configured style
  • All 6 overlay types updated to render with the resolved selection color

🧪 How is this patch tested? If it is not, please explain why.

  • Manual: click a label → cyan dashed (default); alt-click a label → cyan dashed (default, same until configured)
  • Manual: session.set_label_selection_style(alt="dashed-red") → alt-clicked labels turn red dashed
  • Manual: verify across detection, polyline, keypoint, segmentation, heatmap, classification overlays
  • Manual: session.clear_label_selection_style() → reverts all to cyan dashed

Testing sample code
Python SDK testing

import fiftyone as fo
import fiftyone.zoo as foz

# Load a dataset with detections
dataset = foz.load_zoo_dataset("quickstart", max_samples=25)
session = fo.launch_app(dataset)

# --- Test 1: Basic label selection with type ---
# Select some labels programmatically with mixed types
sample = dataset.first()
detections = sample.ground_truth.detections
labels = [
    {
        "label_id": detections[0].id,
        "sample_id": sample.id,
        "field": "ground_truth",
        "type": "default",
    },
    {
        "label_id": detections[1].id,
        "sample_id": sample.id,
        "field": "ground_truth",
        "type": "alt",
    },
]
session.selected_labels = labels

# Verify the type is preserved
print(session.selected_labels)
# Should show both labels with their respective "type" values

# --- Test 2: Set label selection style ---
# Default labels stay cyan dashed, alt labels turn red dashed
session.set_label_selection_style(default="dashed", alt="dashed-red")
print(session.label_selection_style)
# {"default": "dashed", "alt": "dashed-red"}
# >> Open modal on the sample — first label should be cyan dashed,
#    second label should be red dashed

# --- Test 3: Switch to green ---
session.set_label_selection_style(default="dashed", alt="dashed-green")
# >> Alt-selected labels should now be green dashed

# --- Test 4: Both types with custom colors ---
session.set_label_selection_style(default="dashed-green", alt="dashed-red")
# >> Default labels = green dashed, alt labels = red dashed

# --- Test 5: Clear ---
session.clear_label_selection_style()
print(session.label_selection_style)
# {"default": "dashed", "alt": "dashed"}
# >> All labels should revert to cyan dashed

# --- Test 6: Interactive alt-click ---
# Clear labels and test in the UI:
session.selected_labels = []
# >> Click a label in the modal → cyan dashed
# >> Alt+Click another label → also cyan dashed (both default style)
# >> Now run:
session.set_label_selection_style(alt="dashed-red")
# >> Alt+Click a new label → should be red dashed
# >> Regular click a new label → should be cyan dashed

Validation checklist for all overlay types

import fiftyone as fo
import fiftyone.zoo as foz
import numpy as np

dataset = fo.Dataset("alt-label-test")
sample = fo.Sample(filepath="image.png")

# Add different label types to test all overlays
sample["detection"] = fo.Detections(
    detections=[fo.Detection(label="cat", bounding_box=[0.1, 0.1, 0.3, 0.3])]
)
sample["polyline"] = fo.Polylines(
    polylines=[fo.Polyline(label="line", points=[[[0.1, 0.1], [0.5, 0.5], [0.9, 0.1]]])]
)
sample["keypoint"] = fo.Keypoints(
    keypoints=[fo.Keypoint(label="pose", points=[(0.3, 0.3), (0.5, 0.5), (0.7, 0.3)])]
)
sample["classification"] = fo.Classification(label="dog")

dataset.add_sample(sample)
session = fo.launch_app(dataset)

# Select labels with mixed types
labels = []
for field in ["detection", "polyline", "keypoint", "classification"]:
    field_val = sample[field]
    if hasattr(field_val, "detections"):
        for det in field_val.detections:
            labels.append({"label_id": det.id, "sample_id": sample.id, "field": field, "type": "alt"})
    elif hasattr(field_val, "polylines"):
        for pl in field_val.polylines:
            labels.append({"label_id": pl.id, "sample_id": sample.id, "field": field, "type": "alt"})
    elif hasattr(field_val, "keypoints"):
        for kp in field_val.keypoints:
            labels.append({"label_id": kp.id, "sample_id": sample.id, "field": field, "type": "alt"})
    elif hasattr(field_val, "id"):
        labels.append({"label_id": field_val.id, "sample_id": sample.id, "field": field, "type": "alt"})

session.selected_labels = labels
session.set_label_selection_style(alt="dashed-red")
# >> Open modal — all labels should be red dashed

session.set_label_selection_style(alt="dashed-green")
# >> All labels should switch to green dashed

session.clear_label_selection_style()
# >> All labels should revert to cyan dashed

📝 Release Notes

Is this a user-facing change that should be mentioned in the release notes?

  • No. You can skip the rest of this section.
  • Yes. Give a description of this change to be included in the release
    notes for FiftyOne users.

What areas of FiftyOne does this PR affect?

  • App: FiftyOne application changes
  • Build: Build and test infrastructure changes
  • Core: Core fiftyone Python library changes
  • Documentation: FiftyOne documentation changes
  • Other

Summary by CodeRabbit

  • New Features

    • Customizable label selection styles: dashed, dashed-green, dashed-red with separate default vs alt presets.
    • APIs/UI/session support to set/clear and persist label selection style; client/server mutation and operator wiring included.
    • Selection visuals updated across overlays to reflect chosen style; selected labels carry an optional selection "type" (default/alt).
  • Bug Fixes

    • Alt-key state is detected and respected during canvas selection.

lanzhenw and others added 4 commits April 7, 2026 22:47
…ion, operators

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…-in operators

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…, keypoint, segmentation, heatmap, classification

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@lanzhenw lanzhenw requested review from a team as code owners April 8, 2026 13:48
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 8, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds end-to-end label-selection styling: new style names and defaults; session/state types, atoms, selectors, and persisted session field labelSelectionStyle; a Recoil selector selectedLabelTypes; an event hook and writer plus a Relay setLabelSelectionStyle mutation; looker overlay rendering changes to resolve and apply per-label selection visuals; Alt-key threading into select events and per-label type; backend session state, GraphQL mutation, and operator bindings to set/clear styles; and unit tests covering the new behavior.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Canvas as Looker Canvas
    participant App as App Event Handler
    participant Recoil as Recoil Session/Selectors
    participant Relay as Relay Client
    participant Server as Backend

    User->>Canvas: Click/Select label (Alt/Shift state)
    Canvas->>App: dispatch SelectEvent (isAltPressed, isShiftPressed)
    App->>Recoil: update selectedLabels (include type "default"/"alt")
    Recoil->>Canvas: provide options (selectedLabels, selectedLabelTypes, labelSelectionStyle)
    Canvas->>Canvas: resolveLabelSelectionVisuals -> render overlays with selection style/color

    App->>Relay: commitMutation(setLabelSelectionStyle, style)
    Relay->>Server: GraphQL mutation set_label_selection_style
    Server->>Server: dispatch SetLabelSelectionStyle -> update server state
    Server->>App: broadcast updated state
    App->>Recoil: update session.labelSelectionStyle
    Recoil->>Canvas: re-render overlays with new visuals
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.18% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically summarizes the main change: adding alt-click support for label selection with configurable visual styles.
Description check ✅ Passed The description is comprehensive and well-structured, covering all required sections: related issues, proposed changes, testing approach, and release notes considerations.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch alt-selected-labels-v2

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

@lanzhenw lanzhenw changed the title Alt selected labels v2 Support selecting label in with alt click and styles Apr 8, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/schema.graphql (1)

782-789: ⚠️ Potential issue | 🟠 Major

Constrain SelectedLabel.type to an enum, not free-form string.

type: String allows arbitrary values, but this field is semantically constrained to selection variants (default/alt). Keeping it as String permits invalid values into API/state flow.

Suggested schema hardening
+enum SelectionType {
+  default
+  alt
+}
+
 input SelectedLabel {
   labelId: ID!
   field: String!
   sampleId: ID!
   frameNumber: Int = null
   instanceId: ID = null
-  type: String = null
+  type: SelectionType = null
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/schema.graphql` around lines 782 - 789, Change the free-form string
"type" on the SelectedLabel input to a GraphQL enum to restrict allowed values:
add a new enum (e.g., SelectionVariant or SelectedLabelType) with the permitted
members (DEFAULT and ALT) and update the SelectedLabel.input's type field from
"type: String = null" to use that enum (keeping nullable/default behavior if
needed). Ensure any usages of SelectedLabel in queries/mutations are updated to
accept the enum type.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/packages/app/src/useEvents/useSetLabelSelectionStyle.ts`:
- Around line 11-14: The callback in useSetLabelSelectionStyle currently
accesses payload.style unsafely and doesn't normalize partial style objects;
update the callback in useSetLabelSelectionStyle to guard for undefined payload
(e.g., default payload = {}), derive style by merging defaults with any provided
partial (use DEFAULT_LABEL_SELECTION_STYLE merged with payload.style), and pass
the resulting normalized style to setter("labelSelectionStyle", style) so
session state always gets a complete, safe style object.

In `@app/packages/app/src/useEvents/utils.ts`:
- Around line 99-107: The resolveLabelSelectionStyle function currently returns
state.label_selection_style directly which allows partial objects from the
server to omit required keys; instead merge the hydrated object onto
DEFAULT_LABEL_SELECTION_STYLE so missing keys like default/alt are filled.
Update resolveLabelSelectionStyle to, when not env().VITE_NO_STATE, return a
merged object (DEFAULT_LABEL_SELECTION_STYLE spread first, then
state.label_selection_style) or use a shallow merge utility so
LabelSelectionStyle always contains the default properties; keep the
VITE_NO_STATE branch returning DEFAULT_LABEL_SELECTION_STYLE unchanged.

In `@app/packages/looker/src/state.ts`:
- Around line 188-190: Tighten the BaseOptions type by replacing the
overly-broad selectedLabelTypes and labelSelectionStyle declarations: change
selectedLabelTypes from Record<string, string> to a mapped type keyed by the
supported label type union (e.g., Record<SupportedLabelType,
SupportedLabelMode>) and change labelSelectionStyle from { default: string; alt:
string } to an object whose properties use a constrained SelectionStyle union
(e.g., { default: SelectionStyle; alt: SelectionStyle }), keeping
selectedLabelTags?: string[] as-is; update or add the corresponding union types
(SupportedLabelType, SupportedLabelMode, SelectionStyle) and adjust any
imports/exports that reference BaseOptions so type-checking enforces only the
allowed values for selectedLabelTypes and labelSelectionStyle.

In `@app/packages/state/src/recoil/selectors.ts`:
- Around line 294-305: In selectedLabelTypes selector, remove the unsafe
double-cast and instead import and use the SelectionType union to narrow
label.type: iterate over get(atoms.selectedLabels) and for each label check
whether (label as any).type is one of SelectionType values (e.g., if ((label as
any).type === "alt") use "alt" else use "default"); replace the casted
expression with this explicit check and return a string typed as SelectionType
(or "default") for types[label.labelId]; ensure to import SelectionType from
types.ts and avoid casting to Record<string, unknown>.

In `@app/packages/state/src/recoil/types.ts`:
- Line 231: SelectedLabelData currently allows any string for its type field
which lets invalid values slip through; change the SelectedLabelData.type
declaration from `string` to the enum/union `SelectionType` (update the import
or local reference to SelectionType if missing) so TypeScript enforces only
valid selection kinds and keeps client/server payloads consistent.

In `@fiftyone/core/session/events.py`:
- Line 98: The LabelData type annotation and default should be changed so it
cannot be None: update the LabelData declaration (symbol: LabelData.type) to use
a concrete default string (e.g., "default") and a non-optional type (str)
instead of t.Optional[str] = None so serialized payloads never produce None and
state.selected_labels remains normalized; adjust any constructor/serialization
logic in the same module (events.py) that relies on Optional to accept/emit the
concrete default.

In `@fiftyone/core/session/session.py`:
- Around line 1490-1506: The _normalize_selected_labels function currently lets
non-dict labels pass through, which is inconsistent with
normalize_selected_samples and risky; update _normalize_selected_labels to
validate inputs the same way: if a label is a dict, enforce
label.setdefault("type","default") and validate type against
VALID_SELECTION_TYPES (as already implemented), otherwise raise a TypeError (or
ValueError) rejecting non-dict entries with a clear message (e.g., "selected
label must be a dict with at least 'label_id' and optional 'type'"); update
callers/selectors such as select_labels and _get_selected_labels tests to assert
this behavior and add a unit test that passes a non-dict value to
_normalize_selected_labels to ensure it raises.

In `@fiftyone/server/mutation.py`:
- Around line 236-243: The code currently corrects only the 'default'/'alt'
values but forwards the entire client-supplied style dict; instead, create a new
sanitized dict containing only the allowed keys (e.g., "default" and "alt"),
populate it from the incoming style (or DEFAULT_LABEL_SELECTION_STYLE when
absent), validate each value against VALID_LABEL_SELECTION_STYLES and fall back
to DEFAULT_LABEL_SELECTION_STYLE where invalid, and then pass that sanitized
dict to dispatch_event (replace the current use of `style` in the call to
fose.SetLabelSelectionStyle). Reference the existing symbols
VALID_LABEL_SELECTION_STYLES, DEFAULT_LABEL_SELECTION_STYLE and
fose.SetLabelSelectionStyle to locate where to implement the change.

---

Outside diff comments:
In `@app/schema.graphql`:
- Around line 782-789: Change the free-form string "type" on the SelectedLabel
input to a GraphQL enum to restrict allowed values: add a new enum (e.g.,
SelectionVariant or SelectedLabelType) with the permitted members (DEFAULT and
ALT) and update the SelectedLabel.input's type field from "type: String = null"
to use that enum (keeping nullable/default behavior if needed). Ensure any
usages of SelectedLabel in queries/mutations are updated to accept the enum
type.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 41dd3108-cc83-4ad3-b10f-06e3b63602dd

📥 Commits

Reviewing files that changed from the base of the PR and between e9395d1 and b2b6b3e.

⛔ Files ignored due to path filters (6)
  • app/packages/relay/src/mutations/__generated__/createSavedViewMutation.graphql.ts is excluded by !**/__generated__/**, !**/__generated__/**
  • app/packages/relay/src/mutations/__generated__/setLabelSelectionStyleMutation.graphql.ts is excluded by !**/__generated__/**, !**/__generated__/**
  • app/packages/relay/src/mutations/__generated__/setSelectedLabelsMutation.graphql.ts is excluded by !**/__generated__/**, !**/__generated__/**
  • app/packages/relay/src/mutations/__generated__/setViewMutation.graphql.ts is excluded by !**/__generated__/**, !**/__generated__/**
  • app/packages/relay/src/queries/__generated__/aggregationsQuery.graphql.ts is excluded by !**/__generated__/**, !**/__generated__/**
  • app/yarn.lock is excluded by !**/yarn.lock, !**/*.lock, !**/*.lock
📒 Files selected for processing (35)
  • app/packages/app/src/useEvents/index.ts
  • app/packages/app/src/useEvents/useSetLabelSelectionStyle.ts
  • app/packages/app/src/useEvents/utils.ts
  • app/packages/app/src/useWriters/index.ts
  • app/packages/app/src/useWriters/onSetLabelSelectionStyle.ts
  • app/packages/looker/src/elements/common/canvas.ts
  • app/packages/looker/src/overlays/classifications.ts
  • app/packages/looker/src/overlays/detection.ts
  • app/packages/looker/src/overlays/heatmap.ts
  • app/packages/looker/src/overlays/keypoint.ts
  • app/packages/looker/src/overlays/polyline.ts
  • app/packages/looker/src/overlays/segmentation.ts
  • app/packages/looker/src/overlays/util.ts
  • app/packages/looker/src/state.ts
  • app/packages/operators/src/built-in-operators.ts
  • app/packages/relay/src/mutations/index.ts
  • app/packages/relay/src/mutations/setLabelSelectionStyle.ts
  • app/packages/state/src/hooks/useOnSelectLabel.ts
  • app/packages/state/src/recoil/atoms.ts
  • app/packages/state/src/recoil/looker.ts
  • app/packages/state/src/recoil/selectors.ts
  • app/packages/state/src/recoil/types.ts
  • app/packages/state/src/session.ts
  • app/schema.graphql
  • fiftyone/core/session/constants.py
  • fiftyone/core/session/events.py
  • fiftyone/core/session/session.py
  • fiftyone/core/state.py
  • fiftyone/operators/executor.py
  • fiftyone/operators/operations.py
  • fiftyone/server/events/dispatch.py
  • fiftyone/server/inputs.py
  • fiftyone/server/mutation.py
  • tests/unittests/operators/executor_tests.py
  • tests/unittests/session_events_tests.py

Comment thread app/packages/app/src/useEvents/useSetLabelSelectionStyle.ts
Comment thread app/packages/app/src/useEvents/utils.ts
Comment thread app/packages/looker/src/state.ts
Comment thread app/packages/state/src/recoil/selectors.ts Outdated
Comment thread app/packages/state/src/recoil/types.ts Outdated
Comment thread fiftyone/core/session/events.py Outdated
Comment thread fiftyone/core/session/session.py
Comment thread fiftyone/server/mutation.py Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
app/packages/looker/src/state.ts (1)

189-193: 🛠️ Refactor suggestion | 🟠 Major

Tighten selectedLabelTypes to supported union values

Record<string, string> still permits invalid mode values and weakens compile-time guarantees when indexing style config. This concern is still present.

#!/bin/bash
# Verify current broad typing and producer typing
rg -nP --type=ts "selectedLabelTypes\\s*:\\s*Record<string,\\s*string>" app/packages/looker/src/state.ts app/packages/state/src/recoil/selectors.ts
rg -nP --type=ts "type\\s+SelectionType|\"default\"\\s*\\|\\s*\"alt\"" app/packages/state/src/recoil/types.ts

As per coding guidelines **/*.{ts,tsx}: Review the Typescript and React code for conformity with best practices in React, Recoil, Graphql, and Typescript. Highlight any deviations.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/packages/looker/src/state.ts` around lines 189 - 193, The
selectedLabelTypes field is too permissive as Record<string, string>; change its
type to Record<string, LabelSelectionStyleName> (or the explicit union used by
LabelSelectionStyleName) so indexing into labelSelectionStyle is type-safe;
update any producers/assignments (selectors or setters) that currently write
arbitrary strings to selectedLabelTypes to provide only the union values or
cast/convert them, and import/use LabelSelectionStyleName where
selectedLabelTypes is declared to ensure compile-time enforcement across get/set
paths (refer to selectedLabelTypes, LabelSelectionStyleName, and
labelSelectionStyle in the file and related selectors).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/packages/state/src/recoil/atoms.ts`:
- Around line 215-223: The sessionAtom generic parameters are incorrect — they
should be a keyof Session, not the value types; remove the explicit generic
arguments on the two atoms so TypeScript can infer the key from the key
property. Update the calls to sessionAtom used for sampleSelectionStyle and
labelSelectionStyle (which use DEFAULT_SELECTION_STYLE and
DEFAULT_LABEL_SELECTION_STYLE) by deleting the <SelectionStyle> and
<LabelSelectionStyle> generics so the compiler infers types from the provided
key strings.

---

Duplicate comments:
In `@app/packages/looker/src/state.ts`:
- Around line 189-193: The selectedLabelTypes field is too permissive as
Record<string, string>; change its type to Record<string,
LabelSelectionStyleName> (or the explicit union used by LabelSelectionStyleName)
so indexing into labelSelectionStyle is type-safe; update any
producers/assignments (selectors or setters) that currently write arbitrary
strings to selectedLabelTypes to provide only the union values or cast/convert
them, and import/use LabelSelectionStyleName where selectedLabelTypes is
declared to ensure compile-time enforcement across get/set paths (refer to
selectedLabelTypes, LabelSelectionStyleName, and labelSelectionStyle in the file
and related selectors).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9a0eccb8-5909-4a72-aef8-97b7a372804f

📥 Commits

Reviewing files that changed from the base of the PR and between b2b6b3e and b7731bd.

📒 Files selected for processing (6)
  • app/packages/looker/src/state.ts
  • app/packages/operators/src/state.ts
  • app/packages/state/src/recoil/atoms.ts
  • fiftyone/core/session/constants.py
  • fiftyone/core/session/session.py
  • tests/unittests/operators/operations_tests.py

Comment thread app/packages/state/src/recoil/atoms.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/packages/app/src/useEvents/utils.ts (1)

89-97: 🧹 Nitpick | 🔵 Trivial

Consider aligning resolveSampleSelectionStyle with the same merge pattern.

resolveLabelSelectionStyle merges defaults with incoming state, but resolveSampleSelectionStyle does a simple fallback. If the server ever sends a partial sample_selection_style, it could cause similar issues downstream.

Proposed alignment
 const resolveSampleSelectionStyle = (state: {
   sample_selection_style?: SelectionStyle;
 }): SelectionStyle => {
   if (env().VITE_NO_STATE) {
     return DEFAULT_SELECTION_STYLE;
   }

-  return state.sample_selection_style || DEFAULT_SELECTION_STYLE;
+  return {
+    ...DEFAULT_SELECTION_STYLE,
+    ...(state.sample_selection_style || {}),
+  };
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/packages/app/src/useEvents/utils.ts` around lines 89 - 97,
resolveSampleSelectionStyle currently returns state.sample_selection_style or
DEFAULT_SELECTION_STYLE which loses default fields when the server sends a
partial style; change it to merge defaults with the incoming partial like
resolveLabelSelectionStyle does. Update resolveSampleSelectionStyle to
early-return DEFAULT_SELECTION_STYLE when env().VITE_NO_STATE is true, otherwise
return a merged object (e.g., combine DEFAULT_SELECTION_STYLE with
state.sample_selection_style via object spread) so missing fields are filled
from DEFAULT_SELECTION_STYLE; reference the function name
resolveLabelSelectionStyle as the pattern to follow.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/packages/state/src/recoil/selectors.ts`:
- Around line 295-305: The selector selectedLabelTypes currently reads
atoms.selectedLabels and collapses duplicate labelIds by last-write, which can
downgrade an existing "alt" when shift-click appends entries without a type;
change the selector to derive types from the canonical map used elsewhere
(selectors.selectedLabelMap) instead of atoms.selectedLabels so duplicate-ID
resolution matches the canonical semantics—fetch
get(selectors.selectedLabelMap), iterate its entries to produce the
Record<string, SelectionType>, and coerce missing/undefined types to "default"
while preserving "alt".

---

Outside diff comments:
In `@app/packages/app/src/useEvents/utils.ts`:
- Around line 89-97: resolveSampleSelectionStyle currently returns
state.sample_selection_style or DEFAULT_SELECTION_STYLE which loses default
fields when the server sends a partial style; change it to merge defaults with
the incoming partial like resolveLabelSelectionStyle does. Update
resolveSampleSelectionStyle to early-return DEFAULT_SELECTION_STYLE when
env().VITE_NO_STATE is true, otherwise return a merged object (e.g., combine
DEFAULT_SELECTION_STYLE with state.sample_selection_style via object spread) so
missing fields are filled from DEFAULT_SELECTION_STYLE; reference the function
name resolveLabelSelectionStyle as the pattern to follow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5f68dac3-a85c-4d9d-8457-24e1fe45c929

📥 Commits

Reviewing files that changed from the base of the PR and between b7731bd and b718a3b.

📒 Files selected for processing (6)
  • app/packages/app/src/useEvents/useSetLabelSelectionStyle.ts
  • app/packages/app/src/useEvents/utils.ts
  • app/packages/state/src/recoil/selectors.ts
  • app/packages/state/src/recoil/types.ts
  • fiftyone/core/session/events.py
  • fiftyone/server/mutation.py

Comment thread app/packages/state/src/recoil/selectors.ts
lanzhenw and others added 2 commits April 8, 2026 09:55
…nonical map

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Member

@benjaminpkane benjaminpkane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great. Incredible incredible detail ✨

If we do encounter bugs/regressions we should update e2e POMs as necessary

Comment thread app/packages/looker/src/overlays/util.ts
@lanzhenw lanzhenw mentioned this pull request Apr 9, 2026
7 tasks
Copy link
Copy Markdown
Contributor

@swheaton swheaton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks fine to me from backend (minimal changes in this area)
🚢 🇮🇹

@lanzhenw lanzhenw enabled auto-merge April 9, 2026 19:44
@lanzhenw
Copy link
Copy Markdown
Member Author

lanzhenw commented Apr 9, 2026

Screenshot 2026-04-09 at 2 43 31 PM

dashed-green and dashed-red

@lanzhenw lanzhenw merged commit 7b8b1b9 into develop Apr 9, 2026
40 of 43 checks passed
@lanzhenw lanzhenw deleted the alt-selected-labels-v2 branch April 9, 2026 21:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants