Files
amethyst/commons
Claude d1be2ae19e feat(audio-rooms): kick + per-participant host actions (T1 #6)
End-to-end glue for the kick action and the broader per-participant
management surface:

  AudioRoomViewModel.wasKicked: StateFlow<Boolean>
  AudioRoomViewModel.onKick() — set-once flag, calls disconnect().
  Idempotent. Authority enforcement (signer must be host/moderator)
  is the platform layer's job — the relay does not enforce it.

  RoomAdminCommandsFilterAssembler — REQs `kinds=[4312], #a=[room],
  #p=[localPubkey]` so the relay only forwards commands actually
  targeting the local user.

  AudioRoomActivityContent — opens the wire sub on enter, observes
  LocalCache for new AdminCommandEvents, and gates each kick on the
  signer being either the room's pubkey OR a participant whose
  current role is host/moderator. Calls vm.onKick() on a valid
  match, then onLeave() once wasKicked flips.

  ParticipantHostActionsSheet — bottom sheet with three rows:
  Promote to speaker / Demote to listener / Kick. The destructive
  Kick row is colored error. Promote + Demote use
  RoomParticipantActions; Kick uses AdminCommandEvent.kick.

  StagePeopleRow + AudioRoomFullScreen — long-press an avatar
  (host-only, can't long-press the host themselves) opens the
  ParticipantHostActionsSheet for that target.

  RelaySubscriptionsCoordinator.roomAdminCommands registered
  alongside the other audio-room subs.

  Strings: audio_room_promote_speaker, audio_room_demote_listener,
           audio_room_kick_action.

Tests:
  * onKickFlipsWasKickedAndDisconnects — VM state transition
  * onKickIsIdempotent — no double-disconnect
2026-04-26 22:49:47 +00:00
..