Skip to content

fix: resolve text clipping and animation lookup issue #1796#1802

Open
xar43 wants to merge 1 commit into
fossasia:developmentfrom
xar43:perfect-fix-1796
Open

fix: resolve text clipping and animation lookup issue #1796#1802
xar43 wants to merge 1 commit into
fossasia:developmentfrom
xar43:perfect-fix-1796

Conversation

@xar43

@xar43 xar43 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Closes #1796

Fix "Fixed" Animation Bug

This PR fixes the issue where the Fixed animation doesn't behave as expected. Instead of remaining fixed, it can clip the text and may even get transferred as the Splitting animation.

What was causing the issue?

The app was identifying the selected animation by comparing object instances (==). This works only when the exact same instance is reused. If a new instance of the same animation class is created, the comparison fails, causing the app to fall back to the wrong animation during transfer.

What's changed?

I updated lib/badge_animation/animation_abstract.dart to make animation comparisons based on the animation type instead of object identity.

By overriding == and hashCode in the BadgeAnimation base class to compare runtimeType, different instances of the same animation (for example, two FixedAnimation objects) are now treated as equal.

This ensures the correct animation is recognized and transferred, preventing the unexpected fallback behavior.

WhatsApp.Video.2026-07-07.at.1.10.01.AM.mov

Summary by Sourcery

Adjust badge animation handling to correctly identify and apply fixed animations without clipping or unintended fallbacks.

Bug Fixes:

  • Ensure fixed badge animations are identified by type rather than instance to prevent incorrect animation transfers.
  • Prevent fixed animation text clipping by clamping the horizontal offset to non-negative values.
  • Avoid incorrectly defaulting to an animation index when no current animation is found, allowing proper handling of the idle state.
  • Stop badge animations cleanly when no message and no special animation are selected by cancelling timers and resetting the animation index.

@sourcery-ai

sourcery-ai Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

This PR fixes incorrect animation matching logic (leading to text clipping and wrong animation transfer) by comparing animations by type instead of instance, adjusts provider behavior when no animation is found or when stopping animations, and prevents fixed animation text from clipping horizontally.

Sequence diagram for animation lookup with updated equality

sequenceDiagram
  participant AnimationBadgeProvider
  participant animationMap
  participant BadgeAnimation

  AnimationBadgeProvider->>AnimationBadgeProvider: getAnimationIndex()
  loop for animation in animationMap.entries
    AnimationBadgeProvider->>BadgeAnimation: operator==(other:_currentAnimation)
    alt [animation.value != null && animation.value == _currentAnimation]
      AnimationBadgeProvider->>AnimationBadgeProvider: return animation.key
    end
  end
  AnimationBadgeProvider->>AnimationBadgeProvider: return null
Loading

File-Level Changes

Change Details Files
Unify animation equality semantics so different instances of the same animation class are treated as the same animation.
  • Override == in the BadgeAnimation base class to compare objects by runtimeType instead of identity.
  • Override hashCode in BadgeAnimation to use runtimeType.hashCode so maps/sets treat same-type instances as equal.
lib/badge_animation/animation_abstract.dart
Refine animation lookup and stopping behavior in the badge animation provider to avoid incorrect fallbacks and better represent "no active animation" state.
  • Log the resolved animation index when getAnimationIndex finds the current animation in animationMap.
  • Change getAnimationIndex to return null when no matching animation is found instead of defaulting to index 0.
  • Update the empty-message/non-special path to cancel the timer and reset _animationIndex to 0 instead of calling stopAllAnimations().
lib/providers/animation_badge_provider.dart
Prevent horizontal clipping in the Fixed animation by ensuring the offset never becomes negative when rendered on narrower badges.
  • Import dart:math to access the max function.
  • Clamp horizontalOffset to be at least 0 by using max(0, (badgeWidth - newWidth) ~/ 2).
lib/badge_animation/ani_fixed.dart

Assessment against linked issues

Issue Objective Addressed Explanation
#1796 Ensure the Fixed animation renders correctly on the badge (stays fixed and does not clip or misalign the text).
#1796 Ensure that when transferring the badge, the Fixed animation is correctly recognized and transferred as Fixed rather than incorrectly falling back to the Splitting animation.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="lib/providers/animation_badge_provider.dart" line_range="221-225" />
<code_context>
   int? getAnimationIndex() {
     for (var animation in animationMap.entries) {
       if (animation.value != null && animation.value == _currentAnimation) {
+        logger.i("Animation Index: ${animation.key}");
         return animation.key;
       }
     }
-    return 0;
+    return null;
   }

</code_context>
<issue_to_address>
**question (bug_risk):** Changing the default animation index from 0 to null may break existing callers if they assume a non-null value.

`getAnimationIndex()` used to always return `0` when no animation matched; now it can return `null`. Call sites may currently rely on `0` as a sentinel or use the value without null checks. Please review existing usages to ensure they handle `null` correctly, or define and document a clear convention for when `null` vs `0` should be used to avoid regressions.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +221 to +225
logger.i("Animation Index: ${animation.key}");
return animation.key;
}
}
return 0;
return null;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

question (bug_risk): Changing the default animation index from 0 to null may break existing callers if they assume a non-null value.

getAnimationIndex() used to always return 0 when no animation matched; now it can return null. Call sites may currently rely on 0 as a sentinel or use the value without null checks. Please review existing usages to ensure they handle null correctly, or define and document a clear convention for when null vs 0 should be used to avoid regressions.

@ctrlVnt ctrlVnt requested review from bhavjsh, ctrlVnt and rahul31124 July 6, 2026 20:08
@ctrlVnt

ctrlVnt commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Hi @xar43, I think this is a duplicate of #1795

@xar43

xar43 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Hi @ctrlVnt ,

Thank you for your feedback! I completely understand why it might look like a duplicate at first glance since both address the "Fixed animation" behavior, but I would like to explain the critical architectural differences:

  1. Root Cause Analysis vs. Layout Tweak: As I originally pointed out in my comment on this issue 3 days ago, the core problem of text clipping stems from a negative horizontalOffset in ani_fixed.dart when text length exceeds the badge width. PR fix: fixed preview same as the badge result #1795 attempts to stretch the preview bounds loop to align with the clip, whereas this PR (fix: resolve text clipping and animation lookup issue #1796 #1802) corrects the underlying math using max(0, ...) so text naturally aligns to the left edge and gracefully overflows.
  2. The Hardware Transfer Bug (Crucial Fix): PR fix: fixed preview same as the badge result #1795 does not address why the animation incorrectly changes to "Splitting" during actual hardware transfer. This PR solves that root cause by overriding == and hashCode based on runtimeType inside the BadgeAnimation abstract class, ensuring the provider never fails the lookup or silently falls back during transfer.
  3. State Management: This PR also safely preserves the user's selected animation state when the text field is temporarily cleared, rather than forcing a hard-reset to LeftAnimation.

Since this PR completely resolves both the visual clipping math, state management, and the hardware transfer glitch (which was the core of the issue reported here), it offers a permanent, comprehensive fix.

I would be extremely grateful if you could review this architectural approach. Thank you so much for your time and guidance!

pls look this one also #1785

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Fixed animation is not fixed

2 participants