Android/APIExample-Compose/.agent/skills/review-case/SKILL.md
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.
npx skillsauth add agoraio/api-examples review-caseInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
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.
[ ] leaveChannel before destroy in onDispose — engine.leaveChannel() is called before RtcEngine.destroy() in the onDispose block. Destroying without leaving first leaks the channel session on the server side.
[ ] DisposableEffect key is lifecycleOwner not Unit — DisposableEffect(lifecycleOwner) not DisposableEffect(Unit). Using Unit fires only once and won't clean up on back navigation; the onDispose block never re-executes when the lifecycle owner changes.
channelName, isJoined, uid use rememberSaveable; RtcEngine uses remember. rememberSaveable survives configuration changes (rotation); RtcEngine is not serializable and will crash if placed in rememberSaveable.IRtcEngineEventHandler callbacks that show Toast, Dialog, or AlertDialog dispatch to the main thread via coroutineScope.launch(Dispatchers.Main). SDK callbacks arrive on a background thread; Toast and dialog APIs require the main thread or they throw CalledFromWrongThreadException. Note: simple Compose state mutations (e.g. isJoined = true) are thread-safe via the snapshot system and do not need main-thread dispatch.rememberLauncherForActivityResult) is called before joinChannel(). Joining without the required permissions (RECORD_AUDIO, and CAMERA for video cases) causes a silent failure — no error callback, just no audio/video.DisposableEffect(Unit) is used — change key to lifecycleOwner, then verify back navigation triggers cleanup.RtcEngine stored in rememberSaveable or state fields in remember only — fix to RtcEngine -> remember, UI/session state -> rememberSaveable, then verify rotation.coroutineScope.launch(Dispatchers.Main).joinChannel() — gate join flow behind permission callback and re-test denied/granted paths.DisposableEffect key is Unit for case teardown logic.RtcEngine uses rememberSaveable.development
Add a new API example or modify an existing one. Covers both creation and modification scenarios, including dialog class structure, message map registration, and ARCHITECTURE.md updates.
development
Code review for API examples. Ensures examples follow project conventions, handle lifecycle correctly, manage threads safely, and use APIs properly.
development
Add a new API example or modify an existing one. Covers both creation and modification scenarios, including file structure, registration, and ARCHITECTURE.md updates.
development
Code review for API examples. Ensures examples follow project conventions, handle lifecycle correctly, manage threads safely, and use APIs properly.