Skip to content

Commit

Permalink
Merge pull request #6064 from nextcloud/bugfix/activity-list-fixes
Browse files Browse the repository at this point in the history
Bugfix/activity list fixes
  • Loading branch information
allexzander authored Sep 22, 2023
2 parents 2660b04 + 1e9fa0a commit 767af53
Show file tree
Hide file tree
Showing 18 changed files with 361 additions and 62 deletions.
1 change: 1 addition & 0 deletions resources.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
<file>src/gui/tray/EditFileLocallyLoadingDialog.qml</file>
<file>src/gui/tray/NCBusyIndicator.qml</file>
<file>src/gui/tray/NCToolTip.qml</file>
<file>src/gui/tray/NCProgressBar.qml</file>
<file>src/gui/tray/EnforcedPlainTextLabel.qml</file>
<file>theme/Style/Style.qml</file>
<file>theme/Style/qmldir</file>
Expand Down
2 changes: 1 addition & 1 deletion src/gui/folderman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1314,7 +1314,7 @@ QStringList FolderMan::findFileInLocalFolders(const QString &relPath, const Acco
if (acc && folder->accountState()->account() != acc) {
continue;
}
if (!serverPath.startsWith(folder->remotePath()))
if (!serverPath.startsWith(folder->remotePathTrailingSlash()))
continue;

QString path = folder->cleanPath() + '/';
Expand Down
26 changes: 26 additions & 0 deletions src/gui/tray/ActivityList.qml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,19 @@ import com.nextcloud.desktopclient 1.0 as NC
ScrollView {
id: controlRoot
property alias model: sortedActivityList.sourceModel
property alias count: activityList.count
property alias atYBeginning : activityList.atYBeginning
property bool isFileActivityList: false
property int iconSize: Style.trayListItemIconSize
property int delegateHorizontalPadding: 0

property bool scrollingToTop: false

function scrollToTop() {
// Triggers activation of repeating upward flick timer
scrollingToTop = true
}

signal openFile(string filePath)
signal activityItemClicked(int index)

Expand All @@ -22,6 +31,9 @@ ScrollView {

data: NC.WheelHandler {
target: controlRoot.contentItem
onWheel: {
scrollingToTop = false
}
}

ListView {
Expand All @@ -36,6 +48,20 @@ ScrollView {
currentIndex: -1
interactive: true

Timer {
id: repeatUpFlickTimer
interval: Style.activityListScrollToTopTimerInterval
running: controlRoot.scrollingToTop
repeat: true
onTriggered: {
if (!activityList.atYBeginning) {
activityList.flick(0, Style.activityListScrollToTopVelocity)
} else {
controlRoot.scrollingToTop = false
}
}
}

highlight: Rectangle {
id: activityHover
anchors.fill: activityList.currentItem
Expand Down
44 changes: 44 additions & 0 deletions src/gui/tray/NCProgressBar.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2023 by Oleksandr Zolotov <alex@nextcloud.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/

import QtQuick 2.15
import QtQuick.Controls 2.15
import Style 1.0

ProgressBar {
id: control

background: Rectangle {
implicitWidth: Style.progressBarWidth
implicitHeight: Style.progressBarBackgroundHeight
radius: Style.progressBarRadius
color: Style.progressBarBackgroundColor
border.color: Style.progressBarBackgroundBorderColor
border.width: Style.progressBarBackgroundBorderWidth
}

contentItem: Item {
implicitWidth: Style.progressBarWidth
implicitHeight: Style.progressBarContentHeight

Rectangle {
width: control.visualPosition * parent.width
height: parent.height
radius: Style.progressBarRadius
color: Style.progressBarContentColor
border.color: Style.progressBarContentBorderColor
border.width: Style.progressBarContentBorderWidth
}
}
}
31 changes: 4 additions & 27 deletions src/gui/tray/SyncStatus.qml
Original file line number Diff line number Diff line change
Expand Up @@ -61,36 +61,13 @@ RowLayout {

Loader {
Layout.fillWidth: true
Layout.preferredHeight: Style.progressBarPreferredHeight

active: syncStatus.syncing
visible: syncStatus.syncing
active: syncStatus.syncing && syncStatus.totalFiles > 0
visible: active

sourceComponent: ProgressBar {
sourceComponent: NCProgressBar {
id: syncProgressBar

// TODO: Rather than setting all these palette colours manually,
// create a custom style and do it for all components globally.
//
// Additionally, we need to override the entire palette when we
// set one palette property, as otherwise we default back to the
// theme palette -- not the parent palette
palette {
text: Style.ncTextColor
windowText: Style.ncTextColor
buttonText: Style.ncTextColor
brightText: Style.ncTextBrightColor
highlight: Style.lightHover
highlightedText: Style.ncTextColor
light: Style.lightHover
midlight: Style.ncSecondaryTextColor
mid: Style.darkerHover
dark: Style.menuBorder
button: Style.buttonBackgroundColor
window: palette.dark // NOTE: Fusion theme uses darker window colour for the border of the progress bar
base: Style.backgroundColor
toolTipBase: Style.backgroundColor
toolTipText: Style.ncTextColor
}
value: syncStatus.syncProgress
}
}
Expand Down
70 changes: 70 additions & 0 deletions src/gui/tray/Window.qml
Original file line number Diff line number Diff line change
Expand Up @@ -851,7 +851,69 @@ ApplicationWindow {
anchors.right: trayWindowMainItem.right
}

Loader {
id: newActivitiesButtonLoader

anchors.top: activityList.top
anchors.topMargin: 5
anchors.horizontalCenter: activityList.horizontalCenter

width: Style.newActivitiesButtonWidth
height: Style.newActivitiesButtonHeight

z: 1

active: false

sourceComponent: CustomButton {
id: newActivitiesButton
hoverEnabled: true
padding: Style.smallSpacing

textColor: Style.currentUserHeaderTextColor
textColorHovered: Style.currentUserHeaderTextColor
contentsFont.bold: true
bgNormalColor: Qt.lighter(bgHoverColor, 1.25)
bgHoverColor: Style.currentUserHeaderColor
bgNormalOpacity: Style.newActivitiesBgNormalOpacity
bgHoverOpacity: Style.newActivitiesBgHoverOpacity

anchors.fill: parent

text: qsTr("New activities")

icon.source: "image://svgimage-custom-color/expand-less-black.svg" + "/" + Style.currentUserHeaderTextColor
icon.width: Style.activityLabelBaseWidth
icon.height: Style.activityLabelBaseWidth

onClicked: {
activityList.scrollToTop();
newActivitiesButtonLoader.active = false
}

Timer {
id: newActivitiesButtonDisappearTimer
interval: Style.newActivityButtonDisappearTimeout
running: newActivitiesButtonLoader.active && !newActivitiesButton.hovered
repeat: false
onTriggered: fadeoutActivitiesButtonDisappear.running = true
}

OpacityAnimator {
id: fadeoutActivitiesButtonDisappear
target: newActivitiesButton;
from: 1;
to: 0;
duration: Style.newActivityButtonDisappearFadeTimeout
loops: 1
running: false
onFinished: newActivitiesButtonLoader.active = false
}
}
}

ActivityList {
id: activityList
visible: !trayWindowMainItem.isUnifiedSearchActive
anchors.top: syncStatus.bottom
anchors.left: trayWindowMainItem.left
Expand All @@ -864,6 +926,14 @@ ApplicationWindow {
onActivityItemClicked: {
model.slotTriggerDefaultAction(index)
}
Connections {
target: activityModel
onInteractiveActivityReceived: {
if (!activityList.atYBeginning) {
newActivitiesButtonLoader.active = true;
}
}
}
}
} // Item trayWindowMainItem
}
11 changes: 9 additions & 2 deletions src/gui/tray/activitylistmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const
if (!fileName.isEmpty()) {
const auto folder = FolderMan::instance()->folder(a._folder);

const QString relPath = folder ? folder->remotePath() + fileName : fileName;
const QString relPath = folder ? folder->remotePathTrailingSlash() + fileName : fileName;

const auto localFiles = FolderMan::instance()->findFileInLocalFolders(relPath, ast->account());

Expand Down Expand Up @@ -184,7 +184,7 @@ QVariant ActivityListModel::data(const QModelIndex &index, int role) const
if (!a._file.isEmpty()) {
const auto folder = FolderMan::instance()->folder(a._folder);

QString relPath = folder ? folder->remotePath() + a._file : a._file;
QString relPath = folder ? folder->remotePathTrailingSlash() + a._file : a._file;

const auto localFiles = FolderMan::instance()->findFileInLocalFolders(relPath, ast->account());

Expand Down Expand Up @@ -636,6 +636,13 @@ void ActivityListModel::addNotificationToActivityList(const Activity &activity)
qCDebug(lcActivity) << "Notification successfully added to the notification list: " << activity._subject;
addEntriesToActivityList({activity});
_notificationLists.prepend(activity);
for (const auto &link : activity._links) {
if (link._verb == QByteArrayLiteral("POST")
|| link._verb == QByteArrayLiteral("REPLY")
|| link._verb == QByteArrayLiteral("WEB")) {
emit interactiveActivityReceived();
}
}
}

void ActivityListModel::addSyncFileItemToActivityList(const Activity &activity)
Expand Down
2 changes: 2 additions & 0 deletions src/gui/tray/activitylistmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ public slots:
void activityJobStatusCode(int statusCode);
void sendNotificationRequest(const QString &accountName, const QString &link, const QByteArray &verb, int row);

void interactiveActivityReceived();

protected:
[[nodiscard]] bool currentlyFetching() const;

Expand Down
53 changes: 53 additions & 0 deletions src/gui/tray/sortedactivitylistmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,37 @@
*/

#include "activitylistmodel.h"
#include <QVector>

#include "sortedactivitylistmodel.h"

namespace
{
struct ActivityLinksSearchResult {
bool hasPOST = false;
bool hasREPLY = false;
bool hasWEB = false;
bool hasDELETE = false;
};

ActivityLinksSearchResult searchForVerbsInLinks(const QVector<OCC::ActivityLink> &links)
{
ActivityLinksSearchResult result;
for (const auto &link : links) {
if (link._verb == QByteArrayLiteral("POST")) {
result.hasPOST = true;
} else if (link._verb == QByteArrayLiteral("REPLY")) {
result.hasREPLY = true;
} else if (link._verb == QByteArrayLiteral("WEB")) {
result.hasWEB = true;
} else if (link._verb == QByteArrayLiteral("DELETE")) {
result.hasDELETE = true;
}
}
return result;
}
}

namespace OCC {

SortedActivityListModel::SortedActivityListModel(QObject *parent)
Expand Down Expand Up @@ -44,6 +72,31 @@ bool SortedActivityListModel::lessThan(const QModelIndex &sourceLeft, const QMod
return false;
}

const auto leftActivityVerbsSearchResult = searchForVerbsInLinks(leftActivity._links);
const auto rightActivityVerbsSearchResult = searchForVerbsInLinks(rightActivity._links);

if (leftActivityVerbsSearchResult.hasPOST != rightActivityVerbsSearchResult.hasPOST) {
return leftActivityVerbsSearchResult.hasPOST;
}

if (leftActivityVerbsSearchResult.hasREPLY != rightActivityVerbsSearchResult.hasREPLY) {
return leftActivityVerbsSearchResult.hasREPLY;
}

if (leftActivityVerbsSearchResult.hasWEB != rightActivityVerbsSearchResult.hasWEB) {
return leftActivityVerbsSearchResult.hasWEB;
}

if (leftActivityVerbsSearchResult.hasDELETE != rightActivityVerbsSearchResult.hasDELETE) {
return leftActivityVerbsSearchResult.hasDELETE;
}

const auto leftActivityIsSecurityAction = leftActivity._fileAction == QStringLiteral("security");
const auto rightActivityIsSecurityAction = rightActivity._fileAction == QStringLiteral("security");
if (leftActivityIsSecurityAction != rightActivityIsSecurityAction) {
return leftActivityIsSecurityAction;
}

// Let's now check for errors as we want those near the top too
// Sync result errors go first
const auto leftSyncResultStatus = leftActivity._syncResultStatus;
Expand Down
Loading

0 comments on commit 767af53

Please sign in to comment.