Skip to content

fix: Notification bar progress indicator anomaly#1050

Open
JWWTSL wants to merge 1 commit intolinuxdeepin:masterfrom
JWWTSL:master
Open

fix: Notification bar progress indicator anomaly#1050
JWWTSL wants to merge 1 commit intolinuxdeepin:masterfrom
JWWTSL:master

Conversation

@JWWTSL
Copy link

@JWWTSL JWWTSL commented Mar 6, 2026

log: Incorrect replaces_id used when sending the “Received Successfully” notification upon completion (or failure to use the ID from the progress bar notification), causing the 99% progress notification to remain unchanged and persist on the desktop. When the status changes to complete, first read the current a.notifyID within the lock and save it as currentID. Then use this currentID as the replaces_id to send the 100% completion notification. This ensures the completion notification replaces the last progress notification (including the 99% progress notification).

pms: bug-351711

Translated with DeepL.com (free version)

Summary by Sourcery

Fix Bluetooth file transfer notifications to correctly replace in-progress toasts on completion and align gesture window maximize behavior with the generic window manager action API.

Bug Fixes:

  • Ensure the Bluetooth file transfer completion notification correctly replaces the last in-progress notification so partially completed progress bubbles do not linger.
  • Use the existing window manager toggle maximize action for gesture-based maximize/unmaximize to keep behavior consistent.

Enhancements:

  • Simplify notification handling by relying on the notification system's replace ID mechanism instead of manually closing previous notifications.

@sourcery-ai
Copy link

sourcery-ai bot commented Mar 6, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adjusts Bluetooth OBEX file transfer notifications to correctly replace the final progress notification with the completion/failed notification, and updates gesture handling to use a generic window action API for maximize/unmaximize behavior.

Sequence diagram for updated OBEX transfer notification replacement

sequenceDiagram
    participant obexAgent
    participant Notifications
    participant DesktopShell

    obexAgent->>Notifications: notifyProgress(notify, 0, filename, device, 1-99)
    Notifications-->>DesktopShell: ShowOrUpdateProgressNotification(id = notifyID, percent < 100)
    obexAgent-->>obexAgent: notifyID = notifyID

    obexAgent-->>obexAgent: lock notifyMu
    obexAgent-->>obexAgent: currentID = notifyID
    obexAgent-->>obexAgent: unlock notifyMu

    obexAgent->>Notifications: notifyProgress(notify, currentID, realFileName, deviceName, 100)
    Notifications->>DesktopShell: Notify(appId, replaces_id = currentID, iconSuccess, summary, body)
    DesktopShell-->>DesktopShell: ReplaceProgressNotification(currentID, newNotification)

    obexAgent-->>obexAgent: notifyID = newID
Loading

Class diagram for updated OBEX agent notification handling

classDiagram
    class obexAgent {
        notify notifications_Notifications
        notifyID uint32
        receiveProgress(transfer *transferObj)
        notifyProgress(notify notifications_Notifications, replaceID uint32, filename string, device string, percent int) uint32
        notifyFailed(notify notifications_Notifications, replaceID uint32, summary string) uint32
    }

    class notifications_Notifications {
        Notify(serial uint32, appName string, replacesID uint32, appIcon string, summary string, body string, actions []string, hints map_string_dbus_Variant, expireTimeout int32) (uint32, error)
        CloseNotification(serial uint32, id uint32) error
    }

    class transferObj {
        oriFilename string
        deviceName string
    }

    obexAgent --> notifications_Notifications : uses
    obexAgent --> transferObj : reads
Loading

Class diagram for gesture Manager maximizing via generic window action API

classDiagram
    class Manager {
        wm WindowManager
        doHandle4Or5FingersSwipeDown() error
        doMaximizeActiveWindow() error
        doUnMaximizeActiveWindow() error
        doMinimize() error
    }

    class WindowManagerBefore {
        MaximizeActiveWindow(display uint32) error
        UnMaximizeActiveWindow(display uint32) error
    }

    class WindowManagerAfter {
        PerformAction(display uint32, action WindowAction) error
    }

    class WindowAction {
        wmActionToggleMaximize
    }

    Manager --> WindowManagerAfter : calls PerformAction
    WindowManagerBefore <|-- WindowManagerAfter : replacedBy
Loading

File-Level Changes

Change Details Files
Ensure the Bluetooth file transfer completion notification replaces the last progress notification bubble instead of leaving a 99% progress notification lingering.
  • Capture the current progress notification ID under lock before completion and pass it to notifyProgress so the 100% notification uses the last progress bubble as replaces_id.
  • Modify notifyProgress to pass replaceID as the notification ID argument to Notify instead of always using 0, so the server replaces the existing notification instance.
  • Remove the explicit CloseNotification call before sending the completion notification, relying on replaces_id semantics instead.
bluetooth1/obex_agent.go
Ensure Bluetooth transfer failure notifications correctly replace the existing progress notification.
  • Update notifyFailed to pass replaceID as the notification ID argument to Notify so the failure notification replaces any in-progress notification.
  • Remove the pre-Notify CloseNotification call and rely on the replacement mechanism instead.
bluetooth1/obex_agent.go
Refactor gesture-based window maximize/unmaximize operations to use a unified window manager action API.
  • Replace doMaximizeActiveWindow’s direct MaximizeActiveWindow call with wm.PerformAction using wmActionToggleMaximize.
  • Replace doUnMaximizeActiveWindow’s direct UnMaximizeActiveWindow call with wm.PerformAction using wmActionToggleMaximize for symmetric handling.
gesture1/gesture_action.go

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

@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: JWWTSL

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

Copy link

@sourcery-ai sourcery-ai bot left a comment

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:

  • In the gesture manager, doMaximizeActiveWindow and doUnMaximizeActiveWindow now both call PerformAction(0, wmActionToggleMaximize), which makes them identical; if callers depend on strictly-maximize vs strictly-unmaximize semantics, this toggle-based implementation may introduce unexpected behavior and might be better handled with explicit maximize/unmaximize actions.
  • In the notification changes, CloseNotification was removed and replaceID is now passed to notify.Notify; it’s worth double-checking that replaceID is always a valid existing notification ID (or zero when starting fresh), and that the DBus notification spec implementation you use interprets this argument as replaces_id rather than as an unrelated field, to avoid leaking stale notifications or mis-threading updates.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In the gesture manager, `doMaximizeActiveWindow` and `doUnMaximizeActiveWindow` now both call `PerformAction(0, wmActionToggleMaximize)`, which makes them identical; if callers depend on strictly-maximize vs strictly-unmaximize semantics, this toggle-based implementation may introduce unexpected behavior and might be better handled with explicit maximize/unmaximize actions.
- In the notification changes, `CloseNotification` was removed and `replaceID` is now passed to `notify.Notify`; it’s worth double-checking that `replaceID` is always a valid existing notification ID (or zero when starting fresh), and that the DBus notification spec implementation you use interprets this argument as `replaces_id` rather than as an unrelated field, to avoid leaking stale notifications or mis-threading updates.

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.

log: Incorrect replaces_id used when sending the “Received Successfully” notification upon completion (or failure to use the ID from the progress bar notification), causing the 99% progress notification to remain unchanged and persist on the desktop. When the status changes to complete, first read the current `a.notifyID` within the lock and save it as `currentID`. Then use this `currentID` as the `replaces_id` to send the 100% completion notification. This ensures the completion notification replaces the last progress notification (including the 99% progress notification).

pms: bug-351711
@deepin-ci-robot
Copy link

deepin pr auto review

我对这段代码 diff 进行了审查,以下是关于语法逻辑、代码质量、代码性能和代码安全的详细分析及改进建议:

总体评价

这段代码主要涉及蓝牙文件传输 (OBEX) 代理和手势管理器的逻辑修改。整体代码风格符合 Go 语言规范,修改主要集中在通知机制的优化和窗口管理动作的统一。代码逻辑清晰,没有明显的安全隐患,但在通知处理逻辑上存在微小的优化空间。


1. 文件:bluetooth1/obex_agent.go

修改点 1:版权年份更新

-// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd.
+// SPDX-FileCopyrightText: 2018 - 2026 UnionTech Software Technology Co., Ltd.
  • 分析:仅更新了版权年份。
  • 建议:无。这是常规维护操作。

修改点 2:传输完成时的通知更新 (receiveProgress 函数)

- newID := a.notifyProgress(a.notify, a.notifyID, realFileName, transfer.deviceName, 100)
+ // Use the last progress notification id as replaces_id so
+ // the progress bubble (e.g. 99%) won't linger after completion.
+ newID := a.notifyProgress(a.notify, currentID, realFileName, transfer.deviceName, 100)
  • 语法逻辑
    • 代码将 a.notifyID 替换为 currentID。根据上下文推断,currentID 应该是当前正在显示的进度条通知 ID。
    • 潜在问题:在提供的 diff 片段中,没有看到 currentID 变量的定义或赋值。如果 currentID 未定义,编译会失败;如果它是局部变量,需要确保它在调用 notifyProgress 之前已被正确赋值为最新的通知 ID(即 a.notifyID)。
  • 代码质量
    • 添加的注释非常有价值,解释了为什么要使用 replaceID(为了避免 99% 的进度条残留),提高了代码可读性。
  • 改进建议
    • 请确保 currentID 变量在函数作用域内已定义,且值正确(例如:currentID := a.notifyID)。

修改点 3:通知发送逻辑优化 (notifyProgressnotifyFailed 函数)

- notify.CloseNotification(0, replaceID)
  ...
- 0,
+ replaceID,
  • 语法逻辑
    • 移除了显式的 CloseNotification 调用。
    • Notify 函数调用中的 replaces_id 参数从 0(表示不替换任何通知)改为 replaceID
  • 代码质量
    • 改进点:这是一个非常好的改动。在 DBus 通知规范中,Notify 方法的 replaces_id 参数用于指定要替换的现有通知 ID。通过传入 replaceID,新的通知会自动替换旧通知,而不是先关闭旧通知再打开新通知。
    • 效果:这消除了旧通知关闭和新通知弹出之间的时间差,避免了通知栏闪烁或通知顺序错乱的问题,用户体验更流畅。
  • 代码性能
    • 提升:减少了一次 DBus 方法调用(CloseNotification),降低了 IPC(进程间通信)开销,虽然微小但属于有效优化。

2. 文件:gesture1/gesture_action.go

修改点 1:版权年份更新

  • 分析:同上,无建议。

修改点 2:窗口最大化/还原手势逻辑统一

 func (m *Manager) doMaximizeActiveWindow() error {
- return m.wm.MaximizeActiveWindow(0)
+ return m.wm.PerformAction(0, wmActionToggleMaximize)
 }

 func (m *Manager) doUnMaximizeActiveWindow() error {
- return m.wm.UnMaximizeActiveWindow(0)
+ return m.wm.PerformAction(0, wmActionToggleMaximize)
 }
  • 语法逻辑
    • 将原本独立的 MaximizeActiveWindow(最大化)和 UnMaximizeActiveWindow(还原)调用,统一改为 PerformAction 并传入 wmActionToggleMaximize(切换最大化状态)。
    • 逻辑变化:原来的逻辑是"执行最大化"和"执行还原",现在的逻辑变成了"切换最大化状态"。
    • 风险提示:这种修改改变了函数的语义。
      • 对于 doMaximizeActiveWindow:如果窗口已经是最大化状态,调用 ToggleMaximize 会将其还原。这与函数名"最大化"不符。
      • 对于 doUnMaximizeActiveWindow:如果窗口未最大化,调用 ToggleMaximize 会将其最大化。这与函数名"还原"不符。
  • 代码质量
    • 优点:代码复用性提高,统一了接口。
    • 缺点:牺牲了语义的准确性。如果手势触发器期望"四指上滑一定是最大化",那么这种修改可能导致意外行为(即如果已经是最大化,再次上滑会还原)。
  • 改进建议
    • 确认需求:请确认产品需求是否希望将这两个手势改为"切换"行为。如果是,建议重命名函数为 doToggleMaximizeActiveWindow 以准确反映其行为,或者保持函数名不变但在文档中说明其切换行为。
    • 如果需要保持原有语义(强制最大化/强制还原):建议检查 wm (Window Manager) 接口是否有类似 ForceMaximizeSetMaximized(true) 的方法,或者确保 PerformAction 有对应的动作常量(如 wmActionMaximizewmActionUnmaximize),而不是共用 Toggle

总结与建议

  1. 蓝牙部分 (obex_agent.go):修改得很好,优化了通知机制,减少了闪烁和 IPC 调用。唯一需要注意的是确保 currentID 变量在上下文中是有效的。

  2. 手势部分 (gesture_action.go):代码修改在语法上没问题,但逻辑语义发生了重大变化(从"设置状态"变为"切换状态")。这可能会影响用户体验(例如:用户连续做两次"最大化"手势,窗口会变成"还原"状态)。

    • 强烈建议:与产品经理或设计团队确认,是否确实需要将"最大化"和"还原"手势都改为"切换"行为。如果不需要,请回滚此修改或寻找非 Toggle 的 API。
  3. 安全性:未发现明显的安全漏洞。

  4. 代码风格:代码风格统一,符合 Go 语言惯例。注释清晰。

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.

2 participants