127 lines
4.1 KiB
Markdown
127 lines
4.1 KiB
Markdown
# Bank Composition Editor
|
|
|
|
## Original Problem
|
|
|
|
`Bank Composition` needed to become a real editor inside `Asset Details` without collapsing into any of these bad outcomes:
|
|
|
|
- direct binding to raw snapshot or manifest shapes;
|
|
- overgeneric UI components before the first section existed;
|
|
- family-specific rules hidden inside visual controls;
|
|
- direct Studio writes to `asset.json`;
|
|
- public bus chatter for every local section interaction.
|
|
|
|
## Consolidated Decision
|
|
|
|
The first-wave `Bank Composition` model is:
|
|
|
|
1. Studio owns a DTO projection boundary for the section;
|
|
2. the section shell lands early and follows the existing staged-edit rhythm;
|
|
3. dual-list and capacity-meter components stay intentionally dumb;
|
|
4. one section-scoped coordinator around `StudioFormSession<BankCompositionDraft>` owns orchestration;
|
|
5. public workspace-bus events stay minimal and notification-oriented;
|
|
6. `apply` goes through packer and rebinds from refreshed persisted state.
|
|
|
|
## Final Model
|
|
|
|
### 1. DTO Boundary
|
|
|
|
The section never consumes raw packer/runtime structures directly.
|
|
|
|
It works with Studio-owned DTOs for:
|
|
|
|
- `available` rows from current runtime/details state;
|
|
- `selected` rows from persisted composition state.
|
|
|
|
Only non-blocking files enter the `available` DTO projection.
|
|
|
|
### 2. Section Shell
|
|
|
|
`Bank Composition` is a real `Asset Details` section, not a hidden future placeholder.
|
|
|
|
The shell follows the existing staged-edit rhythm:
|
|
|
|
- `change`
|
|
- `apply`
|
|
- `reset`
|
|
- `cancel`
|
|
|
|
Outside edit mode, it teaches the current persisted state in read-only form.
|
|
|
|
### 3. Dumb Components
|
|
|
|
Two named components exist for this area:
|
|
|
|
- `StudioDualListView<T>`
|
|
- `StudioAssetCapacityMeter`
|
|
|
|
They are intentionally state-driven, not rule-driven.
|
|
Family-specific transfer, ordering, and capacity semantics do not live inside these components.
|
|
|
|
### 4. Section-Scoped Coordinator
|
|
|
|
The main orchestration lives in one section-scoped coordinator built around `StudioFormSession<BankCompositionDraft>`.
|
|
|
|
That coordinator owns:
|
|
|
|
- draft lifecycle;
|
|
- transfer and reorder effects;
|
|
- capacity state;
|
|
- blockers and hints;
|
|
- apply success and failure handling.
|
|
|
|
### 5. WorkspaceBus Boundary
|
|
|
|
The public bus surface stays intentionally small.
|
|
|
|
First-wave public notifications are about observable state transitions:
|
|
|
|
- draft changed;
|
|
- capacity changed;
|
|
- apply requested;
|
|
- apply succeeded;
|
|
- apply failed.
|
|
|
|
Local edit actions remain local to the section coordinator.
|
|
|
|
### 6. Persistence Boundary
|
|
|
|
Studio does not write `asset.json` directly for `Bank Composition`.
|
|
|
|
The write path is:
|
|
|
|
1. Studio submits ordered selected files to packer;
|
|
2. packer validates and persists through `asset.json.artifacts`;
|
|
3. packer refreshes the minimum runtime/details state;
|
|
4. Studio rebinds from refreshed persisted state.
|
|
|
|
If apply fails, the draft stays alive and the section remains in editing mode.
|
|
|
|
## Examples
|
|
|
|
### Example: Why the meter must stay dumb
|
|
|
|
Tile banks and sound banks may calculate capacity differently.
|
|
That difference belongs in family policies owned by the coordinator, not in `StudioAssetCapacityMeter`.
|
|
|
|
### Example: Why `apply` is not a public bus command
|
|
|
|
External observers may care that apply was requested or failed.
|
|
They do not need to own the local section command sequence for `moveUp`, `moveDown`, `reset`, or `cancel`.
|
|
|
|
## Common Pitfalls and Anti-Patterns
|
|
|
|
- Binding section UI directly to raw snapshot rows or raw manifest shape.
|
|
- Hiding bank-family rules inside `StudioDualListView<T>` or the capacity meter.
|
|
- Creating a second staged-edit session model parallel to `StudioFormSession`.
|
|
- Turning every local section action into a public workspace-bus event.
|
|
- Writing `asset.json` directly from Studio instead of routing through packer.
|
|
|
|
## References
|
|
|
|
- Specs:
|
|
- [`../specs/4. Assets Workspace Specification.md`](../specs/4.%20Assets%20Workspace%20Specification.md)
|
|
- Cross-domain:
|
|
- [`../../packer/specs/5. Diagnostics, Operations, and Studio Integration Specification.md`](../../packer/specs/5.%20Diagnostics,%20Operations,%20and%20Studio%20Integration%20Specification.md)
|
|
- Related learn:
|
|
- [`./assets-workspace-execution-wave.md`](./assets-workspace-execution-wave.md)
|