diff --git a/panels/dock/tray/package/StashedItemPositioner.qml b/panels/dock/tray/package/StashedItemPositioner.qml index 0179c55ab..cc4b595ed 100644 --- a/panels/dock/tray/package/StashedItemPositioner.qml +++ b/panels/dock/tray/package/StashedItemPositioner.qml @@ -8,7 +8,13 @@ import org.deepin.ds.dock.tray 1.0 as DDT Control { id: root - property bool itemVisible: !DDT.TraySortOrderModel.isUpdating + property bool itemVisible: { + // Startup phase: hide all items without triggering animations + if (DDT.TraySortOrderModel.startupPhase) { + return false + } + return !DDT.TraySortOrderModel.isUpdating + } spacing: 0 padding: 0 @@ -21,6 +27,12 @@ Control { NumberAnimation { duration: 200; easing.type: Easing.OutQuad } } states: [ + State { + name: "startup-hidden" + when: DDT.TraySortOrderModel.startupPhase + PropertyChanges { target: root; opacity: 0.0 } + PropertyChanges { target: root; visible: false } + }, State { when: root.itemVisible PropertyChanges { target: root; opacity: 1.0 } @@ -33,6 +45,14 @@ Control { } ] transitions: [ + Transition { + from: "startup-hidden" + to: "*" + SequentialAnimation { + PropertyAction { target: root; property: "visible"; value: true } + NumberAnimation { property: "opacity"; duration: 300; easing.type: Easing.OutQuad } + } + }, Transition { to: "item-invisible" SequentialAnimation { diff --git a/panels/dock/tray/package/TrayItemPositioner.qml b/panels/dock/tray/package/TrayItemPositioner.qml index 47f935804..1a9fa8870 100644 --- a/panels/dock/tray/package/TrayItemPositioner.qml +++ b/panels/dock/tray/package/TrayItemPositioner.qml @@ -9,6 +9,11 @@ import org.deepin.ds.dock.tray 1.0 as DDT Control { id: root property bool itemVisible: { + // Startup phase: hide all items without triggering animations + if (DDT.TraySortOrderModel.startupPhase) { + return false + } + // Update phase: hide to avoid layout flicker if (DDT.TraySortOrderModel.isUpdating) { return false } @@ -54,6 +59,13 @@ Control { NumberAnimation { duration: 200; easing.type: collapsed || !DDT.TraySortOrderModel.isCollapsing ? Easing.OutQuad : Easing.InQuad } } states: [ + State { + name: "startup-hidden" + when: DDT.TraySortOrderModel.startupPhase + PropertyChanges { target: root; opacity: 0.0 } + PropertyChanges { target: root; scale: 0.8 } + PropertyChanges { target: root; visible: false } + }, State { when: root.itemVisible PropertyChanges { target: root; opacity: 1.0 } @@ -68,6 +80,17 @@ Control { } ] transitions: [ + Transition { + from: "startup-hidden" + to: "*" + SequentialAnimation { + PropertyAction { target: root; property: "visible"; value: true } + ParallelAnimation { + NumberAnimation { property: "opacity"; from: 0.0; to: 1.0; duration: 300; easing.type: Easing.OutQuad } + NumberAnimation { property: "scale"; from: 0.8; to: 1.0; duration: 300; easing.type: Easing.OutBack } + } + } + }, Transition { to: "item-invisible" SequentialAnimation { diff --git a/panels/dock/tray/traysortordermodel.cpp b/panels/dock/tray/traysortordermodel.cpp index 5d2a7b06a..995275b35 100644 --- a/panels/dock/tray/traysortordermodel.cpp +++ b/panels/dock/tray/traysortordermodel.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -63,6 +64,18 @@ TraySortOrderModel::TraySortOrderModel(QObject *parent) qDebug() << "actionsAlwaysVisibleChanged"; updateVisualIndexes(); }); + + // Startup phase timer: end startup phase after 500ms of no new surfaces + m_startupTimer = new QTimer(this); + m_startupTimer->setSingleShot(true); + m_startupTimer->setInterval(500); + connect(m_startupTimer, &QTimer::timeout, this, [this](){ + if (m_startupPhase) { + qDebug() << "Startup phase ended, showing all tray items"; + setStartupPhase(false); + } + }); + updateVisualIndexes(); } @@ -577,6 +590,24 @@ void TraySortOrderModel::onAvailableSurfacesChanged() updateVisualIndexes(); // and also save the current sort order saveDataToDConfig(); + + // During startup phase, reset timer on each new surface to batch updates + if (m_startupPhase && m_startupTimer) { + m_startupTimer->start(); + } +} + +bool TraySortOrderModel::startupPhase() const +{ + return m_startupPhase; +} + +void TraySortOrderModel::setStartupPhase(bool phase) +{ + if (m_startupPhase == phase) + return; + m_startupPhase = phase; + emit startupPhaseChanged(phase); } void TraySortOrderModel::handlePluginVisibleChanged(const QString &surfaceId, bool visible) diff --git a/panels/dock/tray/traysortordermodel.h b/panels/dock/tray/traysortordermodel.h index 69b1a57ef..21ae1d7c0 100644 --- a/panels/dock/tray/traysortordermodel.h +++ b/panels/dock/tray/traysortordermodel.h @@ -7,6 +7,7 @@ #include "constants.h" #include #include +#include namespace Dtk { namespace Core { @@ -26,6 +27,7 @@ class TraySortOrderModel : public QStandardItemModel Q_PROPERTY(bool isCollapsing MEMBER m_isCollapsing NOTIFY isCollapsingChanged) Q_PROPERTY(bool actionsAlwaysVisible MEMBER m_actionsAlwaysVisible NOTIFY actionsAlwaysVisibleChanged) Q_PROPERTY(bool isUpdating MEMBER m_isUpdating NOTIFY isUpdatingChanged) + Q_PROPERTY(bool startupPhase READ startupPhase WRITE setStartupPhase NOTIFY startupPhaseChanged) Q_PROPERTY(QList availableSurfaces MEMBER m_availableSurfaces NOTIFY availableSurfacesChanged) Q_PROPERTY(QString stagedSurfaceId MEMBER m_stagedSurfaceId NOTIFY stagedDropChanged) Q_PROPERTY(int stagedVisualIndex MEMBER m_stagedVisualIndex NOTIFY stagedDropChanged) @@ -74,12 +76,17 @@ class TraySortOrderModel : public QStandardItemModel Q_INVOKABLE void stageDropPosition(const QString &surfaceId, int visualIndex); Q_INVOKABLE void commitStagedDrop(); Q_INVOKABLE void clearStagedDrop(); + + // Startup phase control + bool startupPhase() const; + Q_INVOKABLE void setStartupPhase(bool phase); signals: void collapsedChanged(bool); void isCollapsingChanged(bool); void actionsAlwaysVisibleChanged(bool); void isUpdatingChanged(bool); + void startupPhaseChanged(bool); void visualItemCountChanged(int); void availableSurfacesChanged(const QList &); void stagedDropChanged(); @@ -90,7 +97,9 @@ class TraySortOrderModel : public QStandardItemModel bool m_isCollapsing = false; bool m_actionsAlwaysVisible = false; bool m_isUpdating = false; + bool m_startupPhase = true; std::unique_ptr m_dconfig; + QTimer *m_startupTimer = nullptr; // this is for the plugins that currently available. QList m_availableSurfaces; // these are the sort order data source, it might contain items that are no longer existed.