AprilNEA / AprilNEA/OpenLogi

[Bug]: Lift for Business shows the silhouette - depot metadata is core_metadata_{left,right}.json

Closed
#1,170 1 comment 0 reactions 0 assignees View on GitHub
needs: triage type: bug
Dominant language
Rust
Stars
21k
Forks
675
Avg merge
2d 5h
Merged PRs (30d)
172

Description

### Pre-flight checklist

- [x] I searched [existing issues](https://github.com/AprilNEA/OpenLogi/issues?q=is%3Aissue) and this is not a duplicate.
- [x] I am on the [latest release](https://github.com/AprilNEA/OpenLogi/releases/latest) or a recent `master` build.
- [x] I quit **Logi Options+** before running OpenLogi (the two apps fight over HID++ access and only one can own a receiver at a time).

### Which part of OpenLogi?

GUI (desktop app)

### OpenLogi version

0.8.3

### Operating system

macOS

### OS version & architecture

macOS 26.6 (25G70), Apple Silicon (arm64)

### Device model

Logitech Lift for Business, left-handed (046d:b033, ext=06)

### How is the device connected?

Bluetooth (direct, no receiver)

### Affected area(s)

- [ ] Device discovery / detection
- [ ] Button remapping
- [ ] DPI control
- [ ] SmartShift
- [ ] Per-application profiles
- [ ] Battery status
- [ ] Settings / configuration (TOML)
- [ ] Auto-update
- [ ] Menu bar / tray
- [x] Other

### What happened?

My **LIFT for Business** (left-handed SKU, `046d:b033`, `ext=06`, Bluetooth-direct) is detected and works fine — buttons, DPI, battery — but the device card and the Buttons page show the synthetic silhouette instead of the render.

The render is not missing from the catalog: `mx_vertical_mini_for_business` is in `index.json` (`modelId: 2b033`) and the sync had already downloaded `front_ext_6.png` into the cache. What the depot does *not* ship is any of `METADATA_FILES` (`core_metadata.json`, `metadata_full.json`, `metadata.json`). Because the Lift is sold in left- and right-handed SKUs, Logi splits the hotspot metadata per handedness and names it in the manifest:

```json
{ "modelId": "2b033_ext6",
"resources": [
{ "key": "device_image", "src": "front_ext_6.png" },
{ "key": "device_buttons_image", "src": "front_ext_6.png" },
{ "key": "image_metadata", "src": "core_metadata_left.json" },
{ "key": "device_easyswitch_image","src": "back_ext_6.png" }
] }
```

(`2b033`, `_ext5` and `_ext7` point at `core_metadata_right.json`.)

Two consequences:

1. `DeviceEntry::baseline_files()` (`crates/openlogi-assets/src/index.rs`) only fetches a metadata file whose name is in `METADATA_FILES`, so no metadata is ever downloaded for this depot. My cache after a normal sync held exactly `front_ext_6.png` + `manifest.json`.
2. `AssetResolver::load_files()` (`crates/openlogi-desktop/src/services/assets.rs`) starts with `let Some(&meta_name) = METADATA_FILES.iter().find(|n| dir.join(n).exists()) else { continue; };`, so the depot is skipped before the render is ever considered and the device falls through to the silhouette — even though the correct variant PNG is already in the cache.

Verified by hand: copying `core_metadata_left.json` to `core_metadata.json` (plus `back_ext_6.png`) from the Logi Options+ depot into `~/.local/share/openlogi/assets/mx_vertical_mini_for_business/` makes both the render and the button hotspots appear correctly, with no other change.

Suggested fix: resolve the metadata filename through the manifest's `image_metadata` resource for the device's variant — the same `resource_for_variant` mechanism `load_files` already uses for `device_image` / `device_buttons_image` — and fall back to `METADATA_FILES` when the manifest names none. `"image_metadata"` would also need adding to the variant loop in `services/assets/sync.rs` so the file is downloaded in the first place. That should cover every Lift SKU (`_ext5` / `_ext6` / `_ext7`) and any other depot that splits metadata per handedness.

Happy to open a PR if that approach looks right.

### Steps to reproduce

1. Pair a Logitech Lift / Lift for Business over Bluetooth (mine: `2b033`, `ext=06`, left-handed).
2. Let the asset sync run — `~/.local/share/openlogi/assets/mx_vertical_mini_for_business/` ends up with only `front_ext_6.png` and `manifest.json`.
3. Open the GUI: the device card and the Buttons page show the generic silhouette instead of the Lift render.

### Diagnostics report

```markdown

```

### `openlogi list` output

```text
(inventory read from the running agent)
LIFT B (-, vid=046d pid=b033)
└─ slot 255 ● LIFT For Business (mouse, wpid=?, battery=30% low (discharging))
model_ids=[b033,0000,0000] ext=06 serial= unit_id= transports=btle
```

### Logs

```shell

```

### macOS permissions (if applicable)

- [ ] OpenLogi has **Accessibility** permission (needed to remap buttons via the event tap).
- [ ] OpenLogi has **Input Monitoring** permission (needed for Bluetooth-direct devices and capture).

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with DeviceEntry::baseline_files() in crates/openlogi-assets/src/index.rs and AssetResolver::load_files() in crates/openlogi-desktop/src/services/assets.rs, then inspect the variant loop in services/assets/sync.rs. Trace how the manifest's image_metadata resource is resolved and downloaded for the Lift variants. Done means a normal sync retrieves the handedness-specific metadata and the GUI shows the Lift render and button hotspots instead of the silhouette.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
desktop
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
74/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.