name: review-case description: > Review an existing case implementation against project-specific red lines and coding standards. Use after implementing or modifying a case. Use when: reviewing a Compose case for correctness, checking red-line compliance, verifying lifecycle and state patterns, auditing an existing Composable. Keywords: review, audit, check, red lines, lifecycle, state, compliance, Compose.
Review Case — APIExample-Compose
Run through every item below before considering a case implementation complete. Open the case's Composable source file and verify each point against the actual code.
Checklist
Teardown & Lifecycle
leaveChannel before destroy in onDispose —
engine.leaveChannel()is called beforeRtcEngine.destroy()in theonDisposeblock. Destroying without leaving first leaks the channel session on the server side.DisposableEffect key is lifecycleOwner not Unit —
DisposableEffect(lifecycleOwner)notDisposableEffect(Unit). UsingUnitfires only once and won't clean up on back navigation; theonDisposeblock never re-executes when the lifecycle owner changes.
State Management
- rememberSaveable for channelName/isJoined/uid and remember for RtcEngine —
channelName,isJoined,uiduserememberSaveable;RtcEngineusesremember.rememberSaveablesurvives configuration changes (rotation);RtcEngineis not serializable and will crash if placed inrememberSaveable.
Threading
- Callbacks dispatch to main thread via coroutineScope.launch(Dispatchers.Main) —
IRtcEngineEventHandlercallbacks that showToast,Dialog, orAlertDialogdispatch to the main thread viacoroutineScope.launch(Dispatchers.Main). SDK callbacks arrive on a background thread;Toastand dialog APIs require the main thread or they throwCalledFromWrongThreadException. Note: simple Compose state mutations (e.g.isJoined = true) are thread-safe via the snapshot system and do not need main-thread dispatch.
Permissions
- Permission check before joinChannel — Permission launcher (
rememberLauncherForActivityResult) is called beforejoinChannel(). Joining without the required permissions (RECORD_AUDIO, andCAMERAfor video cases) causes a silent failure — no error callback, just no audio/video.
If a Check Fails
DisposableEffect(Unit)is used — change key tolifecycleOwner, then verify back navigation triggers cleanup.RtcEnginestored inrememberSaveableor state fields inrememberonly — fix toRtcEngine -> remember, UI/session state ->rememberSaveable, then verify rotation.- Toast/Dialog shown directly in callback — move UI-thread-only calls into
coroutineScope.launch(Dispatchers.Main). - Permission launcher bypassed before
joinChannel()— gate join flow behind permission callback and re-test denied/granted paths.
NEVER
- NEVER approve a review when
DisposableEffectkey isUnitfor case teardown logic. - NEVER approve a review when
RtcEngineusesrememberSaveable. - NEVER treat Compose callback state safety as permission to call Toast/Dialog off main thread.
- NEVER skip rotation and back-navigation checks for lifecycle-sensitive Compose cases.