Skip to content

fix: optimize bubble replacement logic with silent replace support#1660

Open
52cyb wants to merge 1 commit into
linuxdeepin:masterfrom
52cyb:master
Open

fix: optimize bubble replacement logic with silent replace support#1660
52cyb wants to merge 1 commit into
linuxdeepin:masterfrom
52cyb:master

Conversation

@52cyb

@52cyb 52cyb commented Jul 7, 2026

Copy link
Copy Markdown
Contributor
  1. Refactored BubbleModel API: replaced isReplaceBubble() and replaceBubble(BubbleItem*) with cleaner
    replaceBubbleIndex(NotifyEntity), updateBubbleInPlace(), and replaceBubble(int, BubbleItem*) methods
  2. Added support for "silent replace" via x-deepin-SilentReplace hint: when two bubbles match and the hint is true, the existing bubble is updated in-place using dataChanged rather than full remove+insert
  3. Changed replaceBubbleIndex to accept NotifyEntity instead of BubbleItem*, enabling replacement logic before creating a new BubbleItem
  4. replaceBubble now handles resource cleanup by calling deleteLater() on both old and new bubbles as needed
  5. Removed the no longer needed isReplaceBubble() method, simplifying the public interface

Log: Refactored bubble replacement mechanism; added silent in-place update for performance

Influence:

  1. Test notification replacement with and without x-deepin- SilentReplace hint
  2. Verify that in-place update works for silent replacements (no visual artifacts)
  3. Test replacement with different app names and bubble IDs to confirm no false matches
  4. Verify memory management: old bubbles are properly deleted via deleteLater()
  5. Test boundary cases: invalid replaceIndex, null bubble, concurrent notifications
  6. Verify that dataChanged signal correctly triggers view updates for non-silent replacements

refactor: 优化气泡替换逻辑,支持静默替换

  1. 重构 BubbleModel API:将 isReplaceBubble()replaceBubble(BubbleItem*) 替换为更清晰的
    replaceBubbleIndex(NotifyEntity)updateBubbleInPlace()replaceBubble(int, BubbleItem*)
  2. 通过 x-deepin-SilentReplace 提示增加"静默替换"支持:当气泡匹配且提 示为 true 时,使用 dataChanged 原地更新现有气泡,避免完整的移除-插入
    操作
  3. replaceBubbleIndex 改为接受 NotifyEntity 而非 BubbleItem*, 允许在创建 BubbleItem 之前执行替换逻辑
  4. replaceBubble 现在通过调用新旧气泡的 deleteLater() 来处理资源清理
  5. 移除不再需要的 isReplaceBubble() 方法,简化公开接口

Log: 重构气泡替换机制;增加静默原地更新以提升性能

Influence:

  1. 测试带或不带 x-deepin-SilentReplace 提示的通知替换
  2. 验证静默替换时原地更新正常工作(无视觉异常)
  3. 测试不同应用名和气泡 ID 的替换,确认无错误匹配
  4. 验证内存管理:旧气泡通过 deleteLater() 正确释放
  5. 测试边界情况:无效的 replaceIndex、空指针、并发通知
  6. 验证对于非静默替换,dataChanged 信号正确触发视图更新

PMS: BUG-367205

Summary by Sourcery

Refactor notification bubble replacement to support index-based replacement and silent in-place updates driven by NotifyEntity metadata.

New Features:

  • Add support for silent in-place bubble updates when the x-deepin-SilentReplace hint is set, using dataChanged instead of remove/insert.

Enhancements:

  • Expose a new BubbleModel API that operates on NotifyEntity and explicit replace indexes, simplifying and clarifying replacement handling.
  • Improve safety and robustness of bubble replacement by validating indexes and centralizing deletion of old BubbleItem instances.

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: 52cyb

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@deepin-ci-robot

Copy link
Copy Markdown

Hi @52cyb. Thanks for your PR.

I'm waiting for a linuxdeepin member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@sourcery-ai

sourcery-ai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Reviewer's Guide

Refactors the bubble replacement flow to compute replacement targets from NotifyEntity before BubbleItem creation, adds a silent in-place update path controlled by the x-deepin-SilentReplace hint, and centralizes index- and lifetime-safe replacement operations inside BubbleModel.

Sequence diagram for addBubble with silent and normal replacement

sequenceDiagram
    actor NotificationSource
    participant BubblePanel
    participant BubbleModel

    NotificationSource->>BubblePanel: addBubble(id)
    BubblePanel->>BubblePanel: getNotifyEntity(id)
    BubblePanel->>BubbleModel: replaceBubbleIndex(entity)
    BubbleModel-->>BubblePanel: replaceIndex

    alt replaceIndex >= 0 and entity.hints().value(x-deepin-SilentReplace).toBool()
        BubblePanel->>BubbleModel: updateBubbleInPlace(replaceIndex, entity)
        BubbleModel->>BubbleModel: oldBubble.setEntity(entity)
        BubbleModel-->>BubbleModel: dataChanged(index, index)
    else replaceIndex >= 0
        BubblePanel->>BubblePanel: bubble = new BubbleItem(entity)
        BubblePanel->>BubblePanel: bubble.setEnablePreview(enablePreview)
        BubblePanel->>BubbleModel: replaceBubble(replaceIndex, bubble)
        BubbleModel->>BubbleModel: oldBubble.deleteLater()
    else no replacement
        BubblePanel->>BubblePanel: bubble = new BubbleItem(entity)
        BubblePanel->>BubblePanel: bubble.setEnablePreview(enablePreview)
        BubblePanel->>BubbleModel: push(bubble)
    end
Loading

File-Level Changes

Change Details Files
Refactor BubbleModel replacement API to use NotifyEntity and index-based operations.
  • Introduce replaceBubbleIndex(const NotifyEntity&) to locate an existing bubble by app name and bubbleId when the entity is flagged as replaceable.
  • Add updateBubbleInPlace(int, const NotifyEntity&) to update an existing bubble via setEntity() and emit dataChanged for efficient, height-preserving updates.
  • Change replaceBubble(int, BubbleItem*) to operate on an explicit index, validate bounds and null pointers, and delete the old bubble via deleteLater() after replacement.
  • Remove legacy isReplaceBubble(const BubbleItem*) and the BubbleItem*-based replaceBubbleIndex() to simplify the public interface and avoid needing a temporary BubbleItem for matching.
panels/notification/bubble/bubblemodel.cpp
panels/notification/bubble/bubblemodel.h
Integrate silent replace behavior and new BubbleModel API into BubblePanel.
  • Before creating a BubbleItem, compute the replacement index using replaceBubbleIndex(const NotifyEntity&).
  • If a replacement target exists and the x-deepin-SilentReplace hint is true, call updateBubbleInPlace() and return without creating a new BubbleItem.
  • Otherwise create a BubbleItem, configure preview, and either call replaceBubble(index, bubble) when a replacement target exists, or push(bubble) for normal insertion.
  • Remove the old logic that relied on isReplaceBubble() and BubbleModel::replaceBubble(BubbleItem*) and manual deleteLater() of the old bubble.
panels/notification/bubble/bubblepanel.cpp

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

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • Consider extracting the "x-deepin-SilentReplace" hint key into a shared constant to avoid typos and make future changes to the hint name easier.
  • In updateBubbleInPlace, silently returning on an invalid replaceIndex or non-replace entity may hide logic errors; adding a warning log for these early returns would make issues easier to diagnose.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider extracting the "x-deepin-SilentReplace" hint key into a shared constant to avoid typos and make future changes to the hint name easier.
- In updateBubbleInPlace, silently returning on an invalid replaceIndex or non-replace entity may hide logic errors; adding a warning log for these early returns would make issues easier to diagnose.

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.

1. Refactored BubbleModel API: replaced `isReplaceBubble()`
and `replaceBubble(BubbleItem*)` with cleaner
`replaceBubbleIndex(NotifyEntity)`, `updateBubbleInPlace()`, and
`replaceBubble(int, BubbleItem*)` methods
2. Added support for "silent replace" via `x-deepin-SilentReplace` hint:
when two bubbles match and the hint is true, the existing bubble is
updated in-place using `dataChanged` rather than full remove+insert
3. Changed `replaceBubbleIndex` to accept `NotifyEntity` instead
of `BubbleItem*`, enabling replacement logic before creating a new
`BubbleItem`
4. `replaceBubble` now handles resource cleanup by calling
`deleteLater()` on both old and new bubbles as needed
5. Removed the no longer needed `isReplaceBubble()` method, simplifying
the public interface

Log: Refactored bubble replacement mechanism; added silent in-place
update for performance

Influence:
1. Test notification replacement with and without `x-deepin-
SilentReplace` hint
2. Verify that in-place update works for silent replacements (no visual
artifacts)
3. Test replacement with different app names and bubble IDs to confirm
no false matches
4. Verify memory management: old bubbles are properly deleted via
`deleteLater()`
5. Test boundary cases: invalid replaceIndex, null bubble, concurrent
notifications
6. Verify that `dataChanged` signal correctly triggers view updates for
non-silent replacements

refactor: 优化气泡替换逻辑,支持静默替换

1. 重构 BubbleModel API:将 `isReplaceBubble()`
和 `replaceBubble(BubbleItem*)` 替换为更清晰的
`replaceBubbleIndex(NotifyEntity)`、`updateBubbleInPlace()` 和
`replaceBubble(int, BubbleItem*)`
2. 通过 `x-deepin-SilentReplace` 提示增加"静默替换"支持:当气泡匹配且提
示为 true 时,使用 `dataChanged` 原地更新现有气泡,避免完整的移除-插入
操作
3. 将 `replaceBubbleIndex` 改为接受 `NotifyEntity` 而非 `BubbleItem*`,
允许在创建 `BubbleItem` 之前执行替换逻辑
4. `replaceBubble` 现在通过调用新旧气泡的 `deleteLater()` 来处理资源清理
5. 移除不再需要的 `isReplaceBubble()` 方法,简化公开接口

Log: 重构气泡替换机制;增加静默原地更新以提升性能

Influence:
1. 测试带或不带 `x-deepin-SilentReplace` 提示的通知替换
2. 验证静默替换时原地更新正常工作(无视觉异常)
3. 测试不同应用名和气泡 ID 的替换,确认无错误匹配
4. 验证内存管理:旧气泡通过 `deleteLater()` 正确释放
5. 测试边界情况:无效的 replaceIndex、空指针、并发通知
6. 验证对于非静默替换,`dataChanged` 信号正确触发视图更新

PMS: BUG-367205
return;

// dataChanged 通知视图刷新
// 前提:内容变更不会引起气泡高度变化,否则布局不刷新(应改用 replaceBubble)。

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.

这个调用方怎么知道内容不会引起高度变化呢?

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.

3 participants