Skip to content

Conversation

@ComixHe
Copy link
Contributor

@ComixHe ComixHe commented Jan 30, 2026

Only enable action buttons when extension hint exists or it's not in the notification center

Pms: BUG-333027
Log: Adjust the activation logic for the notification button

Summary by Sourcery

Bug Fixes:

  • Ensure notification action buttons are only enabled when a corresponding extension hint exists or when the notification is not in the notification center.

@ComixHe ComixHe requested a review from 18202781743 January 30, 2026 09:43
@sourcery-ai
Copy link

sourcery-ai bot commented Jan 30, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adjusts notification action enablement so that action buttons are only interactive when there is a matching extension hint or when the notification is not in the notification center, and wires this enabled state through to the QML button.

Sequence diagram for computing and applying notification action enabled state

sequenceDiagram
    actor User
    participant NotificationSystem
    participant AppNotifyItem
    participant NotifyEntity
    participant QmlEngine
    participant NotifyActionQml
    participant ActionButtonQml

    NotificationSystem->>AppNotifyItem: create or update notification
    AppNotifyItem->>NotifyEntity: hints()
    NotifyEntity-->>AppNotifyItem: hints
    AppNotifyItem->>NotifyEntity: processedType()
    NotifyEntity-->>AppNotifyItem: type

    AppNotifyItem->>AppNotifyItem: updateActions()
    AppNotifyItem->>AppNotifyItem: compute enabled =
    AppNotifyItem->>AppNotifyItem: hints contains x-deepin-action-id
    AppNotifyItem->>AppNotifyItem: or type != Processed
    AppNotifyItem-->>QmlEngine: actionData list with id, text, enabled

    QmlEngine-->>NotifyActionQml: set actionData
    NotifyActionQml->>ActionButtonQml: bind text = actionData.text
    NotifyActionQml->>ActionButtonQml: bind enabled = actionData.enabled

    User->>ActionButtonQml: click
    ActionButtonQml->>QmlEngine: trigger action only if enabled == true
Loading

Class diagram for updated notification action enablement logic

classDiagram
    class AppNotifyItem {
        - NotifyEntity m_entity
        + void updateActions()
    }

    class NotifyEntity {
        + QMap~QString, QVariant~ hints()
        + ProcessedType processedType()
    }

    class ProcessedType {
        <<enumeration>>
        Processed
        OtherStates
    }

    class NotifyActionQml {
        + var actionData
        + void bindText()
        + void bindEnabled()
    }

    AppNotifyItem --> NotifyEntity : uses
    NotifyEntity --> ProcessedType : returns
    AppNotifyItem --> NotifyActionQml : provides actionData

    %% Key logic inside AppNotifyItem.updateActions
    class AppNotifyItemUpdateActionsLogic {
        + void buildActionItem(QString id, QString text, QMap~QString, QVariant~ hints, ProcessedType type)
        + bool isActionEnabled(QString id, QMap~QString, QVariant~ hints, ProcessedType type)
    }

    AppNotifyItem ..> AppNotifyItemUpdateActionsLogic : contains logic

    class ActionButtonQml {
        + var actionData
        + string text
        + bool enabled
    }

    NotifyActionQml --> ActionButtonQml : configures
Loading

File-Level Changes

Change Details Files
Gate notification action invocation on presence of extension hints or on the notification not being in the processed (notification center) state.
  • Retrieve notification hints and processed type from the NotifyEntity before building the actions list.
  • When constructing each action item, compute an enabled flag based on whether hints contain an extension key for the action or the entity type is not Processed.
  • Include this enabled flag in the QVariantMap describing each action so it is available to the UI layer.
panels/notification/center/notifyitem.cpp
Propagate the backend enabled state to the notification action button in QML.
  • Bind the QML button's enabled property to actionData.enabled, defaulting to false when actionData is missing.
  • Ensure the visual interaction state of action buttons matches the backend eligibility logic for invoking actions.
panels/notification/plugin/NotifyAction.qml

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

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:

  • The C++ comment // we only allow to invoke the action if we have the extension hint and it's not in the notify center. doesn't match the implemented || logic (enabled when hint exists OR not in notify center); consider updating the comment to reflect the actual condition.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The C++ comment `// we only allow to invoke the action if we have the extension hint and it's not in the notify center.` doesn't match the implemented `||` logic (enabled when hint exists OR not in notify center); consider updating the comment to reflect the actual condition.

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.

…button

Only enable action buttons when extension hint exists
or it's not in the notification center

Pms: BUG-333027
Log: Adjust the activation logic for the notification button
Signed-off-by: ComixHe <heyuming@deepin.org>
@deepin-ci-robot
Copy link

deepin pr auto review

这段代码的修改主要是为了增强通知中心中操作按钮的控制逻辑,使其能够根据通知的状态和提示信息来决定按钮是否可用。以下是对这段代码的详细审查和改进建议:

1. 代码逻辑与功能审查

功能概述
修改在 AppNotifyItem::updateActions() 中增加了对按钮 enabled 状态的判断逻辑,并在 QML 文件中应用了这个状态。逻辑是:如果通知包含特定的 x-deepin-action-{id} 提示,或者通知未被处理(!processed),则允许操作;否则禁用按钮。

逻辑分析

  • hints.contains("x-deepin-action-" + id):检查是否存在特定于 Deepin 桌面环境的扩展提示。这是一种很好的扩展机制,允许应用声明哪些操作是有效的。
  • !processed:如果通知尚未被处理,则允许操作。这表明一旦通知被标记为已处理,操作可能不再相关或有效。

潜在问题

  • 逻辑冲突:当 processedtrue 时,即使 hints 中包含对应的 action,按钮也会被禁用(因为 || !processed 这一部分为 false)。如果需求是"只要有 hint 就始终启用",那么逻辑应该是 hints.contains(...) || (!processed && !hints.contains(...))。但根据注释 "we only allow to invoke the action if we have the extension hint and it's not in the notify center",当前逻辑 A || !B(A=有hint, B=processed)意味着:
    • 如果有 hint (A=true),启用。
    • 如果没有 hint (A=false),检查是否未处理 (B=false)。如果未处理,启用;如果已处理,禁用。
    • 这看起来符合注释意图。

2. 代码质量与可读性

优点

  • 添加了清晰的注释解释了复杂的布尔逻辑。
  • 使用了 auto 关键字简化了类型声明(C++11 特性)。

改进建议

  • 魔法字符串"x-deepin-action-" + id 是一个硬编码的字符串前缀。建议将其定义为类级别的静态常量,例如:

    static const QLatin1String HINT_PREFIX = QLatin1String("x-deepin-action-");
    // 使用时
    hints.contains(HINT_PREFIX + id)

    这样便于维护和统一修改。

  • 变量命名array 这个名字过于通用,建议改为更具描述性的名称,如 actionListresultActions

3. 代码性能

  • 性能分析
    • m_entity.hints()m_entity.processed() 的调用开销取决于 m_entity 的实现。如果这两个方法涉及深拷贝或复杂计算,建议检查是否可以缓存结果或通过引用传递。
    • hints.contains() 对于 QVariantMapQHash 来说通常是 O(1) 或 O(log n) 的操作,性能影响不大。
    • 在循环中拼接字符串 "x-deepin-action-" + id 会产生临时字符串对象。如果 actions 数组很大,可能会有轻微性能影响。

改进建议

  • 如果 hints 是一个 QVariantMapcontains 操作是 O(log n)。如果是 QHash,则是 O(1)。确保使用合适的容器。
  • 可以考虑在循环外提取 hintsprocessed,避免在循环内重复调用(虽然当前代码已经这样做了)。

4. 代码安全

  • 类型安全
    • idtextactions 数组中取出,但代码没有检查它们的类型。如果 actions 包含非字符串类型,可能会导致运行时错误。
    • hints.contains() 的参数类型应该与 hints 的键类型一致。如果 hints 的键是 QString,确保 id 也是 QString 或能隐式转换。

改进建议

  • 添加类型检查:
    if (!id.canConvert<QString>() || !text.canConvert<QString>()) {
        continue; // 跳过无效项
    }

5. 综合改进后的代码示例

void AppNotifyItem::updateActions()
{
    const QStringList actions = m_entity.actions();
    if (actions.isEmpty()) {
        return;
    }

    // 定义常量前缀
    static const QLatin1String ACTION_HINT_PREFIX = QLatin1String("x-deepin-action-");
    
    // 提前获取 hints 和 processed 状态
    const auto hints = m_entity.hints();
    const bool isProcessed = m_entity.processed();
    
    QVariantList actionList;
    for (int i = 0; i < actions.size(); i += 2) {
        const auto id = actions[i];
        const auto text = actions[i + 1];
        
        // 类型安全检查
        if (!id.canConvert<QString>() || !text.canConvert<QString>()) {
            continue;
        }
        
        QVariantMap item;
        item["id"] = id.toString();
        item["text"] = text.toString();
        
        // 按钮启用逻辑:有扩展提示 或 通知未被处理
        item["enabled"] = hints.contains(ACTION_HINT_PREFIX + id.toString()) || !isProcessed;
        
        actionList.append(item);
    }
    
    // 更新 UI
    // ...
}

6. QML 部分审查

QML 代码的修改很直接,正确地将 enabled 属性绑定到了 actionData.enabled。没有明显问题,但可以添加默认值保护:

enabled: actionData ? (actionData.enabled !== undefined ? actionData.enabled : false) : false

这样可以更明确地处理 enabled 未定义的情况。

总结

这段代码的修改在逻辑上是合理的,但可以通过以下方式改进:

  1. 使用常量代替魔法字符串。
  2. 改进变量命名以提高可读性。
  3. 添加类型安全检查。
  4. 考虑性能优化(如减少临时字符串创建)。

这些改进将使代码更健壮、更易维护,同时保持原有功能不变。

@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: 18202781743, ComixHe

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

@18202781743 18202781743 merged commit 57d0559 into linuxdeepin:master Jan 31, 2026
10 of 11 checks passed
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.

3 participants