Skip to content

Commit

Permalink
Display 'Search globally' as the last sharees list element
Browse files Browse the repository at this point in the history
Signed-off-by: alex-z <[email protected]>
  • Loading branch information
allexzander committed Mar 3, 2023
1 parent 355dbd1 commit 329bca1
Show file tree
Hide file tree
Showing 11 changed files with 318 additions and 30 deletions.
1 change: 1 addition & 0 deletions src/gui/filedetails/ShareView.qml
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ ColumnLayout {
}

ShareeSearchField {
id: shareeSearchField
Layout.fillWidth: true
Layout.leftMargin: root.horizontalPadding
Layout.rightMargin: root.horizontalPadding
Expand Down
51 changes: 51 additions & 0 deletions src/gui/filedetails/ShareeDelegate.qml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,59 @@ import QtQuick.Controls 2.15
import com.nextcloud.desktopclient 1.0
import Style 1.0

import "../tray"

ItemDelegate {
id: root

text: model.display

contentItem:
RowLayout {
Layout.fillWidth: true
height: visible ? implicitHeight : 0

visible: true

Loader {
id: shareeIconLoader

Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft

active: model.icon !== ""

sourceComponent: Image {
id: shareeIcon

Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft

width: height
height: shareeLabel.height

smooth: true
antialiasing: true
mipmap: true
fillMode: Image.PreserveAspectFit

source: model.icon

sourceSize: Qt.size(shareeIcon.height * 1.0, shareeIcon.height * 1.0)

visible: true
}
}

EnforcedPlainTextLabel {
id: shareeLabel
Layout.preferredHeight: unifiedSearchResultSkeletonItemDetails.iconWidth
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft

Layout.fillWidth: true

horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
text: model.display
color: Style.ncTextColor
}
}
}
22 changes: 19 additions & 3 deletions src/gui/filedetails/ShareeSearchField.qml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ TextField {
readonly property double iconsScaleFactor: 0.6

function triggerSuggestionsVisibility() {
shareeListView.count > 0 && text !== "" ? suggestionsPopup.open() : suggestionsPopup.close();
shareeListView.count > 0 ? suggestionsPopup.open() : suggestionsPopup.close();
}

function searchGlobally() {
shareeModel.searchGlobally();
}

placeholderText: qsTr("Search for users or groups…")
Expand Down Expand Up @@ -73,7 +77,7 @@ TextField {
case Qt.Key_Enter:
case Qt.Key_Return:
if(shareeListView.currentIndex > -1) {
shareeListView.itemAtIndex(shareeListView.currentIndex).selectSharee();
shareeListView.itemAtIndex(shareeListView.currentIndex).selectItem();
event.accepted = true;
break;
}
Expand Down Expand Up @@ -219,13 +223,25 @@ TextField {
anchors.left: parent.left
anchors.right: parent.right

enabled: model.type !== Sharee.LookupServerSearchResults
hoverEnabled: model.type !== Sharee.LookupServerSearchResults

function selectSharee() {
root.shareeSelected(model.sharee);
suggestionsPopup.close();

root.clear();
}

function selectItem() {
if (model.type === Sharee.LookupServerSearch) {
shareeListView.currentIndex = -1
root.searchGlobally()
} else {
selectSharee()
}
}

onHoveredChanged: if (hovered) {
// When we set the currentIndex the list view will scroll...
// unless we tamper with the preferred highlight points to stop this.
Expand All @@ -241,7 +257,7 @@ TextField {
shareeListView.preferredHighlightBegin = savedPreferredHighlightBegin;
shareeListView.preferredHighlightEnd = savedPreferredHighlightEnd;
}
onClicked: selectSharee()
onClicked: selectItem()
}
}
}
Expand Down
78 changes: 77 additions & 1 deletion src/gui/filedetails/shareemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <QJsonArray>

#include "ocsshareejob.h"
#include "theme.h"

namespace OCC {

Expand All @@ -29,7 +30,10 @@ ShareeModel::ShareeModel(QObject *parent)
{
_searchRateLimitingTimer.setSingleShot(true);
_searchRateLimitingTimer.setInterval(500);
_searchGloballyPlaceholder.reset(new Sharee({}, tr("Search globally"), Sharee::LookupServerSearch, QStringLiteral(":/client/theme/magnifying-glass.svg")));
_searchGloballyPlaceholder->setIsIconColourful(true);
connect(&_searchRateLimitingTimer, &QTimer::timeout, this, &ShareeModel::fetch);
connect(Theme::instance(), &Theme::darkModeChanged, this, &ShareeModel::slotDarkModeChanged);
}

// ---------------------- QAbstractListModel methods ---------------------- //
Expand All @@ -48,6 +52,8 @@ QHash<int, QByteArray> ShareeModel::roleNames() const
auto roles = QAbstractListModel::roleNames();
roles[ShareeRole] = "sharee";
roles[AutoCompleterStringMatchRole] = "autoCompleterStringMatch";
roles[TypeRole] = "type";
roles[IconRole] = "icon";

return roles;
}
Expand All @@ -68,6 +74,10 @@ QVariant ShareeModel::data(const QModelIndex &index, const int role) const
case AutoCompleterStringMatchRole:
// Don't show this to the user
return QString(sharee->displayName() + " (" + sharee->shareWith() + ")");
case IconRole:
return sharee->iconUrlColoured();
case TypeRole:
return sharee->type();
case ShareeRole:
return QVariant::fromValue(sharee);
}
Expand Down Expand Up @@ -119,6 +129,12 @@ void ShareeModel::setSearchString(const QString &searchString)
return;
}

beginResetModel();
_sharees.clear();
endResetModel();

Q_EMIT shareesReady();

_searchString = searchString;
Q_EMIT searchStringChanged();

Expand Down Expand Up @@ -165,16 +181,28 @@ void ShareeModel::setShareeBlocklist(const QVariantList shareeBlocklist)
filterSharees();
}

void ShareeModel::searchGlobally()
{
setLookupMode(ShareeModel::LookupMode::GlobalSearch);
beginResetModel();
_sharees.clear();
endResetModel();

Q_EMIT shareesReady();
fetch();
}

// ------------------------- Internal data methods ------------------------- //

void ShareeModel::fetch()
{
if(!_accountState || !_accountState->account() || _searchString.isEmpty()) {
if (!_accountState || !_accountState->account() || _searchString.isEmpty()) {
qCInfo(lcShareeModel) << "Not fetching sharees for searchString: " << _searchString;
return;
}

_fetchOngoing = true;

Q_EMIT fetchOngoingChanged();

const auto shareItemTypeString = _shareItemIsFolder ? QStringLiteral("folder") : QStringLiteral("file");
Expand Down Expand Up @@ -233,9 +261,48 @@ void ShareeModel::shareesFetched(const QJsonDocument &reply)

beginResetModel();
_sharees = newSharees;
insertSearchGloballyItem(newSharees);
endResetModel();

Q_EMIT shareesReady();

setLookupMode(LookupMode::LocalSearch);
}

void ShareeModel::insertSearchGloballyItem(const QVector<ShareePtr> &newShareesFetched)
{
const auto isAlreadyInserted = std::find_if(std::begin(_sharees), std::end(_sharees), [](const ShareePtr &sharee) {
return sharee->type() == Sharee::LookupServerSearch || sharee->type() == Sharee::LookupServerSearchResults;
}) != std::end(_sharees);

if (!isAlreadyInserted) {
_sharees.push_back(_searchGloballyPlaceholder);
}

if (lookupMode() == LookupMode::GlobalSearch) {
const auto displayName = newShareesFetched.isEmpty() ? tr("No results found") : tr("Global search results");
_searchGloballyPlaceholder->setDisplayName(displayName);
_searchGloballyPlaceholder->setType(Sharee::LookupServerSearchResults);
} else {
_searchGloballyPlaceholder->setDisplayName(tr("Search globally"));
_searchGloballyPlaceholder->setType(Sharee::LookupServerSearch);
}

sortSharees();
}

void ShareeModel::sortSharees()
{
// sort _sharees such that lookup placeholder is always last
std::sort(std::begin(_sharees), std::end(_sharees), [](const auto &left, const auto &right) {
const auto isRightElementLookupPlaceholder = right->type() == Sharee::LookupServerSearch
|| right->type() == Sharee::LookupServerSearchResults;

const auto isLeftElementLookupPlaceholder = left->type() == Sharee::LookupServerSearch
|| left->type() == Sharee::LookupServerSearchResults;

return !isLeftElementLookupPlaceholder && isRightElementLookupPlaceholder;
});
}

ShareePtr ShareeModel::parseSharee(const QJsonObject &data) const
Expand Down Expand Up @@ -275,4 +342,13 @@ void ShareeModel::filterSharees()
Q_EMIT shareesReady();
}

void ShareeModel::slotDarkModeChanged()
{
for (int i = 0; i < _sharees.size(); ++i) {
if (_sharees[i]->updateIconUrl()) {
Q_EMIT dataChanged(index(i), index(i), {IconRole});
}
}
}

}
8 changes: 8 additions & 0 deletions src/gui/filedetails/shareemodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ class ShareeModel : public QAbstractListModel
enum Roles {
ShareeRole = Qt::UserRole + 1,
AutoCompleterStringMatchRole,
TypeRole,
IconRole,
};
Q_ENUM(Roles);

Expand Down Expand Up @@ -80,12 +82,16 @@ public slots:
void setSearchString(const QString &searchString);
void setLookupMode(const OCC::ShareeModel::LookupMode lookupMode);
void setShareeBlocklist(const QVariantList shareeBlocklist);
void searchGlobally();

void fetch();

private slots:
void shareesFetched(const QJsonDocument &reply);
void insertSearchGloballyItem(const QVector<ShareePtr> &newShareesFetched);
void sortSharees();
void filterSharees();
void slotDarkModeChanged();

private:
[[nodiscard]] ShareePtr parseSharee(const QJsonObject &data) const;
Expand All @@ -100,6 +106,8 @@ private slots:

QVector<ShareePtr> _sharees;
QVector<ShareePtr> _shareeBlocklist;

ShareePtr _searchGloballyPlaceholder;
};

}
2 changes: 2 additions & 0 deletions src/gui/filedetails/sharemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -998,6 +998,8 @@ void ShareModel::createNewUserGroupShareWithPassword(const ShareePtr &sharee, co
return;
}

emit startedCretingNewUserGroupShare();

_manager->createShare(_sharePath,
Share::ShareType(sharee->type()),
sharee->shareWith(),
Expand Down
1 change: 1 addition & 0 deletions src/gui/filedetails/sharemodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ class ShareModel : public QAbstractListModel
void passwordSetError(const QString &shareId, const int code, const QString &message);
void requestPasswordForLinkShare();
void requestPasswordForEmailSharee(const OCC::ShareePtr &sharee);
void startedCretingNewUserGroupShare() const;

void sharesChanged();

Expand Down
2 changes: 2 additions & 0 deletions src/gui/owncloudgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ ownCloudGui::ownCloudGui(Application *parent)

qmlRegisterUncreatableType<UnifiedSearchResultsListModel>("com.nextcloud.desktopclient", 1, 0, "UnifiedSearchResultsListModel", "UnifiedSearchResultsListModel");
qmlRegisterUncreatableType<UserStatus>("com.nextcloud.desktopclient", 1, 0, "UserStatus", "Access to Status enum");
qmlRegisterUncreatableType<Sharee>("com.nextcloud.desktopclient", 1, 0, "Sharee", "Access to Type enum");

qRegisterMetaTypeStreamOperators<Emoji>();

Expand All @@ -136,6 +137,7 @@ ownCloudGui::ownCloudGui(Application *parent)
qRegisterMetaType<UserStatus>("UserStatus");
qRegisterMetaType<SharePtr>("SharePtr");
qRegisterMetaType<ShareePtr>("ShareePtr");
qRegisterMetaType<Sharee>("Sharee");

qmlRegisterSingletonInstance("com.nextcloud.desktopclient", 1, 0, "UserModel", UserModel::instance());
qmlRegisterSingletonInstance("com.nextcloud.desktopclient", 1, 0, "UserAppsModel", UserAppsModel::instance());
Expand Down
Loading

0 comments on commit 329bca1

Please sign in to comment.