Skip to content

Commit

Permalink
Merge pull request #5131 from nextcloud/feature/implement-internal-li…
Browse files Browse the repository at this point in the history
…nk-share

Add an internal link share to the share dialog
  • Loading branch information
claucambra authored Dec 13, 2022
2 parents d0d16e4 + b4ea35e commit da2c978
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 50 deletions.
6 changes: 4 additions & 2 deletions src/gui/filedetails/ShareDelegate.qml
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,13 @@ GridLayout {

readonly property bool isLinkShare: model.shareType === ShareModel.ShareTypeLink
readonly property bool isPlaceholderLinkShare: model.shareType === ShareModel.ShareTypePlaceholderLink
readonly property bool isInternalLinkShare: model.shareType === ShareModel.ShareTypeInternalLink

readonly property string text: model.display ?? ""
readonly property string detailText: model.detailText ?? ""
readonly property string iconUrl: model.iconUrl ?? ""
readonly property string avatarUrl: model.avatarUrl ?? ""
readonly property string link: model.link ?? ""

anchors.left: parent.left
anchors.right: parent.right
Expand Down Expand Up @@ -183,7 +185,7 @@ GridLayout {
icon.width: 16
icon.height: 16

visible: root.isLinkShare
visible: root.isLinkShare || root.isInternalLinkShare
enabled: visible

onClicked: {
Expand All @@ -210,7 +212,7 @@ GridLayout {

imageSource: "image://svgimage-custom-color/more.svg/" + Style.ncTextColor

visible: !root.isPlaceholderLinkShare
visible: !root.isPlaceholderLinkShare && !root.isInternalLinkShare
enabled: visible

onClicked: root.rootStackView.push(shareDetailsPageComponent, {}, StackView.PushTransition)
Expand Down
1 change: 0 additions & 1 deletion src/gui/filedetails/ShareDetailsPage.qml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ Page {
readonly property bool passwordEnforced: shareModelData.passwordEnforced

readonly property bool isLinkShare: shareModelData.shareType === ShareModel.ShareTypeLink
readonly property bool isPlaceholderLinkShare: shareModelData.shareType === ShareModel.ShareTypePlaceholderLink

property bool waitingForEditingAllowedChange: false
property bool waitingForNoteEnabledChange: false
Expand Down
41 changes: 37 additions & 4 deletions src/gui/filedetails/sharemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@

namespace {

static const QString placeholderLinkShareId = QStringLiteral("__placeholderLinkShareId__");
static const auto placeholderLinkShareId = QStringLiteral("__placeholderLinkShareId__");
static const auto internalLinkShareId = QStringLiteral("__internalLinkShareId__");

QString createRandomPassword()
{
Expand Down Expand Up @@ -129,6 +130,8 @@ QVariant ShareModel::data(const QModelIndex &index, const int role) const
return startOfExpireDayUTC.toMSecsSinceEpoch();
}
}
} else if (share->getShareType() == Share::TypeInternalLink && role == LinkRole) {
return _privateLinkUrl;
}

switch(role) {
Expand Down Expand Up @@ -190,6 +193,8 @@ void ShareModel::resetData()
_sharePath.clear();
_maxSharingPermissions = {};
_numericFileId.clear();
_privateLinkUrl.clear();
_filelockState = {};
_manager.clear();
_shares.clear();
_fetchOngoing = false;
Expand Down Expand Up @@ -256,12 +261,19 @@ void ShareModel::updateData()
_sharePath,
Share::TypePlaceholderLink));

_internalLinkShare.reset(new Share(_accountState->account(),
internalLinkShareId,
_accountState->account()->id(),
_accountState->account()->davDisplayName(),
_sharePath,
Share::TypeInternalLink));

auto job = new PropfindJob(_accountState->account(), _sharePath);
job->setProperties(
QList<QByteArray>()
<< "https://open-collaboration-services.org/ns:share-permissions"
<< "https://owncloud.org/ns:fileid" // numeric file id for fallback private link generation
<< "https://owncloud.org/ns:privatelink");
<< "http://open-collaboration-services.org/ns:share-permissions"
<< "http://owncloud.org/ns:fileid" // numeric file id for fallback private link generation
<< "http://owncloud.org/ns:privatelink");
job->setTimeout(10 * 1000);
connect(job, &PropfindJob::result, this, &ShareModel::slotPropfindReceived);
connect(job, &PropfindJob::finishedWithError, this, [&](const QNetworkReply *reply) {
Expand Down Expand Up @@ -359,6 +371,8 @@ void ShareModel::slotPropfindReceived(const QVariantMap &result)
qCInfo(lcShareModel) << "Received numeric file id for" << _sharePath << numericFileId;
_privateLinkUrl = _accountState->account()->deprecatedPrivateLinkUrl(numericFileId).toString(QUrl::FullyEncoded);
}

setupInternalLinkShare();
}

void ShareModel::slotSharesFetched(const QList<SharePtr> &shares)
Expand All @@ -384,6 +398,21 @@ void ShareModel::slotSharesFetched(const QList<SharePtr> &shares)
handlePlaceholderLinkShare();
}

void ShareModel::setupInternalLinkShare()
{
if (!_accountState ||
_accountState->account().isNull() ||
_localPath.isEmpty() ||
_privateLinkUrl.isEmpty()) {
return;
}

beginInsertRows({}, _shares.count(), _shares.count());
_shares.append(_internalLinkShare);
endInsertRows();
Q_EMIT internalLinkReady();
}

void ShareModel::slotAddShare(const SharePtr &share)
{
if (share.isNull()) {
Expand Down Expand Up @@ -508,6 +537,8 @@ QString ShareModel::displayStringForShare(const SharePtr &share) const
return displayString;
} else if (share->getShareType() == Share::TypePlaceholderLink) {
return tr("Link share");
} else if (share->getShareType() == Share::TypeInternalLink) {
return tr("Internal link");
} else if (share->getShareWith()) {
return share->getShareWith()->format();
}
Expand All @@ -521,6 +552,8 @@ QString ShareModel::iconUrlForShare(const SharePtr &share) const
const auto iconsPath = QStringLiteral("image://svgimage-custom-color/");

switch(share->getShareType()) {
case Share::TypeInternalLink:
return QString(iconsPath + QStringLiteral("external.svg"));
case Share::TypePlaceholderLink:
case Share::TypeLink:
return QString(iconsPath + QStringLiteral("public.svg"));
Expand Down
4 changes: 4 additions & 0 deletions src/gui/filedetails/sharemodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class ShareModel : public QAbstractListModel
ShareTypeCircle = Share::TypeCircle,
ShareTypeRoom = Share::TypeRoom,
ShareTypePlaceholderLink = Share::TypePlaceholderLink,
ShareTypeInternalLink = Share::TypeInternalLink,
};
Q_ENUM(ShareType);

Expand Down Expand Up @@ -109,6 +110,7 @@ class ShareModel : public QAbstractListModel
void fetchOngoingChanged();
void hasInitialShareFetchCompletedChanged();
void shareesChanged();
void internalLinkReady();

void serverError(const int code, const QString &message);
void passwordSetError(const QString &shareId, const int code, const QString &message);
Expand Down Expand Up @@ -157,6 +159,7 @@ private slots:
void updateData();
void initShareManager();
void handlePlaceholderLinkShare();
void setupInternalLinkShare();

void slotPropfindReceived(const QVariantMap &result);
void slotServerError(const int code, const QString &message);
Expand All @@ -183,6 +186,7 @@ private slots:
bool _fetchOngoing = false;
bool _hasInitialShareFetchCompleted = false;
SharePtr _placeholderLinkShare;
SharePtr _internalLinkShare;

// DO NOT USE QSHAREDPOINTERS HERE.
// QSharedPointers MUST NOT be used with pointers already assigned to other shared pointers.
Expand Down
13 changes: 12 additions & 1 deletion src/gui/filedetails/sortedsharemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,23 @@ bool SortedShareModel::lessThan(const QModelIndex &sourceLeft, const QModelIndex
const auto leftShareType = leftShare->getShareType();

// Placeholder link shares always go at top
if(leftShareType == Share::TypePlaceholderLink) {
if (leftShareType == Share::TypePlaceholderLink) {
return true;
} else if (leftShareType == Share::TypeInternalLink) {
// Internal links always at bottom
return false;
}

const auto rightShareType = rightShare->getShareType();

// Placeholder link shares always go at top
if (rightShareType == Share::TypePlaceholderLink) {
return false;
} else if (rightShareType == Share::TypeInternalLink) {
// Internal links always at bottom
return true;
}

// We want to place link shares at the top
if (leftShareType == Share::TypeLink && rightShareType != Share::TypeLink) {
return true;
Expand Down
1 change: 1 addition & 0 deletions src/gui/sharemanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class Share : public QObject
* Need to be in sync with Sharee::Type
*/
enum ShareType {
TypeInternalLink = -2,
TypePlaceholderLink = -1,
TypeUser = Sharee::User,
TypeGroup = Sharee::Group,
Expand Down
4 changes: 3 additions & 1 deletion test/sharetestutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,9 @@ void ShareTestHelper::setup()

const auto folderMan = FolderMan::instance();
QCOMPARE(folderMan, &fm);
QVERIFY(folderMan->addFolder(accountState.data(), folderDefinition(fakeFolder.localPath())));
auto folderDef = folderDefinition(fakeFolder.localPath());
folderDef.targetPath = QString();
QVERIFY(folderMan->addFolder(accountState.data(), folderDef));
const auto folder = FolderMan::instance()->folder(fakeFolder.localPath());
QVERIFY(folder);
QVERIFY(fakeFolder.syncOnce());
Expand Down
Loading

0 comments on commit da2c978

Please sign in to comment.