Four buttons, one per entity, each opening the existing picker with the name
already in it. This is the cheap version of the feature complete: a member
looking at a translation can give it a room without backing out to the group,
finding "Add subgroup" and retyping a name the app already knew.
`SelectSubgroupAdminsRoute` grows three nullable fields. The name is a
suggestion and stays editable -- a group renaming its own room is not a route's
business to prevent -- and it is seeded in the view model's constructor rather
than in `initiate`, because a field somebody may already be typing into must not
be overwritten by a load completing underneath them.
The origin is two flat fields rather than one type, because a route is
`@Serializable` and is rebuilt from a bundle. The nav host reassembles them and
requires both or neither: half a reference is a reference with the resolvable
part removed. The view model then only holds it. Riding it onto the ceremony
needs a `DkgSession` column and a tag on the proposal, which is Phase 5, and the
comment at the `proposeRitual` call says so rather than leaving a parameter that
looks forgotten.
The gate is `canAddSubgroup` on all four states and not `canSign`: a share of
the key *and* `mlsGroupState != null`, because a NIP-17 room has no admins to be
a parent's and these entities can live in one. Three states had to learn it.
`ProjectDetailUIState` and `TranslationArtifactVersionDetailUIState` already
carried `canSign`; `ArtifactDetailUIState` carried no capability flag at all, so
the artifact screen and its view model gained a `ChatRepository` as well -- the
one place this phase is more than a button.
Each flag is computed off `SubgroupOrigin.of(entity).parentChatRoomId` rather
than the route's `chatRoomId`. They are the same room in every path that exists,
and reading it through the function is what keeps the parent of a subgroup the
room the entity actually lives in if a route is ever built by hand.
Hidden rather than disabled where it cannot work, which is what the room's own
subgroup entry does and for the same reason: a device with no share cannot open
the certificate session at all, and `proposeSigningBatch` throws rather than
refusing.
Phase 3 of docs/subgroups-for-entities.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>