Implement reusable feature widgets for camera, gallery, and detail screens - #28
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5ba83b7a32
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| Future<void> load() async { | ||
| _loading = true; | ||
| notifyListeners(); | ||
| _photos = await _photoStore.loadPhotos(); |
There was a problem hiding this comment.
Reset loading when photo load fails
When _photoStore.loadPhotos() throws (for example from corrupt saved metadata or a storage/shared-preferences failure), load() exits before clearing _loading or notifying listeners again. Any UI bound to isLoading will stay stuck in the loading state, and callers cannot repair it because _loading is private; wrap the await in a try/finally or otherwise notify after failures.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
This PR replaces placeholder TODO files with reusable Flutter widgets/controllers to standardize UI building blocks across camera, gallery, and detail features, and adds a small camera/provider abstraction plus a shared toast helper.
Changes:
- Introduces
AppToast.showas a standardized floating SnackBar helper with icon support and current-snackbar dismissal. - Adds reusable feature widgets/controllers for camera (toolbars/controls/zoom/capture), gallery (controller/grid/badges), and detail (bottom bar/location card).
- Adds a thin
CameraControllerProviderwrapper around camera discovery/controller creation.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| lib/core/widgets/app_toast.dart | Adds a centralized SnackBar/toast helper for consistent in-app messaging. |
| lib/features/camera/controller/camera_controller_provider.dart | Wraps camera discovery and controller instantiation behind a provider for easier reuse/testing. |
| lib/features/camera/widgets/camera_controls_bar.dart | Adds a reusable bottom controls row (gallery, capture, switch camera). |
| lib/features/camera/widgets/camera_top_toolbar.dart | Adds a reusable top toolbar with flash cycling, gallery, and settings actions. |
| lib/features/camera/widgets/capture_button.dart | Adds a custom capture/record button with busy/recording states. |
| lib/features/camera/widgets/zoom_selector.dart | Adds a reusable zoom preset selector UI. |
| lib/features/detail/widgets/detail_bottom_bar.dart | Adds a reusable bottom action bar for detail screen actions (QR/share/delete). |
| lib/features/detail/widgets/detail_location_card.dart | Wraps LocationStampCard for consistent detail location presentation. |
| lib/features/gallery/controller/gallery_controller.dart | Adds a gallery controller managing photo loading and selection state. |
| lib/features/gallery/widgets/media_grid.dart | Adds a reusable grid widget for rendering selectable media tiles. |
| lib/features/gallery/widgets/video_duration_badge.dart | Adds a reusable duration badge widget for video assets. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| Future<void> load() async { | ||
| _loading = true; | ||
| notifyListeners(); | ||
| _photos = await _photoStore.loadPhotos(); | ||
| _selectedIds.clear(); | ||
| _loading = false; | ||
| notifyListeners(); | ||
| } |
| IconButton( | ||
| onPressed: onDelete, | ||
| icon: const Icon(Icons.delete_outline, color: Colors.red), | ||
| tooltip: 'Delete media', | ||
| ), |
| return Semantics( | ||
| button: true, | ||
| label: isRecording ? 'Stop recording' : 'Capture photo', | ||
| child: GestureDetector( | ||
| onTap: enabled ? onPressed : null, |
Motivation
TODOfiles with concrete, reusable UI components to complete feature scaffolding and improve consistency across camera, gallery, and detail screens.Description
AppToast.showinlib/core/widgets/app_toast.dartas a standardized floating snackbar helper with icon support and current snackbar dismissal.CameraTopToolbar,CameraControlsBar,CaptureButton, andZoomSelectorunderlib/features/camera/widgets/to encapsulate flash cycling, capture actions, gallery/switch controls, and zoom presets.CameraControllerProvideratlib/features/camera/controller/camera_controller_provider.dartto wrapavailableCameras()andCameraControllercreation.DetailBottomBarandDetailLocationCardinlib/features/detail/widgets/to centralize bottom actions and the location stamp wrapper.GalleryControlleratlib/features/gallery/controller/gallery_controller.dart,MediaGridatlib/features/gallery/widgets/media_grid.dart, andVideoDurationBadgeatlib/features/gallery/widgets/video_duration_badge.dartto manage photo lists, selection state, grid rendering, and video duration display.Testing
git diff --checkwhich reported no whitespace or index issues and succeeded.flutter analyzewas not executed because the Flutter SDK is not available in this environment (flutter: command not found).Codex Task