Skip to content

feat(canvas): add canvas centering for all or single image, add re-al…#109

Open
Jaaco wants to merge 1 commit into
mainfrom
feat/jaco/centering-canvas
Open

feat(canvas): add canvas centering for all or single image, add re-al…#109
Jaaco wants to merge 1 commit into
mainfrom
feat/jaco/centering-canvas

Conversation

@Jaaco

@Jaaco Jaaco commented Feb 26, 2026

Copy link
Copy Markdown
Collaborator
  1. Center canvas around all images with button in zoom controls (move position, not images)
  2. Center canvas around single image with double click on image row in left list
  3. Re-align all images onto shared center (moves all images AND recenters canvas position)

Description

Type of Change

  • ✨ New feature (non-breaking change which adds functionality)
  • 🛠️ Bug fix (non-breaking change which fixes an issue)
  • ❌ Breaking change (fix or feature that would cause existing functionality to change)
  • 🧹 Code refactor
  • ✅ Build configuration change
  • 📝 Documentation
  • 🗑️ Chore
  • 🧪 Tests

Summary by CodeRabbit

  • New Features

    • Added canvas alignment controls with new center-focus buttons
    • Double-tap images to center the canvas on them
    • Added alignment action to reposition images and recenter the canvas
  • Bug Fixes

    • Fixed state management when switching rows or deleting selected images
  • Refactor

    • Code formatting and layout restructuring improvements

@coderabbitai

coderabbitai Bot commented Feb 26, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Canvas alignment utilities are added to app state (reAlignAllImages, centerCanvasOnImage, centerCanvasOnAllImages) and integrated into UI components (panel list item, main frame list, zoom controls). Image utilities are refactored with formatting changes. State mutations now validate bounds and clear selections appropriately.

Changes

Cohort / File(s) Summary
Core Canvas Alignment Logic
apps/flites/lib/core/app_state.dart
Adds canvas alignment utilities (reAlignAllImages, centerCanvasOnImage, centerCanvasOnAllImages, _centerOfAllImages, _recenterCanvas) and introduces validation/selection-clearing logic during row/image mutations.
UI Integration — List & Panel
apps/flites/lib/ui/panel/controls/panel_list_item.dart, apps/flites/lib/widgets/project_file_list/widgets/main_frame_list.dart
Integrates new canvas-centering functionality: panel_list_item adds onDoubleTap handler for centerCanvasOnImage, and main_frame_list adds icon button for reAlignAllImages alongside visibility controls.
UI Integration — Zoom Controls
apps/flites/lib/widgets/tool_controls/zoom_controls.dart
Restructures zoom button layout and adds new center_focus_strong button calling appState.centerCanvasOnAllImages; preserves existing zoom behavior.
Image Utilities
apps/flites/lib/utils/flites_image_factory.dart, apps/flites/lib/utils/png_utils.dart
Refactors isPng with direct byte-by-byte comparison and explicit length guard; applies formatting adjustments to image mapping and PNG size logic without functional changes.

Sequence Diagram

sequenceDiagram
    participant User as User
    participant UI as UI Components
    participant AppState as AppState
    participant Canvas as Canvas Controller

    User->>UI: Double-tap image in panel
    UI->>AppState: centerCanvasOnImage(imageId)
    AppState->>Canvas: Compute center & update position

    User->>UI: Click align button
    UI->>AppState: reAlignAllImages()
    AppState->>AppState: Compute center of all images
    AppState->>Canvas: Reposition images, recenter canvas

    User->>UI: Click center button in zoom
    UI->>AppState: centerCanvasOnAllImages()
    AppState->>Canvas: Center on average of all images
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • #90: Modifies same UI components (panel_list_item, main_frame_list, zoom_controls) with canvas-centering/alignment handlers and appState methods.
  • #89: Introduces/refactors PanelListItem component; this PR extends it with onDoubleTap handler for image centering.
  • #86: Modifies zoom_controls.dart with zoom button restructuring and canvas-centering/scale control adjustments.

Suggested labels

Needs Attention

Poem

🐰 Canvas alignment hops are here,
Center, realign, make images clear!
With double-taps and focus-strong buttons bright,
The rabbit arranges frames just right! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly summarizes the main changes: adding canvas centering functionality for all images, single images, and re-alignment. The title is specific, concise, and directly reflects the primary feature work.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/jaco/centering-canvas

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
apps/flites/lib/widgets/tool_controls/zoom_controls.dart (1)

13-13: Remove stale commented layout code.

Line 13 (// width: 64,) looks like dead code and makes intent less clear.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/flites/lib/widgets/tool_controls/zoom_controls.dart` at line 13, Remove
the stale commented layout code "// width: 64," from the ZoomControls widget
file to keep the layout intent clear; locate the commented line inside
apps/flites/lib/widgets/tool_controls/zoom_controls.dart (near the ZoomControls
widget/build method) and delete that single-line comment so only active layout
properties remain.
apps/flites/lib/core/app_state.dart (2)

138-153: Comment/behavior mismatch in centering docs.

The comment says “currently selected images,” but the method computes the center of all images in the current row. Please align wording with actual behavior.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/flites/lib/core/app_state.dart` around lines 138 - 153, The doc comment
for centerCanvasOnAllImages/_centerOfAllImages is misleading: it says "currently
selected images" but the implementation uses _getCurrentRow().images (i.e., all
images in the current row). Update the comments to accurately describe behavior
(e.g., "Centers the canvas on the average of all images in the current row" and
"The non-scaled center point of all images in the current row"), or if you
intended selected images instead, change _centerOfAllImages to iterate over the
selected set; reference the methods centerCanvasOnAllImages and
_centerOfAllImages and the call to _getCurrentRow() to locate the change.

108-123: Batch reAlignAllImages updates to avoid repeated full-row rewrites.

Current implementation updates state once per image via saveImageChanges, which causes avoidable O(n²) work and multiple reactive updates.

♻️ Proposed refactor
 void reAlignAllImages() {
-  final center = _centerOfAllImages();
+  final currentRow = _getCurrentRow();
+  final center = _centerOfAllImages();

   if (center == null) {
     return;
   }

-  for (final image in _getCurrentRow().images) {
-    final offsetFromCenter = image.center - center;
-    final newPosition = image.positionOnCanvas - offsetFromCenter;
-
-    saveImageChanges(image.copyWith(positionOnCanvas: newPosition));
-  }
+  final updatedImages = currentRow.images.map((image) {
+    final offsetFromCenter = image.center - center;
+    final newPosition = image.positionOnCanvas - offsetFromCenter;
+    return image.copyWith(positionOnCanvas: newPosition);
+  }).toList();
+
+  _updateCurrentRow(currentRow.copyWith(images: updatedImages));

   centerCanvasOnAllImages();
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/flites/lib/core/app_state.dart` around lines 108 - 123, reAlignAllImages
is calling saveImageChanges per image causing repeated full-row/state writes and
O(n²) reactive work; instead compute the new positions using _centerOfAllImages
and _getCurrentRow(), build a list/map of updated Image models (e.g.,
updatedImages) and perform a single batched state update (create or use a batch
method such as saveImagesChangesBatch or updateCurrentRowImages) to replace the
row's images in one write, then call centerCanvasOnAllImages() once; update or
add a batch-saving helper if none exists and reference reAlignAllImages,
saveImageChanges, _getCurrentRow, _centerOfAllImages, and
centerCanvasOnAllImages when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/flites/lib/widgets/project_file_list/widgets/main_frame_list.dart`:
- Around line 77-80: The IconBtn rendering the re-align control uses the wrong
tooltip text; replace the tooltip value currently set to
context.l10n.toggleVisibility with a dedicated localized string (e.g.,
context.l10n.realignAllImages or similar) for the reAlignAllImages action so the
tooltip matches the control; if that localization key does not exist, add it to
the localization files and use the new key in the IconBtn next to the existing
reference to appState.reAlignAllImages to ensure correct text is shown.

In `@apps/flites/lib/widgets/tool_controls/zoom_controls.dart`:
- Around line 49-51: The IconButton using onPressed:
appState.centerCanvasOnAllImages currently sets tooltip: context.l10n.zoomOut
which is incorrect; replace that tooltip with a dedicated localization key (e.g.
context.l10n.centerCanvas or context.l10n.centerCanvasOnAllImages) and add the
corresponding entry to the app's localization files (arb/intl) and translations;
ensure the new localized string is used for tooltip (and semanticsLabel if
applicable) so the centerCanvasOnAllImages action has the correct
hover/accessibility text.

---

Nitpick comments:
In `@apps/flites/lib/core/app_state.dart`:
- Around line 138-153: The doc comment for
centerCanvasOnAllImages/_centerOfAllImages is misleading: it says "currently
selected images" but the implementation uses _getCurrentRow().images (i.e., all
images in the current row). Update the comments to accurately describe behavior
(e.g., "Centers the canvas on the average of all images in the current row" and
"The non-scaled center point of all images in the current row"), or if you
intended selected images instead, change _centerOfAllImages to iterate over the
selected set; reference the methods centerCanvasOnAllImages and
_centerOfAllImages and the call to _getCurrentRow() to locate the change.
- Around line 108-123: reAlignAllImages is calling saveImageChanges per image
causing repeated full-row/state writes and O(n²) reactive work; instead compute
the new positions using _centerOfAllImages and _getCurrentRow(), build a
list/map of updated Image models (e.g., updatedImages) and perform a single
batched state update (create or use a batch method such as
saveImagesChangesBatch or updateCurrentRowImages) to replace the row's images in
one write, then call centerCanvasOnAllImages() once; update or add a
batch-saving helper if none exists and reference reAlignAllImages,
saveImageChanges, _getCurrentRow, _centerOfAllImages, and
centerCanvasOnAllImages when making the change.

In `@apps/flites/lib/widgets/tool_controls/zoom_controls.dart`:
- Line 13: Remove the stale commented layout code "// width: 64," from the
ZoomControls widget file to keep the layout intent clear; locate the commented
line inside apps/flites/lib/widgets/tool_controls/zoom_controls.dart (near the
ZoomControls widget/build method) and delete that single-line comment so only
active layout properties remain.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 351fbb4 and b3a25cd.

📒 Files selected for processing (6)
  • apps/flites/lib/core/app_state.dart
  • apps/flites/lib/ui/panel/controls/panel_list_item.dart
  • apps/flites/lib/utils/flites_image_factory.dart
  • apps/flites/lib/utils/png_utils.dart
  • apps/flites/lib/widgets/project_file_list/widgets/main_frame_list.dart
  • apps/flites/lib/widgets/tool_controls/zoom_controls.dart

Comment on lines +77 to +80
IconBtn(
icon: Icons.center_focus_strong,
tooltip: context.l10n.toggleVisibility,
onPressed: appState.reAlignAllImages,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Re-align button tooltip is misleading.

The new reAlignAllImages control uses toggleVisibility text, which does not describe the action. Please use a dedicated localized tooltip for re-alignment.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/flites/lib/widgets/project_file_list/widgets/main_frame_list.dart`
around lines 77 - 80, The IconBtn rendering the re-align control uses the wrong
tooltip text; replace the tooltip value currently set to
context.l10n.toggleVisibility with a dedicated localized string (e.g.,
context.l10n.realignAllImages or similar) for the reAlignAllImages action so the
tooltip matches the control; if that localization key does not exist, add it to
the localization files and use the new key in the IconBtn next to the existing
reference to appState.reAlignAllImages to ensure correct text is shown.

Comment on lines +49 to +51
IconButton(
tooltip: context.l10n.zoomOut,
onPressed: appState.centerCanvasOnAllImages,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Center action has the wrong tooltip text.

Line 50 uses zoomOut for a centering action, so hover text/accessibility hint is misleading. Please wire a dedicated localized tooltip for “center canvas”.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/flites/lib/widgets/tool_controls/zoom_controls.dart` around lines 49 -
51, The IconButton using onPressed: appState.centerCanvasOnAllImages currently
sets tooltip: context.l10n.zoomOut which is incorrect; replace that tooltip with
a dedicated localization key (e.g. context.l10n.centerCanvas or
context.l10n.centerCanvasOnAllImages) and add the corresponding entry to the
app's localization files (arb/intl) and translations; ensure the new localized
string is used for tooltip (and semanticsLabel if applicable) so the
centerCanvasOnAllImages action has the correct hover/accessibility text.

@BenAuerDev

Copy link
Copy Markdown
Collaborator

Generally LGTM.

But the issues coderabbit flagged are valid about the tooltip and toggleVisibility text 😃

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants