Implement missing share settings

Signed-off-by: alex-z <blackslayer4@gmail.com>
This commit is contained in:
alex-z 2023-04-19 20:28:07 +02:00
parent 7edc0a43a6
commit f39a0903c5
12 changed files with 420 additions and 62 deletions

View file

@ -51,5 +51,6 @@
<file>src/gui/tray/EnforcedPlainTextLabel.qml</file>
<file>theme/Style/Style.qml</file>
<file>theme/Style/qmldir</file>
<file>src/gui/filedetails/NCRadioButton.qml</file>
</qresource>
</RCC>

View file

@ -0,0 +1,43 @@
/*
* Copyright (C) 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
RadioButton {
id: root
property int indicatorItemWidth: Style.radioButtonIndicatorSize
property int indicatorItemHeight: Style.radioButtonIndicatorSize
property string color: Style.ncTextColor
readonly property int radius: Style.radioButtonCustomRadius
indicator: Rectangle {
implicitWidth: root.indicatorItemWidth
implicitHeight: root.indicatorItemHeight
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: Style.radioButtonCustomMarginLeftOuter
radius: root.radius
border.color: root.color
border.width: Style.normalBorderWidth
Rectangle {
anchors.fill: parent
visible: root.checked
color: root.color
radius: root.radius
anchors.margins: Style.radioButtonCustomMarginLeftInner
}
}
}

View file

@ -33,11 +33,13 @@ GridLayout {
signal resetPasswordField
signal showPasswordSetError(string errorMessage);
signal toggleHideDownload(bool enable)
signal toggleAllowEditing(bool enable)
signal toggleAllowResharing(bool enable)
signal togglePasswordProtect(bool enable)
signal toggleExpirationDate(bool enable)
signal toggleNoteToRecipient(bool enable)
signal permissionModeChanged(int permissionMode)
signal setLinkShareLabel(string label)
signal setExpireDate(var milliseconds) // Since QML ints are only 32 bits, use a variant
@ -236,9 +238,11 @@ GridLayout {
onToggleAllowEditing: root.toggleAllowEditing(enable)
onToggleAllowResharing: root.toggleAllowResharing(enable)
onToggleHideDownload: root.toggleHideDownload(enable)
onTogglePasswordProtect: root.togglePasswordProtect(enable)
onToggleExpirationDate: root.toggleExpirationDate(enable)
onToggleNoteToRecipient: root.toggleNoteToRecipient(enable)
onPermissionModeChanged: root.permissionModeChanged(permissionMode)
onSetLinkShareLabel: root.setLinkShareLabel(label)
onSetExpireDate: root.setExpireDate(milliseconds) // Since QML ints are only 32 bits, use a variant

View file

@ -32,9 +32,11 @@ Page {
signal toggleAllowEditing(bool enable)
signal toggleAllowResharing(bool enable)
signal toggleHideDownload(bool enable)
signal togglePasswordProtect(bool enable)
signal toggleExpirationDate(bool enable)
signal toggleNoteToRecipient(bool enable)
signal permissionModeChanged(int permissionMode)
signal setLinkShareLabel(string label)
signal setExpireDate(var milliseconds) // Since QML ints are only 32 bits, use a variant
@ -65,16 +67,21 @@ Page {
readonly property string linkShareLabel: shareModelData.linkShareLabel ?? ""
readonly property bool editingAllowed: shareModelData.editingAllowed
readonly property bool hideDownload: shareModelData.hideDownload
readonly property bool noteEnabled: shareModelData.noteEnabled
readonly property bool expireDateEnabled: shareModelData.expireDateEnabled
readonly property bool expireDateEnforced: shareModelData.expireDateEnforced
readonly property bool passwordProtectEnabled: shareModelData.passwordProtectEnabled
readonly property bool passwordEnforced: shareModelData.passwordEnforced
readonly property bool isSecureFileDropLink: shareModelData.isSecureFileDropLink
readonly property bool isSharePermissionChangeInProgress: shareModelData.isSharePermissionChangeInProgress
readonly property bool isHideDownloadInProgress: shareModelData.isHideDownloadInProgress
readonly property int currentPermissionMode: shareModelData.currentPermissionMode
readonly property bool isLinkShare: shareModelData.shareType === ShareModel.ShareTypeLink
property bool waitingForEditingAllowedChange: false
readonly property bool isFolderItem: shareModelData.sharedItemType === ShareModel.SharedItemTypeFolder
readonly property bool isEncryptedItem: shareModelData.sharedItemType === ShareModel.SharedItemTypeEncryptedFile || shareModelData.sharedItemType === ShareModel.SharedItemTypeEncryptedFolder || shareModelData.sharedItemType === ShareModel.SharedItemTypeEncryptedTopLevelFolder
property bool waitingForNoteEnabledChange: false
property bool waitingForExpireDateEnabledChange: false
property bool waitingForPasswordProtectEnabledChange: false
@ -108,11 +115,6 @@ Page {
waitingForExpireDateChange = false;
}
function resetEditingAllowedField() {
editingAllowedMenuItem.checked = editingAllowed;
waitingForEditingAllowedChange = false;
}
function resetNoteEnabledField() {
noteEnabledMenuItem.checked = noteEnabled;
waitingForNoteEnabledChange = false;
@ -135,8 +137,6 @@ Page {
resetPasswordField();
resetLinkShareLabelField();
resetExpireDateField();
resetEditingAllowedField();
resetNoteEnabledField();
resetExpireDateEnabledField();
resetPasswordProtectEnabledField();
@ -154,8 +154,6 @@ Page {
onPasswordChanged: resetPasswordField()
onLinkShareLabelChanged: resetLinkShareLabelField()
onExpireDateChanged: resetExpireDateField()
onEditingAllowedChanged: resetEditingAllowedField()
onNoteEnabledChanged: resetNoteEnabledField()
onExpireDateEnabledChanged: resetExpireDateEnabledField()
onPasswordProtectEnabledChanged: resetPasswordProtectEnabledField()
@ -313,13 +311,11 @@ Page {
}
}
// On these checkables, the clicked() signal is called after
// the check state changes.
CheckBox {
id: editingAllowedMenuItem
Loader {
Layout.fillWidth: true
active: !root.isFolderItem && !root.isEncryptedItem
visible: active
sourceComponent: CheckBox {
spacing: moreMenu.indicatorSpacing
padding: moreMenu.itemPadding
indicator.width: moreMenu.indicatorItemWidth
@ -327,22 +323,114 @@ Page {
checkable: true
checked: root.editingAllowed
text: qsTr("Allow editing")
enabled: !root.waitingForEditingAllowedChange
visible: !root.isSecureFileDropLink
text: qsTr("Allow upload and editing")
enabled: !root.isSharePermissionChangeInProgress
onClicked: {
root.toggleAllowEditing(checked);
root.waitingForEditingAllowedChange = true;
}
onClicked: root.toggleAllowEditing(checked)
NCBusyIndicator {
anchors.fill: parent
visible: root.waitingForEditingAllowedChange
visible: root.isSharePermissionChangeInProgress
running: visible
z: 1
}
}
}
Loader {
Layout.fillWidth: true
active: root.isFolderItem && !root.isEncryptedItem
visible: active
sourceComponent: ColumnLayout {
id: permissionRadioButtonsLayout
spacing: 0
width: parent.width
ButtonGroup {
id: permissionModeRadioButtonsGroup
}
NCRadioButton {
readonly property int permissionMode: ShareModel.ModeViewOnly
Layout.fillWidth: true
ButtonGroup.group: permissionModeRadioButtonsGroup
enabled: !root.isSharePermissionChangeInProgress
checked: root.currentPermissionMode === permissionMode
text: qsTr("View only")
indicatorItemWidth: moreMenu.indicatorItemWidth
indicatorItemHeight: moreMenu.indicatorItemWidth
spacing: moreMenu.indicatorSpacing
padding: moreMenu.itemPadding
onClicked: root.permissionModeChanged(permissionMode)
}
NCRadioButton {
readonly property int permissionMode: ShareModel.ModeUploadAndEditing
Layout.fillWidth: true
ButtonGroup.group: permissionModeRadioButtonsGroup
enabled: !root.isSharePermissionChangeInProgress
checked: root.currentPermissionMode === permissionMode
text: qsTr("Allow upload and editing")
indicatorItemWidth: moreMenu.indicatorItemWidth
indicatorItemHeight: moreMenu.indicatorItemWidth
spacing: moreMenu.indicatorSpacing
padding: moreMenu.itemPadding
onClicked: root.permissionModeChanged(permissionMode)
NCBusyIndicator {
anchors.fill: parent
visible: root.isSharePermissionChangeInProgress
running: visible
z: 1
}
}
NCRadioButton {
readonly property int permissionMode: ShareModel.ModeFileDropOnly
Layout.fillWidth: true
ButtonGroup.group: permissionModeRadioButtonsGroup
enabled: !root.isSharePermissionChangeInProgress
checked: root.currentPermissionMode === permissionMode
text: qsTr("File drop (upload only)")
indicatorItemWidth: moreMenu.indicatorItemWidth
indicatorItemHeight: moreMenu.indicatorItemWidth
spacing: moreMenu.indicatorSpacing
padding: moreMenu.itemPadding
onClicked: root.permissionModeChanged(permissionMode)
}
}
}
Loader {
Layout.fillWidth: true
active: root.isLinkShare
visible: active
sourceComponent: ColumnLayout {
CheckBox {
id: hideDownloadEnabledMenuItem
anchors.left: parent.left
anchors.right: parent.right
spacing: moreMenu.indicatorSpacing
padding: moreMenu.itemPadding
indicator.width: moreMenu.indicatorItemWidth
indicator.height: moreMenu.indicatorItemWidth
checked: root.hideDownload
text: qsTr("Hide download")
enabled: !root.isHideDownloadInProgress
onClicked: root.toggleHideDownload(checked);
NCBusyIndicator {
anchors.fill: parent
visible: root.isHideDownloadInProgress
running: visible
z: 1
}
}
}
}
CheckBox {
id: passwordProtectEnabledMenuItem

View file

@ -241,9 +241,11 @@ ColumnLayout {
onToggleAllowEditing: shareModel.toggleShareAllowEditingFromQml(model.share, enable)
onToggleAllowResharing: shareModel.toggleShareAllowResharingFromQml(model.share, enable)
onToggleHideDownload: shareModel.toggleHideDownloadFromQml(model.share, enable)
onTogglePasswordProtect: shareModel.toggleSharePasswordProtectFromQml(model.share, enable)
onToggleExpirationDate: shareModel.toggleShareExpirationDateFromQml(model.share, enable)
onToggleNoteToRecipient: shareModel.toggleShareNoteToRecipientFromQml(model.share, enable)
onPermissionModeChanged: shareModel.changePermissionModeFromQml(model.share, permissionMode)
onSetLinkShareLabel: shareModel.setLinkShareLabelFromQml(model.share, label)
onSetExpireDate: shareModel.setShareExpireDateFromQml(model.share, milliseconds)

View file

@ -81,7 +81,11 @@ QHash<int, QByteArray> ShareModel::roleNames() const
roles[PasswordRole] = "password";
roles[PasswordEnforcedRole] = "passwordEnforced";
roles[EditingAllowedRole] = "editingAllowed";
roles[IsSecureFileDropLinkRole] = "isSecureFileDropLink";
roles[CurrentPermissionModeRole] = "currentPermissionMode";
roles[SharedItemTypeRole] = "sharedItemType";
roles[IsSharePermissionsChangeInProgress] = "isSharePermissionChangeInProgress";
roles[HideDownloadEnabledRole] = "hideDownload";
roles[IsHideDownloadEnabledChangeInProgress] = "isHideDownloadInProgress";
return roles;
}
@ -107,6 +111,8 @@ QVariant ShareModel::data(const QModelIndex &index, const int role) const
return linkShare->getLabel();
case NoteEnabledRole:
return !linkShare->getNote().isEmpty();
case HideDownloadEnabledRole:
return linkShare->getHideDownload();
case NoteRole:
return linkShare->getNote();
case ExpireDateEnabledRole:
@ -151,8 +157,22 @@ QVariant ShareModel::data(const QModelIndex &index, const int role) const
return expireDateEnforcedForShare(share);
case EnforcedMaximumExpireDateRole:
return enforcedMaxExpireDateForShare(share);
case IsSecureFileDropLinkRole:
return _isSecureFileDropSupportedFolder && share->getPermissions().testFlag(OCC::SharePermission::SharePermissionCreate);
case CurrentPermissionModeRole: {
if (share->getPermissions() == OCC::SharePermission::SharePermissionCreate) {
return QVariant::fromValue(SharePermissionsMode::ModeFileDropOnly);
} else if ((share->getPermissions() & SharePermissionRead) && (share->getPermissions() & SharePermissionCreate)
&& (share->getPermissions() & SharePermissionUpdate) && (share->getPermissions() & SharePermissionDelete)) {
return QVariant::fromValue(SharePermissionsMode::ModeUploadAndEditing);
} else {
return QVariant::fromValue(SharePermissionsMode::ModeViewOnly);
}
}
case SharedItemTypeRole:
return static_cast<int>(_sharedItemType);
case IsSharePermissionsChangeInProgress:
return _sharePermissionsChangeInProgress;
case IsHideDownloadEnabledChangeInProgress:
return _hideDownloadEnabledChangeInProgress;
case PasswordProtectEnabledRole:
return share->isPasswordSet();
case PasswordRole:
@ -250,9 +270,15 @@ void ShareModel::updateData()
_numericFileId = fileRecord.numericFileId();
_isEncryptedItem = fileRecord.isE2eEncrypted();
_isSecureFileDropSupportedFolder =
fileRecord.isE2eEncrypted() && fileRecord.e2eMangledName().isEmpty() && _accountState->account()->secureFileDropSupported();
if (fileRecord.isDirectory()) {
if (fileRecord.isE2eEncrypted()) {
_sharedItemType = fileRecord.e2eMangledName().isEmpty() ? SharedItemType::SharedItemTypeEncryptedTopLevelFolder : SharedItemType::SharedItemTypeEncryptedFolder;
} else {
_sharedItemType = SharedItemType::SharedItemTypeFolder;
}
} else {
_sharedItemType = fileRecord.isE2eEncrypted() ? SharedItemType::SharedItemTypeEncryptedFile : SharedItemType::SharedItemTypeFile;
}
// Will get added when shares are fetched if no link shares are fetched
_placeholderLinkShare.reset(new Share(_accountState->account(),
@ -386,9 +412,9 @@ void ShareModel::handleSecureFileDropLinkShare()
void ShareModel::handleLinkShare()
{
if (!_isEncryptedItem) {
if (!isEncryptedItem()) {
handlePlaceholderLinkShare();
} else if (_isSecureFileDropSupportedFolder) {
} else if (isSecureFileDropSupportedFolder()) {
handleSecureFileDropLinkShare();
}
}
@ -456,7 +482,7 @@ void ShareModel::setupInternalLinkShare()
_accountState->account().isNull() ||
_localPath.isEmpty() ||
_privateLinkUrl.isEmpty() ||
_isEncryptedItem) {
isEncryptedItem()) {
return;
}
@ -466,6 +492,30 @@ void ShareModel::setupInternalLinkShare()
Q_EMIT internalLinkReady();
}
void ShareModel::setSharePermissionChangeInProgress(const QString &shareId, const bool isInProgress)
{
if (isInProgress == _sharePermissionsChangeInProgress) {
return;
}
_sharePermissionsChangeInProgress = isInProgress;
const auto shareIndex = _shareIdIndexHash.value(shareId);
Q_EMIT dataChanged(shareIndex, shareIndex, {IsSharePermissionsChangeInProgress});
}
void ShareModel::setHideDownloadEnabledChangeInProgress(const QString &shareId, const bool isInProgress)
{
if (isInProgress == _hideDownloadEnabledChangeInProgress) {
return;
}
_hideDownloadEnabledChangeInProgress = isInProgress;
const auto shareIndex = _shareIdIndexHash.value(shareId);
Q_EMIT dataChanged(shareIndex, shareIndex, {IsHideDownloadEnabledChangeInProgress});
}
void ShareModel::slotAddShare(const SharePtr &share)
{
if (share.isNull()) {
@ -515,6 +565,7 @@ void ShareModel::slotAddShare(const SharePtr &share)
connect(linkShare.data(), &LinkShare::nameSet, this, [this, shareId]{ slotShareNameSet(shareId); });
connect(linkShare.data(), &LinkShare::labelSet, this, [this, shareId]{ slotShareLabelSet(shareId); });
connect(linkShare.data(), &LinkShare::expireDateSet, this, [this, shareId]{ slotShareExpireDateSet(shareId); });
connect(linkShare.data(), &LinkShare::hideDownloadSet, this, [this, shareId] { slotHideDownloadSet(shareId); });
} else if (const auto userGroupShare = share.objectCast<UserGroupShare>()) {
connect(userGroupShare.data(), &UserGroupShare::noteSet, this, [this, shareId]{ slotShareNoteSet(shareId); });
connect(userGroupShare.data(), &UserGroupShare::expireDateSet, this, [this, shareId]{ slotShareExpireDateSet(shareId); });
@ -582,7 +633,7 @@ QString ShareModel::displayStringForShare(const SharePtr &share) const
{
if (const auto linkShare = share.objectCast<LinkShare>()) {
const auto isSecureFileDropShare = _isSecureFileDropSupportedFolder && linkShare->getPermissions().testFlag(OCC::SharePermission::SharePermissionCreate);
const auto isSecureFileDropShare = isSecureFileDropSupportedFolder() && linkShare->getPermissions().testFlag(OCC::SharePermission::SharePermissionCreate);
const auto displayString = isSecureFileDropShare ? tr("Secure file drop link") : tr("Share link");
@ -708,7 +759,8 @@ void ShareModel::slotSharePermissionsSet(const QString &shareId)
const auto sharePersistentModelIndex = _shareIdIndexHash.value(shareId);
const auto shareModelIndex = index(sharePersistentModelIndex.row());
Q_EMIT dataChanged(shareModelIndex, shareModelIndex, { EditingAllowedRole });
Q_EMIT dataChanged(shareModelIndex, shareModelIndex, { EditingAllowedRole, CurrentPermissionModeRole });
setSharePermissionChangeInProgress(shareId, false);
}
void ShareModel::slotSharePasswordSet(const QString &shareId)
@ -722,6 +774,18 @@ void ShareModel::slotSharePasswordSet(const QString &shareId)
Q_EMIT dataChanged(shareModelIndex, shareModelIndex, { PasswordProtectEnabledRole, PasswordRole });
}
void ShareModel::slotHideDownloadSet(const QString &shareId)
{
if (shareId.isEmpty() || !_shareIdIndexHash.contains(shareId)) {
return;
}
const auto sharePersistentModelIndex = _shareIdIndexHash.value(shareId);
const auto shareModelIndex = index(sharePersistentModelIndex.row());
Q_EMIT dataChanged(shareModelIndex, shareModelIndex, {HideDownloadEnabledRole});
setHideDownloadEnabledChangeInProgress(shareId, false);
}
void ShareModel::slotShareNoteSet(const QString &shareId)
{
if (shareId.isEmpty() || !_shareIdIndexHash.contains(shareId)) {
@ -768,37 +832,56 @@ void ShareModel::slotShareExpireDateSet(const QString &shareId)
// ----------------------- Shares modification slots ----------------------- //
void ShareModel::toggleShareAllowEditing(const SharePtr &share, const bool enable) const
void ShareModel::toggleShareAllowEditing(const SharePtr &share, const bool enable)
{
if (share.isNull()) {
if (share.isNull() || _sharePermissionsChangeInProgress) {
return;
}
auto permissions = share->getPermissions();
enable ? permissions |= SharePermissionUpdate : permissions &= ~SharePermissionUpdate;
setSharePermissionChangeInProgress(share->getId(), true);
share->setPermissions(permissions);
}
void ShareModel::toggleShareAllowEditingFromQml(const QVariant &share, const bool enable) const
void ShareModel::toggleShareAllowEditingFromQml(const QVariant &share, const bool enable)
{
const auto ptr = share.value<SharePtr>();
toggleShareAllowEditing(ptr, enable);
}
void ShareModel::toggleShareAllowResharing(const SharePtr &share, const bool enable) const
void ShareModel::toggleShareAllowResharing(const SharePtr &share, const bool enable)
{
if (share.isNull()) {
if (share.isNull() || _sharePermissionsChangeInProgress) {
return;
}
auto permissions = share->getPermissions();
enable ? permissions |= SharePermissionShare : permissions &= ~SharePermissionShare;
setSharePermissionChangeInProgress(share->getId(), true);
share->setPermissions(permissions);
}
void ShareModel::toggleShareAllowResharingFromQml(const QVariant &share, const bool enable) const
void ShareModel::toggleHideDownloadFromQml(const QVariant &share, const bool enable)
{
const auto sharePtr = share.value<SharePtr>();
if (sharePtr.isNull() || _hideDownloadEnabledChangeInProgress) {
return;
}
const auto linkShare = sharePtr.objectCast<LinkShare>();
if (linkShare.isNull()) {
return;
}
setHideDownloadEnabledChangeInProgress(linkShare->getId(), true);
linkShare->setHideDownload(enable);
}
void ShareModel::toggleShareAllowResharingFromQml(const QVariant &share, const bool enable)
{
const auto ptr = share.value<SharePtr>();
toggleShareAllowResharing(ptr, enable);
@ -867,6 +950,42 @@ void ShareModel::toggleShareNoteToRecipientFromQml(const QVariant &share, const
toggleShareNoteToRecipient(ptr, enable);
}
void ShareModel::changePermissionModeFromQml(const QVariant &share, const SharePermissionsMode permissionMode)
{
const auto sharePtr = share.value<SharePtr>();
if (sharePtr.isNull() || _sharePermissionsChangeInProgress) {
return;
}
const auto shareIndex = _shareIdIndexHash.value(sharePtr->getId());
if (!checkIndex(shareIndex, QAbstractItemModel::CheckIndexOption::IndexIsValid | QAbstractItemModel::CheckIndexOption::ParentIsInvalid)) {
qCWarning(lcShareModel) << "Can't change permission mode for:" << sharePtr->getId() << ", invalid share index: " << shareIndex;
return;
}
const auto currentPermissionMode = shareIndex.data(ShareModel::CurrentPermissionModeRole).value<SharePermissionsMode>();
if (currentPermissionMode == permissionMode) {
return;
}
SharePermissions perm = SharePermissionRead;
switch (permissionMode) {
case SharePermissionsMode::ModeViewOnly:
break;
case SharePermissionsMode::ModeUploadAndEditing:
perm |= SharePermissionCreate | SharePermissionUpdate | SharePermissionDelete;
break;
case SharePermissionsMode::ModeFileDropOnly:
perm = SharePermissionCreate;
break;
}
setSharePermissionChangeInProgress(sharePtr->getId(), true);
sharePtr->setPermissions(perm);
}
void ShareModel::setLinkShareLabel(const QSharedPointer<LinkShare> &linkShare, const QString &label) const
{
if (linkShare.isNull()) {
@ -944,7 +1063,7 @@ void ShareModel::setShareNoteFromQml(const QVariant &share, const QString &note)
void ShareModel::createNewLinkShare() const
{
if (_isEncryptedItem && !_isSecureFileDropSupportedFolder) {
if (isEncryptedItem() && !isSecureFileDropSupportedFolder()) {
qCWarning(lcShareModel) << "Attempt to create a link share for non-root encrypted folder or a file.";
return;
}
@ -952,7 +1071,7 @@ void ShareModel::createNewLinkShare() const
if (_manager) {
const auto askOptionalPassword = _accountState->account()->capabilities().sharePublicLinkAskOptionalPassword();
const auto password = askOptionalPassword ? createRandomPassword() : QString();
if (_isSecureFileDropSupportedFolder) {
if (isSecureFileDropSupportedFolder()) {
_manager->createSecureFileDropShare(_sharePath, {}, password);
return;
}
@ -1089,6 +1208,17 @@ bool ShareModel::validCapabilities() const
_accountState->account()->capabilities().isValid();
}
bool ShareModel::isSecureFileDropSupportedFolder() const
{
return _sharedItemType == SharedItemType::SharedItemTypeEncryptedTopLevelFolder && _accountState->account()->secureFileDropSupported();
}
bool ShareModel::isEncryptedItem() const
{
return _sharedItemType == SharedItemType::SharedItemTypeEncryptedFile || _sharedItemType == SharedItemType::SharedItemTypeEncryptedFolder
|| _sharedItemType == SharedItemType::SharedItemTypeEncryptedTopLevelFolder;
}
bool ShareModel::sharingEnabled() const
{
return validCapabilities() &&

View file

@ -57,7 +57,11 @@ public:
PasswordRole,
PasswordEnforcedRole,
EditingAllowedRole,
IsSecureFileDropLinkRole,
CurrentPermissionModeRole,
SharedItemTypeRole,
IsSharePermissionsChangeInProgress,
HideDownloadEnabledRole,
IsHideDownloadEnabledChangeInProgress,
};
Q_ENUM(Roles)
@ -80,6 +84,23 @@ public:
};
Q_ENUM(ShareType);
enum class SharedItemType {
SharedItemTypeUndefined = -1,
SharedItemTypeFile,
SharedItemTypeFolder,
SharedItemTypeEncryptedFile,
SharedItemTypeEncryptedFolder,
SharedItemTypeEncryptedTopLevelFolder,
};
Q_ENUM(SharedItemType);
enum class SharePermissionsMode {
ModeViewOnly,
ModeUploadAndEditing,
ModeFileDropOnly,
};
Q_ENUM(SharePermissionsMode);
explicit ShareModel(QObject *parent = nullptr);
[[nodiscard]] QVariant data(const QModelIndex &index, const int role) const override;
@ -135,16 +156,18 @@ public slots:
void deleteShare(const OCC::SharePtr &share) const;
void deleteShareFromQml(const QVariant &share) const;
void toggleShareAllowEditing(const OCC::SharePtr &share, const bool enable) const;
void toggleShareAllowEditingFromQml(const QVariant &share, const bool enable) const;
void toggleShareAllowResharing(const OCC::SharePtr &share, const bool enable) const;
void toggleShareAllowResharingFromQml(const QVariant &share, const bool enable) const;
void toggleHideDownloadFromQml(const QVariant &share, const bool enable);
void toggleShareAllowEditing(const OCC::SharePtr &share, const bool enable);
void toggleShareAllowEditingFromQml(const QVariant &share, const bool enable);
void toggleShareAllowResharing(const OCC::SharePtr &share, const bool enable);
void toggleShareAllowResharingFromQml(const QVariant &share, const bool enable);
void toggleSharePasswordProtect(const OCC::SharePtr &share, const bool enable);
void toggleSharePasswordProtectFromQml(const QVariant &share, const bool enable);
void toggleShareExpirationDate(const OCC::SharePtr &share, const bool enable) const;
void toggleShareExpirationDateFromQml(const QVariant &share, const bool enable) const;
void toggleShareNoteToRecipient(const OCC::SharePtr &share, const bool enable) const;
void toggleShareNoteToRecipientFromQml(const QVariant &share, const bool enable) const;
void changePermissionModeFromQml(const QVariant &share, const SharePermissionsMode permissionMode);
void setLinkShareLabel(const QSharedPointer<OCC::LinkShare> &linkShare, const QString &label) const;
void setLinkShareLabelFromQml(const QVariant &linkShare, const QString &label) const;
@ -164,6 +187,8 @@ private slots:
void handleSecureFileDropLinkShare();
void handleLinkShare();
void setupInternalLinkShare();
void setSharePermissionChangeInProgress(const QString &shareId, const bool isInProgress);
void setHideDownloadEnabledChangeInProgress(const QString &shareId, const bool isInProgress);
void slotPropfindReceived(const QVariantMap &result);
void slotServerError(const int code, const QString &message);
@ -176,6 +201,7 @@ private slots:
void slotSharePermissionsSet(const QString &shareId);
void slotSharePasswordSet(const QString &shareId);
void slotShareNoteSet(const QString &shareId);
void slotHideDownloadSet(const QString &shareId);
void slotShareNameSet(const QString &shareId);
void slotShareLabelSet(const QString &shareId);
void slotShareExpireDateSet(const QString &shareId);
@ -187,9 +213,13 @@ private:
[[nodiscard]] long long enforcedMaxExpireDateForShare(const SharePtr &share) const;
[[nodiscard]] bool expireDateEnforcedForShare(const SharePtr &share) const;
[[nodiscard]] bool validCapabilities() const;
[[nodiscard]] bool isSecureFileDropSupportedFolder() const;
[[nodiscard]] bool isEncryptedItem() const;
bool _fetchOngoing = false;
bool _hasInitialShareFetchCompleted = false;
bool _sharePermissionsChangeInProgress = false;
bool _hideDownloadEnabledChangeInProgress = false;
SharePtr _placeholderLinkShare;
SharePtr _internalLinkShare;
SharePtr _secureFileDropPlaceholderLinkShare;
@ -201,8 +231,7 @@ private:
QString _sharePath;
SharePermissions _maxSharingPermissions;
QByteArray _numericFileId;
bool _isEncryptedItem = false;
bool _isSecureFileDropSupportedFolder = false;
SharedItemType _sharedItemType = SharedItemType::SharedItemTypeUndefined;
SyncJournalFileLockInfo _filelockState;
QString _privateLinkUrl;

View file

@ -134,6 +134,18 @@ void OcsShareJob::setLabel(const QString &shareId, const QString &label)
start();
}
void OcsShareJob::setHideDownload(const QString &shareId, const bool hideDownload)
{
appendPath(shareId);
setVerb("PUT");
const auto value = QString::fromLatin1(hideDownload ? QByteArrayLiteral("true") : QByteArrayLiteral("false"));
addParam(QStringLiteral("hideDownload"), value);
_value = hideDownload;
start();
}
void OcsShareJob::createLinkShare(const QString &path,
const QString &name,
const QString &password)

View file

@ -102,6 +102,11 @@ public:
*/
void setLabel(const QString &shareId, const QString &label);
/**
* Set share hideDownload flag
*/
void setHideDownload(const QString &shareId, const bool hideDownload);
/**
* Create a new link share
*

View file

@ -203,7 +203,8 @@ LinkShare::LinkShare(AccountPtr account,
const QUrl &url,
const QDate &expireDate,
const QString &note,
const QString &label)
const QString &label,
const bool hideDownload)
: Share(account, id, uidowner, ownerDisplayName, path, Share::TypeLink, isPasswordSet, permissions)
, _name(name)
, _token(token)
@ -211,6 +212,7 @@ LinkShare::LinkShare(AccountPtr account,
, _expireDate(expireDate)
, _url(url)
, _label(label)
, _hideDownload(hideDownload)
{
}
@ -239,6 +241,11 @@ QString LinkShare::getLabel() const
return _label;
}
bool LinkShare::getHideDownload() const
{
return _hideDownload;
}
void LinkShare::setName(const QString &name)
{
createShareJob(&LinkShare::slotNameSet)->setName(getId(), name);
@ -270,6 +277,11 @@ void LinkShare::setLabel(const QString &label)
createShareJob(&LinkShare::slotLabelSet)->setLabel(getId(), label);
}
void LinkShare::setHideDownload(const bool hideDownload)
{
createShareJob(&LinkShare::slotHideDownloadSet)->setHideDownload(getId(), hideDownload);
}
template <typename LinkShareSlot>
OcsShareJob *LinkShare::createShareJob(const LinkShareSlot slotFunction) {
auto *job = new OcsShareJob(_account);
@ -308,6 +320,16 @@ void LinkShare::slotLabelSet(const QJsonDocument &, const QVariant &label)
}
}
void LinkShare::slotHideDownloadSet(const QJsonDocument &jsonDoc, const QVariant &hideDownload)
{
Q_UNUSED(jsonDoc);
if (!hideDownload.isValid()) {
return;
}
_hideDownload = hideDownload.toBool();
emit hideDownloadSet();
}
UserGroupShare::UserGroupShare(AccountPtr account,
const QString &id,
const QString &owner,
@ -583,7 +605,8 @@ QSharedPointer<LinkShare> ShareManager::parseLinkShare(const QJsonObject &data)
url,
expireDate,
note,
data.value("label").toString()));
data.value("label").toString(),
data.value("hide_download").toInt() == 1));
}
SharePtr ShareManager::parseShare(const QJsonObject &data) const

View file

@ -132,6 +132,7 @@ signals:
void shareDeleted();
void serverError(int code, const QString &message);
void passwordSet();
void hideDownloadSet();
void passwordSetError(int statusCode, const QString &message);
public slots:
@ -197,6 +198,7 @@ class LinkShare : public Share
Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameSet)
Q_PROPERTY(QString note READ getNote WRITE setNote NOTIFY noteSet)
Q_PROPERTY(QString label READ getLabel WRITE setLabel NOTIFY labelSet)
Q_PROPERTY(bool hideDownload READ getHideDownload WRITE setHideDownload NOTIFY hideDownloadSet)
Q_PROPERTY(QDate expireDate READ getExpireDate WRITE setExpireDate NOTIFY expireDateSet)
Q_PROPERTY(QString token READ getToken CONSTANT)
@ -213,7 +215,8 @@ public:
const QUrl &url,
const QDate &expireDate,
const QString &note,
const QString &label);
const QString &label,
const bool hideDownload);
/*
* Get the share link
@ -250,6 +253,11 @@ public:
*/
[[nodiscard]] QString getLabel() const;
/*
* Returns if the link share's hideDownload is true or false
*/
[[nodiscard]] bool getHideDownload() const;
/*
* Returns the token of the link share.
*/
@ -292,17 +300,24 @@ public slots:
*/
void setLabel(const QString &label);
/*
* Set the hideDownload flag of the share link.
*/
void setHideDownload(const bool hideDownload);
signals:
void expireDateSet();
void noteSet();
void nameSet();
void labelSet();
void hideDownloadSet();
private slots:
void slotNoteSet(const QJsonDocument &, const QVariant &value);
void slotExpireDateSet(const QJsonDocument &reply, const QVariant &value);
void slotNameSet(const QJsonDocument &, const QVariant &value);
void slotLabelSet(const QJsonDocument &, const QVariant &value);
void slotHideDownloadSet(const QJsonDocument &jsonDoc, const QVariant &hideDownload);
private:
QString _name;
@ -311,6 +326,7 @@ private:
QDate _expireDate;
QUrl _url;
QString _label;
bool _hideDownload = false;
};
class UserGroupShare : public Share

View file

@ -122,6 +122,11 @@ QtObject {
readonly property int unifiedSearchResultSectionItemVerticalPadding: 8
readonly property int unifiedSearchResultNothingFoundHorizontalMargin: 10
readonly property int radioButtonCustomMarginLeftInner: 4
readonly property int radioButtonCustomMarginLeftOuter: 5
readonly property int radioButtonCustomRadius: 9
readonly property int radioButtonIndicatorSize: 16
readonly property var fontMetrics: FontMetrics {}
readonly property int activityContentSpace: 4