fix: improve notification bubble panel hide animation#1490
fix: improve notification bubble panel hide animation#1490qxp930712 wants to merge 1 commit intolinuxdeepin:masterfrom
Conversation
Changed the bubble panel visibility logic to include a 400ms delay before hiding when there are no notifications. This prevents the panel from disappearing abruptly when the last bubble is removed. The QML ListView now includes a remove transition with smooth exit animation for bubbles. Added QTimer include for delayed hide functionality. Modified the ListView height calculation to use maximum of contentHeight and childrenRect.height to ensure proper layout during animations. Implemented a sequential animation for bubble removal with x-axis slide- out effect. Log: Improved notification bubble animations with smoother hide effects Influence: 1. Test notification bubble appearance and disappearance 2. Verify panel remains visible during bubble removal animations 3. Check that multiple bubbles animate correctly 4. Test edge cases with rapid notification additions/removals 5. Verify panel properly hides after all bubbles are removed 6. Test animation timing and smoothness PMS: BUG-284659
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: qxp930712 The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
Reviewer's GuideImproves the notification bubble panel’s disappearance behavior by delaying panel hide until after a 400ms bubble removal animation, and adjusts ListView sizing to better accommodate animated content. Sequence diagram for delayed hide of notification bubble panelsequenceDiagram
participant NotificationSource
participant BubbleModel
participant BubblePanel
participant QML_BubbleView
participant QTimer
NotificationSource->>BubbleModel: removeNotification(id)
BubbleModel-->>BubblePanel: bubbleCountChanged()
BubblePanel->>BubblePanel: onBubbleCountChanged()
BubblePanel->>BubblePanel: isEmpty = m_bubbles.items().isEmpty()
BubblePanel->>BubblePanel: visible = !isEmpty && enabled()
alt visible is true
BubblePanel->>BubblePanel: setVisible(true)
BubblePanel-->>QML_BubbleView: remain visible
else visible is false
BubblePanel->>QTimer: singleShot(400ms, this, lambda)
QML_BubbleView->>QML_BubbleView: ListView remove Transition
QML_BubbleView->>QML_BubbleView: SequentialAnimation
QML_BubbleView->>QML_BubbleView: ListView.delayRemove = true
QML_BubbleView->>QML_BubbleView: NumberAnimation x -> 360 (400ms)
QML_BubbleView->>QML_BubbleView: ListView.delayRemove = false
QTimer-->>BubblePanel: timeout after 400ms
BubblePanel->>BubblePanel: setVisible(false)
end
Updated class diagram for BubblePanel notification visibility logicclassDiagram
class BubblePanel {
- m_bubbles
+ onNotificationStateChanged(id, processedType) void
+ onBubbleCountChanged() void
+ addBubble(id) void
+ setVisible(visible) void
+ enabled() bool
}
class QTimer {
+ singleShot(msec, receiver, slot) void
}
BubblePanel ..> QTimer : uses_singleShot_for_delayed_hide
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- The QTimer::singleShot in onBubbleCountChanged() will hide the panel unconditionally after 400ms even if new bubbles arrived in the meantime; consider checking the current bubble count/enabled state in the lambda or cancelling/reusing a single timer to avoid hiding an active panel.
- In the ListView remove transition, the hardcoded value
to: 360for the x animation couples the animation to a magic number; usingto: widthor a shared constant would make the slide-out behavior robust to future width/layout changes.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The QTimer::singleShot in onBubbleCountChanged() will hide the panel unconditionally after 400ms even if new bubbles arrived in the meantime; consider checking the current bubble count/enabled state in the lambda or cancelling/reusing a single timer to avoid hiding an active panel.
- In the ListView remove transition, the hardcoded value `to: 360` for the x animation couples the animation to a magic number; using `to: width` or a shared constant would make the slide-out behavior robust to future width/layout changes.
## Individual Comments
### Comment 1
<location path="panels/notification/bubble/bubblepanel.cpp" line_range="114-120" />
<code_context>
{
bool isEmpty = m_bubbles->items().isEmpty();
- setVisible(!isEmpty && enabled());
+ const bool visible = !isEmpty && enabled();
+ if (!visible) {
+ QTimer::singleShot(400, this, [this]() {
+ setVisible(false);
+ });
+ } else {
+ setVisible(visible);
+ }
}
</code_context>
<issue_to_address>
**issue (bug_risk):** Delayed hide timer can incorrectly hide the panel after it becomes visible again.
Because `QTimer::singleShot` is unconditional, a call with `visible == false` will still invoke `setVisible(false)` after 400 ms even if a later call with `visible == true` has already made the panel visible. This creates a race where a stale hide timer overrides a newer show.
To fix this, either cancel/gate the hide in the lambda (e.g. re-check `!m_bubbles->items().isEmpty()` and `enabled()` before calling `setVisible(false)`), or track a hide request ID/sequence and only apply the latest one.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| const bool visible = !isEmpty && enabled(); | ||
| if (!visible) { | ||
| QTimer::singleShot(400, this, [this]() { | ||
| setVisible(false); | ||
| }); | ||
| } else { | ||
| setVisible(visible); |
There was a problem hiding this comment.
issue (bug_risk): Delayed hide timer can incorrectly hide the panel after it becomes visible again.
Because QTimer::singleShot is unconditional, a call with visible == false will still invoke setVisible(false) after 400 ms even if a later call with visible == true has already made the panel visible. This creates a race where a stale hide timer overrides a newer show.
To fix this, either cancel/gate the hide in the lambda (e.g. re-check !m_bubbles->items().isEmpty() and enabled() before calling setVisible(false)), or track a hide request ID/sequence and only apply the latest one.
deepin pr auto review这份代码变更主要是为了优化通知气泡面板在气泡数量变化时的显示/隐藏逻辑,并添加了气泡移除时的动画效果。以下是对代码的审查意见: 1. 代码逻辑与功能审查BubblePanel.cpp 部分:
main.qml 部分:
2. 代码质量与规范
3. 代码性能
4. 代码安全
改进建议代码示例针对 BubblePanel.cpp 的改进(防止闪烁和规范头文件): // 头文件中
#include <QTimer> // 修正头文件大小写
// 类定义中增加成员变量
// private:
// QTimer *m_hideTimer;
// 构造函数中初始化
// m_hideTimer = new QTimer(this);
// m_hideTimer->setSingleShot(true);
// connect(m_hideTimer, &QTimer::timeout, this, [this]() { setVisible(false); });
void BubblePanel::onBubbleCountChanged()
{
bool isEmpty = m_bubbles->items().isEmpty();
const bool visible = !isEmpty && enabled();
if (visible) {
// 如果需要显示,立即停止可能存在的隐藏定时器,防止闪烁
if (m_hideTimer->isActive()) {
m_hideTimer->stop();
}
setVisible(true);
} else {
// 如果需要隐藏,启动定时器
// 如果定时器已经在运行,start 会重置时间,这也是合理的行为
m_hideTimer->start(400);
}
}针对 main.qml 的改进(去除魔法数字): // Window 或 ListView 内部定义属性
readonly property int bubbleWidth: 360
readonly property int animationDuration: 400
readonly property int hideDelayDuration: 400 // 如果QML中也需要用到延迟逻辑
ListView {
id: bubbleView
width: bubbleWidth
// ...
remove: Transition {
SequentialAnimation {
PropertyAction {
property: "ListView.delayRemove"
value: true
}
ParallelAnimation {
NumberAnimation {
property: "x"
to: bubbleWidth // 使用属性替代魔法数字
duration: animationDuration
easing.type: Easing.InExpo
}
}
PropertyAction {
property: "ListView.delayRemove"
value: false
}
}
}
}总结这段代码主要改进了 UI 交互体验。主要的改进点在于 C++ 端处理异步隐藏逻辑时的竞态条件(防止闪烁),以及对硬编码常量的提取。QML 端的动画逻辑实现正确,但需注意 |
| { | ||
| bool isEmpty = m_bubbles->items().isEmpty(); | ||
| setVisible(!isEmpty && enabled()); | ||
| const bool visible = !isEmpty && enabled(); |
There was a problem hiding this comment.
这个代码要优化下吧,例如它放在qml端,
另外,这个在暂存区域显示的时候,enabled()为false,实际上它不需要延迟隐藏,
Changed the bubble panel visibility logic to include a 400ms delay before hiding when there are no notifications. This prevents the panel from disappearing abruptly when the last bubble is removed. The QML ListView now includes a remove transition with smooth exit animation for bubbles.
Added QTimer include for delayed hide functionality. Modified the ListView height calculation to use maximum of contentHeight and childrenRect.height to ensure proper layout during animations. Implemented a sequential animation for bubble removal with x-axis slide- out effect.
Log: Improved notification bubble animations with smoother hide effects
Influence:
PMS: BUG-284659
Summary by Sourcery
Improve notification bubble panel visibility and removal animations to provide a smoother hide experience when bubbles are cleared.
New Features:
Bug Fixes:
Enhancements: