Add an internal link share to the share dialog
authorClaudio Cambra <claudio.cambra@nextcloud.com>
Fri, 4 Nov 2022 18:30:22 +0000 (19:30 +0100)
committerClaudio Cambra <claudio.cambra@nextcloud.com>
Tue, 13 Dec 2022 16:33:33 +0000 (17:33 +0100)
Signed-off-by: Claudio Cambra <claudio.cambra@nextcloud.com>
src/gui/filedetails/ShareDelegate.qml
src/gui/filedetails/sharemodel.cpp
src/gui/filedetails/sharemodel.h
src/gui/filedetails/sortedsharemodel.cpp
src/gui/sharemanager.h

index 5768cc44de34704d3297e90d0c45d8d653c27e5d..e95cd1fa2b3d0cc1fb298f60468e2310a6247ca8 100644 (file)
@@ -53,6 +53,7 @@ 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 ?? ""
@@ -183,7 +184,7 @@ GridLayout {
             icon.width: 16
             icon.height: 16
 
-            visible: root.isLinkShare
+            visible: root.isLinkShare || root.isInternalLinkShare
             enabled: visible
 
             onClicked: {
@@ -210,7 +211,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)
index d4891ac775e3a2c6089ae7c132f9d5bd8b907c27..9679cf5bf189c99bd66c1a6cdf822efd4a6f81a9 100644 (file)
@@ -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()
 {
@@ -129,6 +130,11 @@ QVariant ShareModel::data(const QModelIndex &index, const int role) const
             return startOfExpireDayUTC.toMSecsSinceEpoch();
         }
         }
+    } else if (share->getShareType() == Share::TypeInternalLink) {
+        switch(role) {
+        case LinkRole:
+            return _privateLinkUrl;
+        }
     }
 
     switch(role) {
@@ -190,6 +196,8 @@ void ShareModel::resetData()
     _sharePath.clear();
     _maxSharingPermissions = {};
     _numericFileId.clear();
+    _privateLinkUrl.clear();
+    _filelockState = {};
     _manager.clear();
     _shares.clear();
     _fetchOngoing = false;
@@ -256,12 +264,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) {
@@ -359,6 +374,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)
@@ -384,6 +401,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()) {
@@ -508,6 +540,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();
     }
@@ -521,6 +555,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"));
index 0c2eb62dd79fa5cf78571da3257908582c777ef5..05e08fbdca264c71b3de81a2a6de509d6306774f 100644 (file)
@@ -74,6 +74,7 @@ public:
         ShareTypeCircle = Share::TypeCircle,
         ShareTypeRoom = Share::TypeRoom,
         ShareTypePlaceholderLink = Share::TypePlaceholderLink,
+        ShareTypeInternalLink = Share::TypeInternalLink,
     };
     Q_ENUM(ShareType);
 
@@ -109,6 +110,7 @@ signals:
     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);
@@ -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);
@@ -183,6 +186,7 @@ private:
     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.
index 9906cfc57e4e16fb047bb2b44285570bd10a1922..4658060e10b4878b821933106ea610ef71e9e6d8 100644 (file)
@@ -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;
index c3462377a7fb88949e55a78524ab3b9a9b53e672..7afae8afaca1995c75cd5d744ee5c8e644d20f7d 100644 (file)
@@ -52,6 +52,7 @@ public:
      * Need to be in sync with Sharee::Type
      */
     enum ShareType {
+        TypeInternalLink = -2,
         TypePlaceholderLink = -1,
         TypeUser = Sharee::User,
         TypeGroup = Sharee::Group,