cozy-sharing 28.2.1 → 28.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,16 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [28.3.1](https://github.com/cozy/cozy-libs/compare/cozy-sharing@28.3.0...cozy-sharing@28.3.1) (2026-01-29)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package cozy-sharing
|
|
9
|
+
|
|
10
|
+
# [28.3.0](https://github.com/cozy/cozy-libs/compare/cozy-sharing@28.2.1...cozy-sharing@28.3.0) (2026-01-26)
|
|
11
|
+
|
|
12
|
+
### Features
|
|
13
|
+
|
|
14
|
+
- Generate and copy folder link in one click ([7b806da](https://github.com/cozy/cozy-libs/commit/7b806dae2564c45d1a469150832ebed3ac47235a))
|
|
15
|
+
|
|
6
16
|
## [28.2.1](https://github.com/cozy/cozy-libs/compare/cozy-sharing@28.2.0...cozy-sharing@28.2.1) (2026-01-15)
|
|
7
17
|
|
|
8
18
|
**Note:** Version bump only for package cozy-sharing
|
|
@@ -2,8 +2,9 @@ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
|
2
2
|
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
3
3
|
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
4
4
|
import PropTypes from 'prop-types';
|
|
5
|
-
import React, { useReducer } from 'react';
|
|
5
|
+
import React, { useReducer, useState } from 'react';
|
|
6
6
|
import { useI18n } from 'twake-i18n';
|
|
7
|
+
import { useClient } from 'cozy-client';
|
|
7
8
|
import Button from 'cozy-ui/transpiled/react/Buttons';
|
|
8
9
|
import Icon from 'cozy-ui/transpiled/react/Icon';
|
|
9
10
|
import CopyIcon from 'cozy-ui/transpiled/react/Icons/Copy';
|
|
@@ -11,9 +12,12 @@ import LinkIcon from 'cozy-ui/transpiled/react/Icons/Link';
|
|
|
11
12
|
import { useAlert } from 'cozy-ui/transpiled/react/providers/Alert';
|
|
12
13
|
import useBreakpoints from 'cozy-ui/transpiled/react/providers/Breakpoints';
|
|
13
14
|
import { ShareRestrictionModal } from './ShareRestrictionModal/ShareRestrictionModal';
|
|
14
|
-
import { copyToClipboard } from './ShareRestrictionModal/helpers';
|
|
15
|
+
import { copyToClipboard, createSharingLink } from './ShareRestrictionModal/helpers';
|
|
16
|
+
import { useSharingContext } from '../hooks/useSharingContext';
|
|
15
17
|
|
|
16
18
|
var ShareByLink = function ShareByLink(_ref) {
|
|
19
|
+
var _navigator;
|
|
20
|
+
|
|
17
21
|
var link = _ref.link,
|
|
18
22
|
document = _ref.document,
|
|
19
23
|
documentType = _ref.documentType;
|
|
@@ -27,8 +31,19 @@ var ShareByLink = function ShareByLink(_ref) {
|
|
|
27
31
|
var _useAlert = useAlert(),
|
|
28
32
|
showAlert = _useAlert.showAlert;
|
|
29
33
|
|
|
30
|
-
var
|
|
31
|
-
|
|
34
|
+
var client = useClient();
|
|
35
|
+
|
|
36
|
+
var _useSharingContext = useSharingContext(),
|
|
37
|
+
shareByLink = _useSharingContext.shareByLink;
|
|
38
|
+
|
|
39
|
+
var _useState = useState(false),
|
|
40
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
41
|
+
isGenerating = _useState2[0],
|
|
42
|
+
setIsGenerating = _useState2[1];
|
|
43
|
+
|
|
44
|
+
var canShare = typeof ((_navigator = navigator) === null || _navigator === void 0 ? void 0 : _navigator.share) === 'function';
|
|
45
|
+
var showCopyAndSendButtons = isMobile && canShare;
|
|
46
|
+
var showOnlyCopyButton = !isMobile || !canShare;
|
|
32
47
|
|
|
33
48
|
var _useReducer = useReducer(function (state) {
|
|
34
49
|
return !state;
|
|
@@ -37,55 +52,158 @@ var ShareByLink = function ShareByLink(_ref) {
|
|
|
37
52
|
isEditDialogOpen = _useReducer2[0],
|
|
38
53
|
toggleEditDialogOpen = _useReducer2[1];
|
|
39
54
|
|
|
40
|
-
var
|
|
55
|
+
var handleGenerateLink = /*#__PURE__*/function () {
|
|
41
56
|
var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
|
|
42
57
|
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
43
58
|
while (1) switch (_context.prev = _context.next) {
|
|
44
59
|
case 0:
|
|
45
|
-
|
|
46
|
-
|
|
60
|
+
setIsGenerating(true);
|
|
61
|
+
_context.prev = 1;
|
|
62
|
+
_context.next = 4;
|
|
63
|
+
return createSharingLink({
|
|
64
|
+
client: client,
|
|
65
|
+
file: document,
|
|
66
|
+
documentType: documentType,
|
|
67
|
+
shareByLink: shareByLink,
|
|
47
68
|
t: t,
|
|
48
|
-
showAlert: showAlert
|
|
69
|
+
showAlert: showAlert,
|
|
70
|
+
password: '',
|
|
71
|
+
ttl: undefined,
|
|
72
|
+
editingRights: 'readOnly'
|
|
49
73
|
});
|
|
50
74
|
|
|
51
|
-
case
|
|
75
|
+
case 4:
|
|
76
|
+
return _context.abrupt("return", _context.sent);
|
|
77
|
+
|
|
78
|
+
case 7:
|
|
79
|
+
_context.prev = 7;
|
|
80
|
+
_context.t0 = _context["catch"](1);
|
|
81
|
+
return _context.abrupt("return", null);
|
|
82
|
+
|
|
83
|
+
case 10:
|
|
84
|
+
_context.prev = 10;
|
|
85
|
+
setIsGenerating(false);
|
|
86
|
+
return _context.finish(10);
|
|
87
|
+
|
|
88
|
+
case 13:
|
|
52
89
|
case "end":
|
|
53
90
|
return _context.stop();
|
|
54
91
|
}
|
|
55
|
-
}, _callee);
|
|
92
|
+
}, _callee, null, [[1, 7, 10, 13]]);
|
|
56
93
|
}));
|
|
57
94
|
|
|
58
|
-
return function
|
|
95
|
+
return function handleGenerateLink() {
|
|
59
96
|
return _ref2.apply(this, arguments);
|
|
60
97
|
};
|
|
61
98
|
}();
|
|
62
99
|
|
|
63
|
-
var
|
|
100
|
+
var generateLinkAndCopyLinkToClipboard = /*#__PURE__*/function () {
|
|
64
101
|
var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
|
|
65
|
-
var
|
|
102
|
+
var linkToCopy;
|
|
66
103
|
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
|
|
67
104
|
while (1) switch (_context2.prev = _context2.next) {
|
|
68
105
|
case 0:
|
|
69
|
-
|
|
106
|
+
linkToCopy = link;
|
|
107
|
+
|
|
108
|
+
if (linkToCopy) {
|
|
109
|
+
_context2.next = 5;
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
_context2.next = 4;
|
|
114
|
+
return handleGenerateLink();
|
|
115
|
+
|
|
116
|
+
case 4:
|
|
117
|
+
linkToCopy = _context2.sent;
|
|
118
|
+
|
|
119
|
+
case 5:
|
|
120
|
+
if (!linkToCopy) {
|
|
121
|
+
_context2.next = 10;
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
_context2.next = 8;
|
|
126
|
+
return copyToClipboard(linkToCopy, {
|
|
127
|
+
t: t,
|
|
128
|
+
showAlert: showAlert
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
case 8:
|
|
132
|
+
_context2.next = 11;
|
|
133
|
+
break;
|
|
134
|
+
|
|
135
|
+
case 10:
|
|
136
|
+
showAlert({
|
|
137
|
+
message: t("".concat(documentType, ".share.error.generic")),
|
|
138
|
+
severity: 'error',
|
|
139
|
+
variant: 'filled'
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
case 11:
|
|
143
|
+
case "end":
|
|
144
|
+
return _context2.stop();
|
|
145
|
+
}
|
|
146
|
+
}, _callee2);
|
|
147
|
+
}));
|
|
148
|
+
|
|
149
|
+
return function generateLinkAndCopyLinkToClipboard() {
|
|
150
|
+
return _ref3.apply(this, arguments);
|
|
151
|
+
};
|
|
152
|
+
}();
|
|
153
|
+
|
|
154
|
+
var shareLink = /*#__PURE__*/function () {
|
|
155
|
+
var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3() {
|
|
156
|
+
var linkToShare, shareData;
|
|
157
|
+
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
|
|
158
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
159
|
+
case 0:
|
|
160
|
+
linkToShare = link;
|
|
161
|
+
|
|
162
|
+
if (linkToShare) {
|
|
163
|
+
_context3.next = 5;
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
_context3.next = 4;
|
|
168
|
+
return handleGenerateLink();
|
|
169
|
+
|
|
170
|
+
case 4:
|
|
171
|
+
linkToShare = _context3.sent;
|
|
172
|
+
|
|
173
|
+
case 5:
|
|
174
|
+
if (linkToShare) {
|
|
175
|
+
_context3.next = 8;
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
showAlert({
|
|
180
|
+
message: t("".concat(documentType, ".share.error.generic")),
|
|
181
|
+
severity: 'error',
|
|
182
|
+
variant: 'filled'
|
|
183
|
+
});
|
|
184
|
+
return _context3.abrupt("return");
|
|
185
|
+
|
|
186
|
+
case 8:
|
|
187
|
+
_context3.prev = 8;
|
|
70
188
|
shareData = {
|
|
71
189
|
text: t("".concat(documentType, ".share.shareByLink.shareDescription"), {
|
|
72
190
|
name: document.name || ''
|
|
73
191
|
}),
|
|
74
|
-
url:
|
|
192
|
+
url: linkToShare
|
|
75
193
|
};
|
|
76
|
-
|
|
194
|
+
_context3.next = 12;
|
|
77
195
|
return navigator.share(shareData);
|
|
78
196
|
|
|
79
|
-
case
|
|
80
|
-
|
|
197
|
+
case 12:
|
|
198
|
+
_context3.next = 17;
|
|
81
199
|
break;
|
|
82
200
|
|
|
83
|
-
case
|
|
84
|
-
|
|
85
|
-
|
|
201
|
+
case 14:
|
|
202
|
+
_context3.prev = 14;
|
|
203
|
+
_context3.t0 = _context3["catch"](8);
|
|
86
204
|
|
|
87
205
|
// Don't show error when user cancels the share dialog
|
|
88
|
-
if (
|
|
206
|
+
if (_context3.t0.name !== 'AbortError') {
|
|
89
207
|
showAlert({
|
|
90
208
|
message: t("".concat(documentType, ".share.error.generic")),
|
|
91
209
|
severity: 'error',
|
|
@@ -93,34 +211,21 @@ var ShareByLink = function ShareByLink(_ref) {
|
|
|
93
211
|
});
|
|
94
212
|
}
|
|
95
213
|
|
|
96
|
-
case
|
|
214
|
+
case 17:
|
|
97
215
|
case "end":
|
|
98
|
-
return
|
|
216
|
+
return _context3.stop();
|
|
99
217
|
}
|
|
100
|
-
},
|
|
218
|
+
}, _callee3, null, [[8, 14]]);
|
|
101
219
|
}));
|
|
102
220
|
|
|
103
221
|
return function shareLink() {
|
|
104
|
-
return
|
|
222
|
+
return _ref4.apply(this, arguments);
|
|
105
223
|
};
|
|
106
224
|
}();
|
|
107
225
|
|
|
108
226
|
return /*#__PURE__*/React.createElement("div", {
|
|
109
227
|
className: "u-w-100 u-flex u-flex-justify-center"
|
|
110
|
-
},
|
|
111
|
-
label: t("".concat(documentType, ".share.shareByLink.create")),
|
|
112
|
-
variant: "secondary",
|
|
113
|
-
size: "medium",
|
|
114
|
-
startIcon: /*#__PURE__*/React.createElement(Icon, {
|
|
115
|
-
icon: LinkIcon
|
|
116
|
-
}),
|
|
117
|
-
className: "u-flex-auto",
|
|
118
|
-
style: {
|
|
119
|
-
position: 'initial'
|
|
120
|
-
} // fix z-index bug on iOS when under a BottomDrawer due to relative position
|
|
121
|
-
,
|
|
122
|
-
onClick: toggleEditDialogOpen
|
|
123
|
-
}), showCopyAndSendButtons && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
|
|
228
|
+
}, showCopyAndSendButtons && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
|
|
124
229
|
label: t("".concat(documentType, ".share.shareByLink.send")),
|
|
125
230
|
variant: "secondary",
|
|
126
231
|
size: "medium",
|
|
@@ -128,14 +233,16 @@ var ShareByLink = function ShareByLink(_ref) {
|
|
|
128
233
|
icon: LinkIcon
|
|
129
234
|
}),
|
|
130
235
|
className: "u-flex-auto u-mr-half",
|
|
131
|
-
onClick: shareLink
|
|
236
|
+
onClick: shareLink,
|
|
237
|
+
busy: isGenerating
|
|
132
238
|
}), /*#__PURE__*/React.createElement(Button, {
|
|
133
239
|
label: /*#__PURE__*/React.createElement(Icon, {
|
|
134
240
|
icon: CopyIcon
|
|
135
241
|
}),
|
|
136
242
|
variant: "secondary",
|
|
137
243
|
size: "medium",
|
|
138
|
-
onClick:
|
|
244
|
+
onClick: generateLinkAndCopyLinkToClipboard,
|
|
245
|
+
disabled: isGenerating
|
|
139
246
|
})), showOnlyCopyButton && /*#__PURE__*/React.createElement(Button, {
|
|
140
247
|
label: t("".concat(documentType, ".share.shareByLink.copy")),
|
|
141
248
|
variant: "secondary",
|
|
@@ -144,7 +251,8 @@ var ShareByLink = function ShareByLink(_ref) {
|
|
|
144
251
|
icon: LinkIcon
|
|
145
252
|
}),
|
|
146
253
|
className: "u-flex-auto u-mr-half",
|
|
147
|
-
onClick:
|
|
254
|
+
onClick: generateLinkAndCopyLinkToClipboard,
|
|
255
|
+
busy: isGenerating
|
|
148
256
|
}), isEditDialogOpen && /*#__PURE__*/React.createElement(ShareRestrictionModal, {
|
|
149
257
|
file: document,
|
|
150
258
|
onClose: toggleEditDialogOpen
|
|
@@ -1,9 +1,82 @@
|
|
|
1
1
|
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
2
2
|
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
3
|
+
import { generateWebLink } from 'cozy-client';
|
|
3
4
|
import minilog from 'cozy-minilog';
|
|
5
|
+
import { getAppSlugFromDocumentType } from '../../helpers/link';
|
|
4
6
|
var log = minilog('ShareRestrictionModal/helpers');
|
|
5
7
|
export var WRITE_PERMS = ['GET', 'POST', 'PUT', 'PATCH'];
|
|
6
8
|
export var READ_ONLY_PERMS = ['GET'];
|
|
9
|
+
/**
|
|
10
|
+
* Create a sharing link for a file with specified options
|
|
11
|
+
* @param {object} options
|
|
12
|
+
* @param {object} options.client - CozyClient instance
|
|
13
|
+
* @param {object} options.file - File to share
|
|
14
|
+
* @param {string} options.documentType - Type of the document
|
|
15
|
+
* @param {Function} options.shareByLink - Function to create permissions
|
|
16
|
+
* @param {Function} options.t - Translation function
|
|
17
|
+
* @param {Function} options.showAlert - Function to display an alert
|
|
18
|
+
* @param {Date|string} [options.ttl] - Time to live of the sharing link
|
|
19
|
+
* @param {'readOnly'|'write'} [options.editingRights] - Editing rights
|
|
20
|
+
* @param {string} [options.password] - Password
|
|
21
|
+
* @param {boolean} [options.withTTL] - Whether to add a default TTL
|
|
22
|
+
* @returns {Promise<string|null>} - The generated web link or null if permissions creation fails
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
export var createSharingLink = /*#__PURE__*/function () {
|
|
26
|
+
var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(_ref) {
|
|
27
|
+
var _permsResult$data;
|
|
28
|
+
|
|
29
|
+
var client, file, documentType, shareByLink, t, ttl, _ref$editingRights, editingRights, password, showAlert, permsResult, perms;
|
|
30
|
+
|
|
31
|
+
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
32
|
+
while (1) switch (_context.prev = _context.next) {
|
|
33
|
+
case 0:
|
|
34
|
+
client = _ref.client, file = _ref.file, documentType = _ref.documentType, shareByLink = _ref.shareByLink, t = _ref.t, ttl = _ref.ttl, _ref$editingRights = _ref.editingRights, editingRights = _ref$editingRights === void 0 ? 'readOnly' : _ref$editingRights, password = _ref.password, showAlert = _ref.showAlert;
|
|
35
|
+
_context.next = 3;
|
|
36
|
+
return createPermissions({
|
|
37
|
+
file: file,
|
|
38
|
+
t: t,
|
|
39
|
+
ttl: ttl,
|
|
40
|
+
editingRights: editingRights,
|
|
41
|
+
password: password,
|
|
42
|
+
documentType: documentType,
|
|
43
|
+
shareByLink: shareByLink,
|
|
44
|
+
showAlert: showAlert
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
case 3:
|
|
48
|
+
permsResult = _context.sent;
|
|
49
|
+
|
|
50
|
+
if (permsResult !== null && permsResult !== void 0 && (_permsResult$data = permsResult.data) !== null && _permsResult$data !== void 0 && (_permsResult$data = _permsResult$data.attributes) !== null && _permsResult$data !== void 0 && (_permsResult$data = _permsResult$data.shortcodes) !== null && _permsResult$data !== void 0 && _permsResult$data.code) {
|
|
51
|
+
_context.next = 6;
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return _context.abrupt("return", null);
|
|
56
|
+
|
|
57
|
+
case 6:
|
|
58
|
+
perms = permsResult.data;
|
|
59
|
+
return _context.abrupt("return", generateWebLink({
|
|
60
|
+
cozyUrl: client.getStackClient().uri,
|
|
61
|
+
searchParams: [['sharecode', perms.attributes.shortcodes.code]],
|
|
62
|
+
pathname: '/public',
|
|
63
|
+
slug: getAppSlugFromDocumentType({
|
|
64
|
+
documentType: documentType
|
|
65
|
+
}),
|
|
66
|
+
subDomainType: client.capabilities.flat_subdomains ? 'flat' : 'nested'
|
|
67
|
+
}));
|
|
68
|
+
|
|
69
|
+
case 8:
|
|
70
|
+
case "end":
|
|
71
|
+
return _context.stop();
|
|
72
|
+
}
|
|
73
|
+
}, _callee);
|
|
74
|
+
}));
|
|
75
|
+
|
|
76
|
+
return function createSharingLink(_x) {
|
|
77
|
+
return _ref2.apply(this, arguments);
|
|
78
|
+
};
|
|
79
|
+
}();
|
|
7
80
|
/**
|
|
8
81
|
* Copy a string to the clipboard
|
|
9
82
|
*
|
|
@@ -14,27 +87,27 @@ export var READ_ONLY_PERMS = ['GET'];
|
|
|
14
87
|
*/
|
|
15
88
|
|
|
16
89
|
export var copyToClipboard = /*#__PURE__*/function () {
|
|
17
|
-
var
|
|
18
|
-
var
|
|
90
|
+
var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(value) {
|
|
91
|
+
var _ref4,
|
|
19
92
|
t,
|
|
20
93
|
showAlert,
|
|
21
|
-
|
|
94
|
+
_args2 = arguments;
|
|
22
95
|
|
|
23
|
-
return _regeneratorRuntime.wrap(function
|
|
24
|
-
while (1) switch (
|
|
96
|
+
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
|
|
97
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
25
98
|
case 0:
|
|
26
|
-
|
|
99
|
+
_ref4 = _args2.length > 1 && _args2[1] !== undefined ? _args2[1] : {}, t = _ref4.t, showAlert = _ref4.showAlert;
|
|
27
100
|
|
|
28
101
|
if (value) {
|
|
29
|
-
|
|
102
|
+
_context2.next = 3;
|
|
30
103
|
break;
|
|
31
104
|
}
|
|
32
105
|
|
|
33
|
-
return
|
|
106
|
+
return _context2.abrupt("return", false);
|
|
34
107
|
|
|
35
108
|
case 3:
|
|
36
|
-
|
|
37
|
-
|
|
109
|
+
_context2.prev = 3;
|
|
110
|
+
_context2.next = 6;
|
|
38
111
|
return navigator.clipboard.writeText(value);
|
|
39
112
|
|
|
40
113
|
case 6:
|
|
@@ -43,28 +116,28 @@ export var copyToClipboard = /*#__PURE__*/function () {
|
|
|
43
116
|
severity: 'success',
|
|
44
117
|
variant: 'filled'
|
|
45
118
|
});
|
|
46
|
-
|
|
119
|
+
_context2.next = 13;
|
|
47
120
|
break;
|
|
48
121
|
|
|
49
122
|
case 9:
|
|
50
|
-
|
|
51
|
-
|
|
123
|
+
_context2.prev = 9;
|
|
124
|
+
_context2.t0 = _context2["catch"](3);
|
|
52
125
|
showAlert({
|
|
53
126
|
message: t('copyReminderContent.error'),
|
|
54
127
|
severity: 'error',
|
|
55
128
|
variant: 'filled'
|
|
56
129
|
});
|
|
57
|
-
log.error("Error in 'copyToClipboard' function when trying to copy to clipboard",
|
|
130
|
+
log.error("Error in 'copyToClipboard' function when trying to copy to clipboard", _context2.t0);
|
|
58
131
|
|
|
59
132
|
case 13:
|
|
60
133
|
case "end":
|
|
61
|
-
return
|
|
134
|
+
return _context2.stop();
|
|
62
135
|
}
|
|
63
|
-
},
|
|
136
|
+
}, _callee2, null, [[3, 9]]);
|
|
64
137
|
}));
|
|
65
138
|
|
|
66
|
-
return function copyToClipboard(
|
|
67
|
-
return
|
|
139
|
+
return function copyToClipboard(_x2) {
|
|
140
|
+
return _ref3.apply(this, arguments);
|
|
68
141
|
};
|
|
69
142
|
}();
|
|
70
143
|
/**
|
|
@@ -115,39 +188,39 @@ export var makeTTL = function makeTTL(selectedDate) {
|
|
|
115
188
|
*/
|
|
116
189
|
|
|
117
190
|
export var createPermissions = /*#__PURE__*/function () {
|
|
118
|
-
var
|
|
191
|
+
var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(_ref5) {
|
|
119
192
|
var file, t, ttl, password, editingRights, documentType, shareByLink, showAlert, verbs;
|
|
120
|
-
return _regeneratorRuntime.wrap(function
|
|
121
|
-
while (1) switch (
|
|
193
|
+
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
|
|
194
|
+
while (1) switch (_context3.prev = _context3.next) {
|
|
122
195
|
case 0:
|
|
123
|
-
file =
|
|
124
|
-
|
|
196
|
+
file = _ref5.file, t = _ref5.t, ttl = _ref5.ttl, password = _ref5.password, editingRights = _ref5.editingRights, documentType = _ref5.documentType, shareByLink = _ref5.shareByLink, showAlert = _ref5.showAlert;
|
|
197
|
+
_context3.prev = 1;
|
|
125
198
|
verbs = editingRights === 'readOnly' ? READ_ONLY_PERMS : WRITE_PERMS;
|
|
126
|
-
return
|
|
199
|
+
return _context3.abrupt("return", shareByLink(file, {
|
|
127
200
|
verbs: verbs,
|
|
128
201
|
ttl: ttl,
|
|
129
202
|
password: password
|
|
130
203
|
}));
|
|
131
204
|
|
|
132
205
|
case 6:
|
|
133
|
-
|
|
134
|
-
|
|
206
|
+
_context3.prev = 6;
|
|
207
|
+
_context3.t0 = _context3["catch"](1);
|
|
135
208
|
showAlert({
|
|
136
209
|
message: t("".concat(documentType, ".share.shareByLink.permserror")),
|
|
137
210
|
severity: 'error',
|
|
138
211
|
variant: 'filled'
|
|
139
212
|
});
|
|
140
|
-
log.error("Error in 'readOnlyPermissionLink' function when trying to change permission",
|
|
213
|
+
log.error("Error in 'readOnlyPermissionLink' function when trying to change permission", _context3.t0);
|
|
141
214
|
|
|
142
215
|
case 10:
|
|
143
216
|
case "end":
|
|
144
|
-
return
|
|
217
|
+
return _context3.stop();
|
|
145
218
|
}
|
|
146
|
-
},
|
|
219
|
+
}, _callee3, null, [[1, 6]]);
|
|
147
220
|
}));
|
|
148
221
|
|
|
149
|
-
return function createPermissions(
|
|
150
|
-
return
|
|
222
|
+
return function createPermissions(_x3) {
|
|
223
|
+
return _ref6.apply(this, arguments);
|
|
151
224
|
};
|
|
152
225
|
}();
|
|
153
226
|
/**
|
|
@@ -166,41 +239,41 @@ export var createPermissions = /*#__PURE__*/function () {
|
|
|
166
239
|
*/
|
|
167
240
|
|
|
168
241
|
export var updatePermissions = /*#__PURE__*/function () {
|
|
169
|
-
var
|
|
242
|
+
var _ref8 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4(_ref7) {
|
|
170
243
|
var file, t, dateToggle, selectedDate, passwordToggle, password, editingRights, documentType, updateDocumentPermissions, showAlert, expiresAt, ensurePassword, verbs;
|
|
171
|
-
return _regeneratorRuntime.wrap(function
|
|
172
|
-
while (1) switch (
|
|
244
|
+
return _regeneratorRuntime.wrap(function _callee4$(_context4) {
|
|
245
|
+
while (1) switch (_context4.prev = _context4.next) {
|
|
173
246
|
case 0:
|
|
174
|
-
file =
|
|
175
|
-
|
|
247
|
+
file = _ref7.file, t = _ref7.t, dateToggle = _ref7.dateToggle, selectedDate = _ref7.selectedDate, passwordToggle = _ref7.passwordToggle, password = _ref7.password, editingRights = _ref7.editingRights, documentType = _ref7.documentType, updateDocumentPermissions = _ref7.updateDocumentPermissions, showAlert = _ref7.showAlert;
|
|
248
|
+
_context4.prev = 1;
|
|
176
249
|
expiresAt = dateToggle ? (selectedDate === null || selectedDate === void 0 ? void 0 : selectedDate.toISOString()) || undefined : '';
|
|
177
250
|
ensurePassword = passwordToggle ? password || undefined : '';
|
|
178
251
|
verbs = editingRights === 'readOnly' ? READ_ONLY_PERMS : WRITE_PERMS;
|
|
179
|
-
return
|
|
252
|
+
return _context4.abrupt("return", updateDocumentPermissions(file, {
|
|
180
253
|
verbs: verbs,
|
|
181
254
|
expiresAt: expiresAt,
|
|
182
255
|
password: ensurePassword
|
|
183
256
|
}));
|
|
184
257
|
|
|
185
258
|
case 8:
|
|
186
|
-
|
|
187
|
-
|
|
259
|
+
_context4.prev = 8;
|
|
260
|
+
_context4.t0 = _context4["catch"](1);
|
|
188
261
|
showAlert({
|
|
189
262
|
message: t("".concat(documentType, ".share.shareByLink.permserror")),
|
|
190
263
|
severity: 'error',
|
|
191
264
|
variant: 'filled'
|
|
192
265
|
});
|
|
193
|
-
log.error("Error in 'updateDocumentPermissions' function when trying to change permission",
|
|
266
|
+
log.error("Error in 'updateDocumentPermissions' function when trying to change permission", _context4.t0);
|
|
194
267
|
|
|
195
268
|
case 12:
|
|
196
269
|
case "end":
|
|
197
|
-
return
|
|
270
|
+
return _context4.stop();
|
|
198
271
|
}
|
|
199
|
-
},
|
|
272
|
+
}, _callee4, null, [[1, 8]]);
|
|
200
273
|
}));
|
|
201
274
|
|
|
202
|
-
return function updatePermissions(
|
|
203
|
-
return
|
|
275
|
+
return function updatePermissions(_x4) {
|
|
276
|
+
return _ref8.apply(this, arguments);
|
|
204
277
|
};
|
|
205
278
|
}();
|
|
206
279
|
/**
|
|
@@ -214,33 +287,33 @@ export var updatePermissions = /*#__PURE__*/function () {
|
|
|
214
287
|
*/
|
|
215
288
|
|
|
216
289
|
export var revokePermissions = /*#__PURE__*/function () {
|
|
217
|
-
var
|
|
290
|
+
var _ref10 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5(_ref9) {
|
|
218
291
|
var file, t, documentType, revokeSharingLink, showAlert;
|
|
219
|
-
return _regeneratorRuntime.wrap(function
|
|
220
|
-
while (1) switch (
|
|
292
|
+
return _regeneratorRuntime.wrap(function _callee5$(_context5) {
|
|
293
|
+
while (1) switch (_context5.prev = _context5.next) {
|
|
221
294
|
case 0:
|
|
222
|
-
file =
|
|
223
|
-
|
|
224
|
-
return
|
|
295
|
+
file = _ref9.file, t = _ref9.t, documentType = _ref9.documentType, revokeSharingLink = _ref9.revokeSharingLink, showAlert = _ref9.showAlert;
|
|
296
|
+
_context5.prev = 1;
|
|
297
|
+
return _context5.abrupt("return", revokeSharingLink(file));
|
|
225
298
|
|
|
226
299
|
case 5:
|
|
227
|
-
|
|
228
|
-
|
|
300
|
+
_context5.prev = 5;
|
|
301
|
+
_context5.t0 = _context5["catch"](1);
|
|
229
302
|
showAlert({
|
|
230
303
|
message: t("".concat(documentType, ".share.error.revoke")),
|
|
231
304
|
severity: 'error',
|
|
232
305
|
variant: 'filled'
|
|
233
306
|
});
|
|
234
|
-
log.error("Error in 'revokePermissions' function when trying to revoke sharing link",
|
|
307
|
+
log.error("Error in 'revokePermissions' function when trying to revoke sharing link", _context5.t0);
|
|
235
308
|
|
|
236
309
|
case 9:
|
|
237
310
|
case "end":
|
|
238
|
-
return
|
|
311
|
+
return _context5.stop();
|
|
239
312
|
}
|
|
240
|
-
},
|
|
313
|
+
}, _callee5, null, [[1, 5]]);
|
|
241
314
|
}));
|
|
242
315
|
|
|
243
|
-
return function revokePermissions(
|
|
244
|
-
return
|
|
316
|
+
return function revokePermissions(_x5) {
|
|
317
|
+
return _ref10.apply(this, arguments);
|
|
245
318
|
};
|
|
246
319
|
}();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cozy-sharing",
|
|
3
|
-
"version": "28.
|
|
3
|
+
"version": "28.3.1",
|
|
4
4
|
"description": "Provides sharing login for React applications.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"author": "Cozy",
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@cozy/minilog": "^1.0.0",
|
|
32
32
|
"classnames": "^2.5.1",
|
|
33
|
-
"cozy-device-helper": "^4.0.
|
|
34
|
-
"cozy-doctypes": "^1.98.
|
|
33
|
+
"cozy-device-helper": "^4.0.2",
|
|
34
|
+
"cozy-doctypes": "^1.98.3",
|
|
35
35
|
"date-fns": "2.30.0",
|
|
36
36
|
"lodash": "^4.17.21",
|
|
37
37
|
"react-autosuggest": "^10.1.0",
|
|
@@ -56,17 +56,17 @@
|
|
|
56
56
|
"babel-plugin-inline-react-svg": "1.1.2",
|
|
57
57
|
"cozy-client": "^60.19.0",
|
|
58
58
|
"cozy-device-helper": "^3.7.1",
|
|
59
|
-
"cozy-intent": "^2.30.
|
|
59
|
+
"cozy-intent": "^2.30.2",
|
|
60
60
|
"cozy-minilog": "^3.10.0",
|
|
61
61
|
"cozy-ui": "^135.0.0",
|
|
62
|
-
"cozy-ui-plus": "^4.4.
|
|
62
|
+
"cozy-ui-plus": "^4.4.1",
|
|
63
63
|
"jest": "26.6.3",
|
|
64
64
|
"jest-environment-jsdom": "26.6.2",
|
|
65
65
|
"react": "16.12.0",
|
|
66
66
|
"react-dom": "16.13.0",
|
|
67
67
|
"react-router": "^5.0.1",
|
|
68
68
|
"storybook": "7.6.0",
|
|
69
|
-
"twake-i18n": "^0.3.
|
|
69
|
+
"twake-i18n": "^0.3.1"
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
72
72
|
"cozy-client": ">=60.19.0",
|
|
@@ -83,5 +83,5 @@
|
|
|
83
83
|
"sideEffects": [
|
|
84
84
|
"*.css"
|
|
85
85
|
],
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "80ec928bcefb30b6ea6ed778fbd71e3417c2efa6"
|
|
87
87
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import PropTypes from 'prop-types'
|
|
2
|
-
import React, { useReducer } from 'react'
|
|
2
|
+
import React, { useReducer, useState } from 'react'
|
|
3
3
|
import { useI18n } from 'twake-i18n'
|
|
4
4
|
|
|
5
|
+
import { useClient } from 'cozy-client'
|
|
5
6
|
import Button from 'cozy-ui/transpiled/react/Buttons'
|
|
6
7
|
import Icon from 'cozy-ui/transpiled/react/Icon'
|
|
7
8
|
import CopyIcon from 'cozy-ui/transpiled/react/Icons/Copy'
|
|
@@ -10,33 +11,86 @@ import { useAlert } from 'cozy-ui/transpiled/react/providers/Alert'
|
|
|
10
11
|
import useBreakpoints from 'cozy-ui/transpiled/react/providers/Breakpoints'
|
|
11
12
|
|
|
12
13
|
import { ShareRestrictionModal } from './ShareRestrictionModal/ShareRestrictionModal'
|
|
13
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
copyToClipboard,
|
|
16
|
+
createSharingLink
|
|
17
|
+
} from './ShareRestrictionModal/helpers'
|
|
18
|
+
import { useSharingContext } from '../hooks/useSharingContext'
|
|
14
19
|
|
|
15
20
|
const ShareByLink = ({ link, document, documentType }) => {
|
|
16
21
|
const { t } = useI18n()
|
|
17
22
|
const { isMobile } = useBreakpoints()
|
|
18
23
|
const { showAlert } = useAlert()
|
|
24
|
+
const client = useClient()
|
|
25
|
+
const { shareByLink } = useSharingContext()
|
|
26
|
+
const [isGenerating, setIsGenerating] = useState(false)
|
|
19
27
|
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
28
|
+
const canShare = typeof navigator?.share === 'function'
|
|
29
|
+
const showCopyAndSendButtons = isMobile && canShare
|
|
30
|
+
const showOnlyCopyButton = !isMobile || !canShare
|
|
23
31
|
|
|
24
32
|
const [isEditDialogOpen, toggleEditDialogOpen] = useReducer(
|
|
25
33
|
state => !state,
|
|
26
34
|
false
|
|
27
35
|
)
|
|
28
36
|
|
|
29
|
-
const
|
|
30
|
-
|
|
37
|
+
const handleGenerateLink = async () => {
|
|
38
|
+
setIsGenerating(true)
|
|
39
|
+
try {
|
|
40
|
+
return await createSharingLink({
|
|
41
|
+
client,
|
|
42
|
+
file: document,
|
|
43
|
+
documentType,
|
|
44
|
+
shareByLink,
|
|
45
|
+
t,
|
|
46
|
+
showAlert,
|
|
47
|
+
password: '',
|
|
48
|
+
ttl: undefined,
|
|
49
|
+
editingRights: 'readOnly'
|
|
50
|
+
})
|
|
51
|
+
} catch (error) {
|
|
52
|
+
return null
|
|
53
|
+
} finally {
|
|
54
|
+
setIsGenerating(false)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const generateLinkAndCopyLinkToClipboard = async () => {
|
|
59
|
+
let linkToCopy = link
|
|
60
|
+
if (!linkToCopy) {
|
|
61
|
+
linkToCopy = await handleGenerateLink()
|
|
62
|
+
}
|
|
63
|
+
if (linkToCopy) {
|
|
64
|
+
await copyToClipboard(linkToCopy, { t, showAlert })
|
|
65
|
+
} else {
|
|
66
|
+
showAlert({
|
|
67
|
+
message: t(`${documentType}.share.error.generic`),
|
|
68
|
+
severity: 'error',
|
|
69
|
+
variant: 'filled'
|
|
70
|
+
})
|
|
71
|
+
}
|
|
31
72
|
}
|
|
32
73
|
|
|
33
74
|
const shareLink = async () => {
|
|
75
|
+
let linkToShare = link
|
|
76
|
+
if (!linkToShare) {
|
|
77
|
+
linkToShare = await handleGenerateLink()
|
|
78
|
+
}
|
|
79
|
+
if (!linkToShare) {
|
|
80
|
+
showAlert({
|
|
81
|
+
message: t(`${documentType}.share.error.generic`),
|
|
82
|
+
severity: 'error',
|
|
83
|
+
variant: 'filled'
|
|
84
|
+
})
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
|
|
34
88
|
try {
|
|
35
89
|
const shareData = {
|
|
36
90
|
text: t(`${documentType}.share.shareByLink.shareDescription`, {
|
|
37
91
|
name: document.name || ''
|
|
38
92
|
}),
|
|
39
|
-
url:
|
|
93
|
+
url: linkToShare
|
|
40
94
|
}
|
|
41
95
|
await navigator.share(shareData)
|
|
42
96
|
} catch (error) {
|
|
@@ -53,17 +107,6 @@ const ShareByLink = ({ link, document, documentType }) => {
|
|
|
53
107
|
|
|
54
108
|
return (
|
|
55
109
|
<div className="u-w-100 u-flex u-flex-justify-center">
|
|
56
|
-
{!link && (
|
|
57
|
-
<Button
|
|
58
|
-
label={t(`${documentType}.share.shareByLink.create`)}
|
|
59
|
-
variant="secondary"
|
|
60
|
-
size="medium"
|
|
61
|
-
startIcon={<Icon icon={LinkIcon} />}
|
|
62
|
-
className="u-flex-auto"
|
|
63
|
-
style={{ position: 'initial' }} // fix z-index bug on iOS when under a BottomDrawer due to relative position
|
|
64
|
-
onClick={toggleEditDialogOpen}
|
|
65
|
-
/>
|
|
66
|
-
)}
|
|
67
110
|
{showCopyAndSendButtons && (
|
|
68
111
|
<>
|
|
69
112
|
<Button
|
|
@@ -73,12 +116,14 @@ const ShareByLink = ({ link, document, documentType }) => {
|
|
|
73
116
|
startIcon={<Icon icon={LinkIcon} />}
|
|
74
117
|
className="u-flex-auto u-mr-half"
|
|
75
118
|
onClick={shareLink}
|
|
119
|
+
busy={isGenerating}
|
|
76
120
|
/>
|
|
77
121
|
<Button
|
|
78
122
|
label={<Icon icon={CopyIcon} />}
|
|
79
123
|
variant="secondary"
|
|
80
124
|
size="medium"
|
|
81
|
-
onClick={
|
|
125
|
+
onClick={generateLinkAndCopyLinkToClipboard}
|
|
126
|
+
disabled={isGenerating}
|
|
82
127
|
/>
|
|
83
128
|
</>
|
|
84
129
|
)}
|
|
@@ -89,7 +134,8 @@ const ShareByLink = ({ link, document, documentType }) => {
|
|
|
89
134
|
size="medium"
|
|
90
135
|
startIcon={<Icon icon={LinkIcon} />}
|
|
91
136
|
className="u-flex-auto u-mr-half"
|
|
92
|
-
onClick={
|
|
137
|
+
onClick={generateLinkAndCopyLinkToClipboard}
|
|
138
|
+
busy={isGenerating}
|
|
93
139
|
/>
|
|
94
140
|
)}
|
|
95
141
|
{isEditDialogOpen && (
|
|
@@ -1,10 +1,62 @@
|
|
|
1
|
+
import { generateWebLink } from 'cozy-client'
|
|
1
2
|
import minilog from 'cozy-minilog'
|
|
2
3
|
|
|
4
|
+
import { getAppSlugFromDocumentType } from '../../helpers/link'
|
|
5
|
+
|
|
3
6
|
const log = minilog('ShareRestrictionModal/helpers')
|
|
4
7
|
|
|
5
8
|
export const WRITE_PERMS = ['GET', 'POST', 'PUT', 'PATCH']
|
|
6
9
|
export const READ_ONLY_PERMS = ['GET']
|
|
7
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Create a sharing link for a file with specified options
|
|
13
|
+
* @param {object} options
|
|
14
|
+
* @param {object} options.client - CozyClient instance
|
|
15
|
+
* @param {object} options.file - File to share
|
|
16
|
+
* @param {string} options.documentType - Type of the document
|
|
17
|
+
* @param {Function} options.shareByLink - Function to create permissions
|
|
18
|
+
* @param {Function} options.t - Translation function
|
|
19
|
+
* @param {Function} options.showAlert - Function to display an alert
|
|
20
|
+
* @param {Date|string} [options.ttl] - Time to live of the sharing link
|
|
21
|
+
* @param {'readOnly'|'write'} [options.editingRights] - Editing rights
|
|
22
|
+
* @param {string} [options.password] - Password
|
|
23
|
+
* @param {boolean} [options.withTTL] - Whether to add a default TTL
|
|
24
|
+
* @returns {Promise<string|null>} - The generated web link or null if permissions creation fails
|
|
25
|
+
*/
|
|
26
|
+
export const createSharingLink = async ({
|
|
27
|
+
client,
|
|
28
|
+
file,
|
|
29
|
+
documentType,
|
|
30
|
+
shareByLink,
|
|
31
|
+
t,
|
|
32
|
+
ttl,
|
|
33
|
+
editingRights = 'readOnly',
|
|
34
|
+
password,
|
|
35
|
+
showAlert
|
|
36
|
+
}) => {
|
|
37
|
+
const permsResult = await createPermissions({
|
|
38
|
+
file,
|
|
39
|
+
t,
|
|
40
|
+
ttl,
|
|
41
|
+
editingRights,
|
|
42
|
+
password,
|
|
43
|
+
documentType,
|
|
44
|
+
shareByLink,
|
|
45
|
+
showAlert
|
|
46
|
+
})
|
|
47
|
+
if (!permsResult?.data?.attributes?.shortcodes?.code) {
|
|
48
|
+
return null
|
|
49
|
+
}
|
|
50
|
+
const { data: perms } = permsResult
|
|
51
|
+
return generateWebLink({
|
|
52
|
+
cozyUrl: client.getStackClient().uri,
|
|
53
|
+
searchParams: [['sharecode', perms.attributes.shortcodes.code]],
|
|
54
|
+
pathname: '/public',
|
|
55
|
+
slug: getAppSlugFromDocumentType({ documentType }),
|
|
56
|
+
subDomainType: client.capabilities.flat_subdomains ? 'flat' : 'nested'
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
|
|
8
60
|
/**
|
|
9
61
|
* Copy a string to the clipboard
|
|
10
62
|
*
|