Conversation
There was a problem hiding this comment.
Code Review
This pull request refactors the camera constraints repository and permission handling. It removes the settable constraints repository, simplifies ConstraintsRepository to be served directly by CameraXCameraSystemRepository, and introduces a centralized CameraPermissionGuard in JcaApp to handle camera permission revocation. Additionally, the settings screen now displays a loading indicator while constraints are being loaded. The review feedback suggests restricting the visibility of the new Dagger provider methods in CameraModule to internal and adding KDoc documentation for the new isPermissionsRoute extension function.
| @Provides | ||
| @ActivityRetainedScoped | ||
| fun providesCameraSystemRepository( | ||
| fun providesCameraXCameraSystemRepository( |
There was a problem hiding this comment.
According to the repository style guide, we should use the most restrictive visibility modifier possible. Since CameraModule is an internal object, this provides method should be marked internal.
| fun providesCameraXCameraSystemRepository( | |
| internal fun providesCameraXCameraSystemRepository( |
References
- Ensure all new functions, properties, and classes use the most restrictive visibility modifier possible (e.g., private, internal) while still allowing necessary access. Avoid public visibility unless explicitly required for external API exposure. (link)
| @Provides | ||
| fun providesCameraSystemRepository( | ||
| repository: CameraXCameraSystemRepository | ||
| ): CameraSystemRepository = repository | ||
|
|
||
| @Provides | ||
| fun providesConstraintsRepository( | ||
| repository: CameraXCameraSystemRepository | ||
| ): ConstraintsRepository = repository |
There was a problem hiding this comment.
Following the repository style guide, these new provides methods should also be marked internal to restrict their visibility appropriately.
| @Provides | |
| fun providesCameraSystemRepository( | |
| repository: CameraXCameraSystemRepository | |
| ): CameraSystemRepository = repository | |
| @Provides | |
| fun providesConstraintsRepository( | |
| repository: CameraXCameraSystemRepository | |
| ): ConstraintsRepository = repository | |
| @Provides | |
| internal fun providesCameraSystemRepository( | |
| repository: CameraXCameraSystemRepository | |
| ): CameraSystemRepository = repository | |
| @Provides | |
| internal fun providesConstraintsRepository( | |
| repository: CameraXCameraSystemRepository | |
| ): ConstraintsRepository = repository |
References
- Ensure all new functions, properties, and classes use the most restrictive visibility modifier possible (e.g., private, internal) while still allowing necessary access. Avoid public visibility unless explicitly required for external API exposure. (link)
| } | ||
| } | ||
|
|
||
| fun NavDestination.isPermissionsRoute(): Boolean = route?.substringBefore('?') == BASE_ROUTE_DEF |
There was a problem hiding this comment.
According to the repository style guide, all non-private members must have KDoc documentation. Please add a KDoc comment for isPermissionsRoute.
/**
* Returns whether this [NavDestination] corresponds to the permissions route.
*/
fun NavDestination.isPermissionsRoute(): Boolean = route?.substringBefore('?') == BASE_ROUTE_DEFReferences
- Document all non-private members: All non-private classes, functions, and composables must have KDoc documentation. (link)
Description
Fixes #572.
SettableConstraintsRepositoryImplwas only ever populated byPreviewViewModel, so when the process was recreated withSettingsScreenon top of the back stack,systemConstraintsstayed null and the settings list never rendered.CameraXCameraSystemRepositorynow implementsConstraintsRepository, andSettableConstraintsRepositoryandConstraintsModuleare removed.CameraModulescopes the concrete repository and provides bothCameraSystemRepositoryandConstraintsRepositoryfrom it, so they resolve to the same activity-retained instance.PreviewViewModelno longer copies constraints; it readscameraSystemRepository.systemConstraintsdirectly forcaptureUiState/debugUiState.systemConstraintsis first accessed. I went with this instead of theonStart+stateInapproach I described in the issue:stateInlaunches a sharing coroutine in the@Singleton@DefaultCoroutineScope, and that coroutine stays alive regardless of theSharingStartedpolicy, so it outlives the@ActivityRetainedScopedrepository.runTestcaught that as anUncompletedCoroutinesErroron the first attempt.initializationDeferred.start()needs no extra coroutine and exposes the camera system's ownStateFlowas is.SettingsUiState.Disabledis renamed toLoading, andSettingsScreenrenders a progress indicator for it instead of an emptyColumn.previewScreeninto aCameraPermissionGuardinJcaApp. It covers whichever destination is restored, clears the back stack before routing toPermissionsRoute, and does nothing while the current destination is already the permissions screen.PreviewViewModelexisted.PreviewViewModelnow diffs default settings against the snapshot the camera system was initialized with, rather than against its own first emission. The snapshot is exposed asCameraSystemRepository.getInitialDefaultCameraAppSettings().As discussed in the issue,
SettingsScreennow initializes CameraX on its own.SettableConstraintsRepositoryImplwas also doubling as a fake inPreviewViewModelTest,CameraAppSettingsViewModelTestandCaptureUiStateAdapterTest. Those now use a newFakeConstraintsRepositoryin:data:settings:testingorFakeCameraSystem.setSystemConstraints.Testing
./gradlew test./gradlew spotlessCheck./gradlew assembleStableDebugadb shell am kill, "Don't keep activities", and revoking CAMERA in system settings.Loadingstate, and default settings changed beforePreviewViewModelexists.