Skip to content

Commit

Permalink
Merge pull request #7339 from nextcloud/feature/distinguisable-shares
Browse files Browse the repository at this point in the history
Make shares distinguishable if there are sharees with the same display name
  • Loading branch information
mgallien authored Oct 18, 2024
2 parents d228d85 + e366042 commit de22334
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 7 deletions.
65 changes: 59 additions & 6 deletions src/gui/filedetails/sharemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ QVariant ShareModel::data(const QModelIndex &index, const int role) const
{
Q_ASSERT(checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::ParentIsInvalid));

const auto share = _shares.at(index.row());
const auto shareIdx = index.row();
const auto share = _shares.at(shareIdx);

if (!share) {
return {};
Expand Down Expand Up @@ -138,7 +139,7 @@ QVariant ShareModel::data(const QModelIndex &index, const int role) const

switch (role) {
case Qt::DisplayRole:
return displayStringForShare(share);
return displayStringForShare(share, _duplicateDisplayNameShareIndices.contains(shareIdx));
case ShareRole:
return QVariant::fromValue(share);
case ShareTypeRole:
Expand Down Expand Up @@ -486,6 +487,41 @@ void ShareModel::slotSharesFetched(const QList<SharePtr> &shares)
slotAddShare(share);
}

// Perform forward pass on shares and check for duplicate display names; store these indeces so
// we can check for these and display the specific user identifier in the display string later
_duplicateDisplayNameShareIndices.clear();
const auto shareCount = _shares.count();
for (auto i = 0; i < shareCount; ++i) {
if (_duplicateDisplayNameShareIndices.contains(i)) {
continue;
}

const auto sharee = _shares.at(i)->getShareWith();
if (sharee == nullptr) {
continue;
}

const auto duplicateIndices = QSharedPointer<QSet<unsigned int>>::create();
const auto handleDuplicateIndex = [this, duplicateIndices](const unsigned int idx) {
duplicateIndices->insert(idx);
_duplicateDisplayNameShareIndices[idx] = duplicateIndices;
const auto targetIdx = index(idx);
dataChanged(targetIdx, targetIdx, {Qt::DisplayRole});
};

for (auto j = i + 1; j < shareCount; ++j) {
const auto otherSharee = _shares.at(j)->getShareWith();
if (otherSharee == nullptr || sharee->format() != otherSharee->format()) {
continue;
}
handleDuplicateIndex(j);
}

if (!duplicateIndices->isEmpty()) {
handleDuplicateIndex(i);
}
}

handleLinkShare();
}

Expand Down Expand Up @@ -611,10 +647,26 @@ void ShareModel::slotRemoveShareWithId(const QString &shareId)
const auto sharee = share->getShareWith();
slotRemoveSharee(sharee);

beginRemoveRows({}, shareIndex.row(), shareIndex.row());
_shares.removeAt(shareIndex.row());
const auto shareRow = shareIndex.row();
beginRemoveRows({}, shareRow, shareRow);
_shares.removeAt(shareRow);
endRemoveRows();

// Handle display name duplicates now. First remove the index from the bucket it was in; then,
// check if this removal means the remaining index in the bucket is no longer a duplicate.
// If this is the case then handle the update for this item too.
const auto duplicateShares = _duplicateDisplayNameShareIndices.value(shareRow);
if (duplicateShares) {
duplicateShares->remove(shareRow);
if (duplicateShares->count() == 1) {
const auto noLongerDuplicateIndex = *(duplicateShares->begin());
_duplicateDisplayNameShareIndices.remove(noLongerDuplicateIndex);
const auto noLongerDuplicateModelIndex = index(noLongerDuplicateIndex);
Q_EMIT dataChanged(noLongerDuplicateModelIndex, noLongerDuplicateModelIndex, {Qt::DisplayRole});
}
_duplicateDisplayNameShareIndices.remove(shareRow);
}

handleLinkShare();

Q_EMIT sharesChanged();
Expand Down Expand Up @@ -642,7 +694,7 @@ void ShareModel::slotRemoveSharee(const ShareePtr &sharee)
Q_EMIT shareesChanged();
}

QString ShareModel::displayStringForShare(const SharePtr &share) const
QString ShareModel::displayStringForShare(const SharePtr &share, const bool verbose) const
{
if (const auto linkShare = share.objectCast<LinkShare>()) {

Expand All @@ -662,7 +714,8 @@ QString ShareModel::displayStringForShare(const SharePtr &share) const
} else if (share->getShareType() == Share::TypeSecureFileDropPlaceholderLink) {
return tr("Secure file drop");
} else if (share->getShareWith()) {
return share->getShareWith()->format();
const auto sharee = share->getShareWith();
return verbose ? QString{"%1 (%2)"}.arg(sharee->format(), sharee->shareWith()) : sharee->format();
}

qCWarning(lcShareModel) << "Unable to provide good display string for share";
Expand Down
4 changes: 3 additions & 1 deletion src/gui/filedetails/sharemodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ private slots:
void slotDeleteE2EeShare(const SharePtr &share) const;

private:
[[nodiscard]] QString displayStringForShare(const SharePtr &share) const;
[[nodiscard]] QString displayStringForShare(const SharePtr &share, bool verbose = false) const;
[[nodiscard]] QString iconUrlForShare(const SharePtr &share) const;
[[nodiscard]] QString avatarUrlForShare(const SharePtr &share) const;
[[nodiscard]] long long enforcedMaxExpireDateForShare(const SharePtr &share) const;
Expand Down Expand Up @@ -253,6 +253,8 @@ private slots:
QHash<QString, QPersistentModelIndex> _shareIdIndexHash;
QHash<QString, QString> _shareIdRecentlySetPasswords;
QVector<ShareePtr> _sharees;
// Buckets of sharees with the same display name
QHash<unsigned int, QSharedPointer<QSet<unsigned int>>> _duplicateDisplayNameShareIndices;
};

} // namespace OCC

0 comments on commit de22334

Please sign in to comment.