cozy-viewer 25.0.1 → 26.0.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/Footer/FooterContent.d.ts +3 -1
  3. package/dist/Footer/FooterContent.js +6 -4
  4. package/dist/Panel/AI/AIAssistantPanel.d.ts +17 -0
  5. package/dist/Panel/AI/AIAssistantPanel.js +339 -0
  6. package/dist/Panel/AI/prompts.d.ts +6 -0
  7. package/dist/Panel/AI/prompts.js +25 -0
  8. package/dist/ViewerContainer.d.ts +2 -24
  9. package/dist/ViewerContainer.js +5 -1
  10. package/dist/ViewerInformationsWrapper.js +28 -3
  11. package/dist/ViewersByFile/PdfJsViewer.d.ts +1 -0
  12. package/dist/ViewersByFile/PdfJsViewer.js +9 -1
  13. package/dist/components/Footer.js +2 -1
  14. package/dist/components/Navigation.js +2 -1
  15. package/dist/components/Toolbar.js +40 -4
  16. package/dist/components/ViewerControls.js +6 -3
  17. package/dist/helpers.d.ts +5 -0
  18. package/dist/helpers.js +96 -2
  19. package/dist/locales/index.js +52 -0
  20. package/dist/providers/ViewerProvider.js +20 -1
  21. package/dist/stylesheet.css +56 -0
  22. package/jest.config.js +12 -3
  23. package/package.json +6 -4
  24. package/src/Footer/FooterContent.jsx +16 -8
  25. package/src/NoViewer/__snapshots__/NoViewer.spec.jsx.snap +1 -1
  26. package/src/Panel/AI/AIAssistantPanel.jsx +221 -0
  27. package/src/Panel/AI/prompts.js +29 -0
  28. package/src/Panel/AI/styles.styl +22 -0
  29. package/src/ViewerContainer.jsx +2 -1
  30. package/src/ViewerInformationsWrapper.jsx +43 -10
  31. package/src/ViewerInformationsWrapper.spec.jsx +13 -7
  32. package/src/ViewersByFile/PdfJsViewer.jsx +8 -0
  33. package/src/ViewersByFile/__snapshots__/ShortcutViewer.spec.jsx.snap +1 -1
  34. package/src/components/Toolbar.jsx +38 -3
  35. package/src/components/ViewerControls.jsx +8 -1
  36. package/src/components/styles.styl +5 -0
  37. package/src/helpers.js +87 -0
  38. package/src/helpers.spec.js +130 -1
  39. package/src/locales/en.json +13 -0
  40. package/src/locales/fr.json +13 -0
  41. package/src/locales/ru.json +13 -0
  42. package/src/locales/vi.json +13 -0
  43. package/src/providers/ViewerProvider.jsx +9 -2
  44. package/test/__mocks__/cozy-harvest-lib.js +3 -0
  45. package/test/__mocks__/cozy-intent.js +7 -0
  46. package/test/__mocks__/cozy-sharing.js +8 -0
  47. package/test/__mocks__/cozyFlagsMock.js +2 -0
  48. package/test/__mocks__/twake-i18n.js +55 -0
package/CHANGELOG.md CHANGED
@@ -3,6 +3,22 @@
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
+ ## [26.0.1](https://github.com/cozy/cozy-libs/compare/cozy-viewer@26.0.0...cozy-viewer@26.0.1) (2025-12-08)
7
+
8
+ ### Bug Fixes
9
+
10
+ - Fix usage of twake-i18n :bug: ([5620f15](https://github.com/cozy/cozy-libs/commit/5620f156f1891a671393a41bf1d1f28c9ec06bda))
11
+
12
+ # [26.0.0](https://github.com/cozy/cozy-libs/compare/cozy-viewer@25.0.1...cozy-viewer@26.0.0) (2025-12-08)
13
+
14
+ ### Features
15
+
16
+ - Implement summarization by AI :sparkles: ([eeed0b4](https://github.com/cozy/cozy-libs/commit/eeed0b4b2bb36a9ec4bb318ea9f75ef93d414c96))
17
+
18
+ ### BREAKING CHANGES
19
+
20
+ - You need to add react-router-dom >= 6.14.2 as dep in your app :heavy_plus_sign:
21
+
6
22
  ## [25.0.1](https://github.com/cozy/cozy-libs/compare/cozy-viewer@25.0.0...cozy-viewer@25.0.1) (2025-12-05)
7
23
 
8
24
  **Note:** Version bump only for package cozy-viewer
@@ -1,12 +1,14 @@
1
1
  export default FooterContent;
2
- declare function FooterContent({ toolbarRef, children }: {
2
+ declare function FooterContent({ toolbarRef, children, isDisplayChildrenDirectly }: {
3
3
  toolbarRef: any;
4
4
  children: any;
5
+ isDisplayChildrenDirectly: any;
5
6
  }): JSX.Element;
6
7
  declare namespace FooterContent {
7
8
  namespace propTypes {
8
9
  let toolbarRef: PropTypes.Requireable<object>;
9
10
  let children: PropTypes.Requireable<NonNullable<PropTypes.ReactNodeLike>>;
11
+ let isDisplayChildrenDirectly: PropTypes.Requireable<boolean>;
10
12
  }
11
13
  }
12
14
  import PropTypes from 'prop-types';
@@ -47,7 +47,8 @@ var useStyles = (0, _styles.makeStyles)(function (theme) {
47
47
 
48
48
  var FooterContent = function FooterContent(_ref) {
49
49
  var toolbarRef = _ref.toolbarRef,
50
- children = _ref.children;
50
+ children = _ref.children,
51
+ isDisplayChildrenDirectly = _ref.isDisplayChildrenDirectly;
51
52
  var styles = useStyles();
52
53
 
53
54
  var _useViewer = (0, _ViewerProvider.useViewer)(),
@@ -74,14 +75,15 @@ var FooterContent = function FooterContent(_ref) {
74
75
  disablePortal: true
75
76
  },
76
77
  settings: bottomSheetSettings
77
- }, /*#__PURE__*/_react.default.createElement(_BottomSheet.BottomSheetHeader, {
78
+ }, isDisplayChildrenDirectly ? children : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_BottomSheet.BottomSheetHeader, {
78
79
  className: (0, _classnames.default)('u-ph-1 u-pb-1', styles.bottomSheetHeader)
79
- }, FooterActionButtonsWithFile), /*#__PURE__*/_react.default.createElement(_BottomSheetContent.default, null));
80
+ }, FooterActionButtonsWithFile), /*#__PURE__*/_react.default.createElement(_BottomSheetContent.default, null)));
80
81
  };
81
82
 
82
83
  FooterContent.propTypes = {
83
84
  toolbarRef: _propTypes.default.object,
84
- children: _propTypes.default.oneOfType([_propTypes.default.node, _propTypes.default.arrayOf(_propTypes.default.node)])
85
+ children: _propTypes.default.oneOfType([_propTypes.default.node, _propTypes.default.arrayOf(_propTypes.default.node)]),
86
+ isDisplayChildrenDirectly: _propTypes.default.bool
85
87
  };
86
88
  var _default = FooterContent;
87
89
  exports.default = _default;
@@ -0,0 +1,17 @@
1
+ export default AIAssistantPanel;
2
+ declare function AIAssistantPanel(): JSX.Element;
3
+ declare namespace AIAssistantPanel {
4
+ namespace propTypes {
5
+ let isLoading: PropTypes.Requireable<boolean>;
6
+ let summary: PropTypes.Requireable<string>;
7
+ let onStop: PropTypes.Requireable<(...args: any[]) => any>;
8
+ let onSend: PropTypes.Requireable<(...args: any[]) => any>;
9
+ }
10
+ namespace defaultProps {
11
+ let isLoading_1: boolean;
12
+ export { isLoading_1 as isLoading };
13
+ let summary_1: string;
14
+ export { summary_1 as summary };
15
+ }
16
+ }
17
+ import PropTypes from 'prop-types';
@@ -0,0 +1,339 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = void 0;
9
+
10
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
11
+
12
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
13
+
14
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
15
+
16
+ var _classnames = _interopRequireDefault(require("classnames"));
17
+
18
+ var _propTypes = _interopRequireDefault(require("prop-types"));
19
+
20
+ var _react = _interopRequireWildcard(require("react"));
21
+
22
+ var _reactRouterDom = require("react-router-dom");
23
+
24
+ var _twakeI18n = require("twake-i18n");
25
+
26
+ var _cozyClient = require("cozy-client");
27
+
28
+ var _ai = require("cozy-client/dist/models/ai");
29
+
30
+ var _file = require("cozy-client/dist/models/file");
31
+
32
+ var _cozyLogger = _interopRequireDefault(require("cozy-logger"));
33
+
34
+ var _Buttons = _interopRequireDefault(require("cozy-ui/transpiled/react/Buttons"));
35
+
36
+ var _Icon = _interopRequireDefault(require("cozy-ui/transpiled/react/Icon"));
37
+
38
+ var _IconButton = _interopRequireDefault(require("cozy-ui/transpiled/react/IconButton"));
39
+
40
+ var _Assistant = _interopRequireDefault(require("cozy-ui/transpiled/react/Icons/Assistant"));
41
+
42
+ var _Copy = _interopRequireDefault(require("cozy-ui/transpiled/react/Icons/Copy"));
43
+
44
+ var _CrossMedium = _interopRequireDefault(require("cozy-ui/transpiled/react/Icons/CrossMedium"));
45
+
46
+ var _Refresh = _interopRequireDefault(require("cozy-ui/transpiled/react/Icons/Refresh"));
47
+
48
+ var _Paper = _interopRequireDefault(require("cozy-ui/transpiled/react/Paper"));
49
+
50
+ var _Stack = _interopRequireDefault(require("cozy-ui/transpiled/react/Stack"));
51
+
52
+ var _Typography = _interopRequireDefault(require("cozy-ui/transpiled/react/Typography"));
53
+
54
+ var _Alert = require("cozy-ui/transpiled/react/providers/Alert");
55
+
56
+ var _prompts = require("./prompts");
57
+
58
+ var _helpers = require("../../helpers");
59
+
60
+ var _ViewerProvider = require("../../providers/ViewerProvider");
61
+
62
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
63
+
64
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
65
+
66
+ var styles = {
67
+ "loaderContainer": "styles__loaderContainer___RuLAO",
68
+ "loaderBar": "styles__loaderBar___2_kw1",
69
+ "aiLoaderSlide": "styles__aiLoaderSlide___9K8aD"
70
+ };
71
+
72
+ var AIAssistantPanel = function AIAssistantPanel() {
73
+ var _useI18n = (0, _twakeI18n.useI18n)(),
74
+ t = _useI18n.t;
75
+
76
+ var client = (0, _cozyClient.useClient)();
77
+
78
+ var _useViewer = (0, _ViewerProvider.useViewer)(),
79
+ file = _useViewer.file,
80
+ setIsOpenAiAssistant = _useViewer.setIsOpenAiAssistant;
81
+
82
+ var _useAlert = (0, _Alert.useAlert)(),
83
+ showAlert = _useAlert.showAlert;
84
+
85
+ var _useState = (0, _react.useState)(true),
86
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
87
+ isLoading = _useState2[0],
88
+ setIsLoading = _useState2[1];
89
+
90
+ var _useState3 = (0, _react.useState)(''),
91
+ _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
92
+ summary = _useState4[0],
93
+ setSummary = _useState4[1];
94
+
95
+ var _useState5 = (0, _react.useState)(null),
96
+ _useState6 = (0, _slicedToArray2.default)(_useState5, 2),
97
+ error = _useState6[0],
98
+ setError = _useState6[1];
99
+
100
+ var location = (0, _reactRouterDom.useLocation)();
101
+ var navigate = (0, _reactRouterDom.useNavigate)();
102
+
103
+ var handleClose = function handleClose() {
104
+ var _location$state;
105
+
106
+ setIsOpenAiAssistant(false);
107
+
108
+ if (location !== null && location !== void 0 && (_location$state = location.state) !== null && _location$state !== void 0 && _location$state.showAIAssistant) {
109
+ navigate('..');
110
+ }
111
+ };
112
+
113
+ var summarizeFile = /*#__PURE__*/function () {
114
+ var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(_ref) {
115
+ var client, file, _ref$stream, stream, model, fileBlob, textContent, summaryConfig, _error, messages, summaryResponse;
116
+
117
+ return _regenerator.default.wrap(function _callee$(_context) {
118
+ while (1) {
119
+ switch (_context.prev = _context.next) {
120
+ case 0:
121
+ client = _ref.client, file = _ref.file, _ref$stream = _ref.stream, stream = _ref$stream === void 0 ? false : _ref$stream, model = _ref.model;
122
+ _context.prev = 1;
123
+ _context.next = 4;
124
+ return (0, _file.fetchBlobFileById)(client, file === null || file === void 0 ? void 0 : file._id);
125
+
126
+ case 4:
127
+ fileBlob = _context.sent;
128
+ _context.next = 7;
129
+ return (0, _ai.extractText)(client, fileBlob, {
130
+ name: file.name,
131
+ mime: file.mime
132
+ });
133
+
134
+ case 7:
135
+ textContent = _context.sent;
136
+ summaryConfig = (0, _helpers.getSummaryConfig)();
137
+
138
+ if (!(summaryConfig !== null && summaryConfig !== void 0 && summaryConfig.maxTokens && (0, _helpers.roughTokensEstimation)(textContent) > summaryConfig.maxTokens)) {
139
+ _context.next = 13;
140
+ break;
141
+ }
142
+
143
+ _error = new Error('DOCUMENT_TOO_LARGE');
144
+ _error.code = 'DOCUMENT_TOO_LARGE';
145
+ throw _error;
146
+
147
+ case 13:
148
+ messages = [{
149
+ role: 'system',
150
+ content: _prompts.SUMMARY_SYSTEM_PROMPT
151
+ }, {
152
+ role: 'user',
153
+ content: (0, _prompts.getSummaryUserPrompt)(textContent)
154
+ }];
155
+ _context.next = 16;
156
+ return (0, _ai.chatCompletion)(client, messages, {
157
+ stream: stream,
158
+ model: model
159
+ });
160
+
161
+ case 16:
162
+ summaryResponse = _context.sent;
163
+ return _context.abrupt("return", summaryResponse);
164
+
165
+ case 20:
166
+ _context.prev = 20;
167
+ _context.t0 = _context["catch"](1);
168
+
169
+ _cozyLogger.default.error('Error when summarizing file:', _context.t0);
170
+
171
+ throw _context.t0;
172
+
173
+ case 24:
174
+ case "end":
175
+ return _context.stop();
176
+ }
177
+ }
178
+ }, _callee, null, [[1, 20]]);
179
+ }));
180
+
181
+ return function summarizeFile(_x) {
182
+ return _ref2.apply(this, arguments);
183
+ };
184
+ }();
185
+
186
+ var fetchSummary = (0, _react.useCallback)( /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2() {
187
+ var response, errorMessage;
188
+ return _regenerator.default.wrap(function _callee2$(_context2) {
189
+ while (1) {
190
+ switch (_context2.prev = _context2.next) {
191
+ case 0:
192
+ if (file) {
193
+ _context2.next = 2;
194
+ break;
195
+ }
196
+
197
+ return _context2.abrupt("return");
198
+
199
+ case 2:
200
+ setIsLoading(true);
201
+ setError(null);
202
+ _context2.prev = 4;
203
+ _context2.next = 7;
204
+ return summarizeFile({
205
+ client: client,
206
+ file: file,
207
+ stream: false
208
+ });
209
+
210
+ case 7:
211
+ response = _context2.sent;
212
+
213
+ if (response && response.content) {
214
+ setSummary(response.content);
215
+ } else if (response && response.choices && response.choices[0]) {
216
+ setSummary(response.choices[0].message.content);
217
+ }
218
+
219
+ _context2.next = 15;
220
+ break;
221
+
222
+ case 11:
223
+ _context2.prev = 11;
224
+ _context2.t0 = _context2["catch"](4);
225
+ errorMessage = _context2.t0.code === 'DOCUMENT_TOO_LARGE' ? t('Viewer.ai.error.documentTooLarge') : t('Viewer.ai.error.summary');
226
+ setError(errorMessage);
227
+
228
+ case 15:
229
+ _context2.prev = 15;
230
+ setIsLoading(false);
231
+ return _context2.finish(15);
232
+
233
+ case 18:
234
+ case "end":
235
+ return _context2.stop();
236
+ }
237
+ }
238
+ }, _callee2, null, [[4, 11, 15, 18]]);
239
+ })), [client, file, t]);
240
+
241
+ var handleRefresh = function handleRefresh() {
242
+ fetchSummary();
243
+ };
244
+
245
+ var handleCopy = function handleCopy() {
246
+ if (summary) {
247
+ navigator.clipboard.writeText(summary);
248
+ showAlert({
249
+ message: t('Viewer.ai.copied'),
250
+ severity: 'success'
251
+ });
252
+ }
253
+ };
254
+
255
+ (0, _react.useEffect)(function () {
256
+ fetchSummary();
257
+ }, [fetchSummary]);
258
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_Stack.default, {
259
+ spacing: "s",
260
+ className: (0, _classnames.default)('u-flex u-flex-column u-h-100')
261
+ }, /*#__PURE__*/_react.default.createElement(_Paper.default, {
262
+ className: (0, _classnames.default)({
263
+ 'u-flex-grow-1': !isLoading
264
+ }),
265
+ elevation: 2,
266
+ square: true
267
+ }, /*#__PURE__*/_react.default.createElement("div", {
268
+ className: "u-flex u-flex-items-center u-flex-justify-between u-h-3 u-ph-1 u-flex-shrink-0"
269
+ }, /*#__PURE__*/_react.default.createElement(_Typography.default, {
270
+ variant: "h4"
271
+ }, /*#__PURE__*/_react.default.createElement(_Icon.default, {
272
+ icon: _Assistant.default
273
+ }), " ", t('Viewer.ai.panelTitle')), /*#__PURE__*/_react.default.createElement(_IconButton.default, {
274
+ "aria-label": "Close AI Assistant",
275
+ onClick: handleClose
276
+ }, /*#__PURE__*/_react.default.createElement(_Icon.default, {
277
+ icon: _CrossMedium.default
278
+ }))), !isLoading && /*#__PURE__*/_react.default.createElement(_Stack.default, {
279
+ spacing: "s",
280
+ className: "u-ph-1"
281
+ }, /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("div", {
282
+ className: "u-flex u-flex-items-center u-flex-justify-between u-mb-1"
283
+ }, /*#__PURE__*/_react.default.createElement(_Typography.default, {
284
+ variant: "subtitle1"
285
+ }, t('Viewer.ai.bodyText')), /*#__PURE__*/_react.default.createElement("div", {
286
+ className: "u-flex"
287
+ }, /*#__PURE__*/_react.default.createElement(_IconButton.default, {
288
+ size: "small",
289
+ onClick: handleRefresh
290
+ }, /*#__PURE__*/_react.default.createElement(_Icon.default, {
291
+ icon: _Refresh.default
292
+ })), summary && /*#__PURE__*/_react.default.createElement(_IconButton.default, {
293
+ size: "small",
294
+ onClick: handleCopy
295
+ }, /*#__PURE__*/_react.default.createElement(_Icon.default, {
296
+ icon: _Copy.default
297
+ })))), /*#__PURE__*/_react.default.createElement(_Typography.default, {
298
+ className: "u-mb-1"
299
+ }, error ? /*#__PURE__*/_react.default.createElement("span", {
300
+ style: {
301
+ color: 'var(--errorColor)'
302
+ }
303
+ }, error) : summary), !isLoading && summary && /*#__PURE__*/_react.default.createElement(_Typography.default, {
304
+ variant: "caption",
305
+ color: "textSecondary"
306
+ }, t('Viewer.ai.footerText'))))), isLoading ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
307
+ className: styles.loaderContainer
308
+ }, /*#__PURE__*/_react.default.createElement("div", {
309
+ className: styles.loaderBar
310
+ })), /*#__PURE__*/_react.default.createElement("div", {
311
+ className: "u-flex u-flex-items-center u-flex-justify-between u-ph-1"
312
+ }, /*#__PURE__*/_react.default.createElement(_Typography.default, {
313
+ variant: "body1",
314
+ className: "u-flex u-flex-items-center"
315
+ }, /*#__PURE__*/_react.default.createElement(_Icon.default, {
316
+ icon: _Assistant.default,
317
+ color: "var(--primaryColor)",
318
+ className: "u-mr-1"
319
+ }), t('Viewer.ai.loadingText')), /*#__PURE__*/_react.default.createElement(_Buttons.default, {
320
+ size: "small",
321
+ variant: "text",
322
+ color: "default",
323
+ label: t('Viewer.ai.stop'),
324
+ onClick: handleClose
325
+ }))) : null));
326
+ };
327
+
328
+ AIAssistantPanel.propTypes = {
329
+ isLoading: _propTypes.default.bool,
330
+ summary: _propTypes.default.string,
331
+ onStop: _propTypes.default.func,
332
+ onSend: _propTypes.default.func
333
+ };
334
+ AIAssistantPanel.defaultProps = {
335
+ isLoading: false,
336
+ summary: ''
337
+ };
338
+ var _default = AIAssistantPanel;
339
+ exports.default = _default;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * AI prompts for document summarization
3
+ * These will be externalized in the future
4
+ */
5
+ export const SUMMARY_SYSTEM_PROMPT: "You are a concise and reliable text summarizer.\n\nYour goal:\n- Produce a clear and accurate summary of the provided content\n- Keep the original meaning and key information only\n- Remove redundancy, examples, anecdotes, and minor details\n\nWriting rules:\n- Keep the same language as the provided input. For example, if it's french, keep french\n- Be concise and use simple phrasing\n- Do not add new information\n- Do not guess what is not explicitly stated\n\nOutput:\n- A single coherent paragraph unless otherwise specified\n- Do not add any extra information or interpret anything beyond the explicit task";
6
+ export function getSummaryUserPrompt(textContent: string): string;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getSummaryUserPrompt = exports.SUMMARY_SYSTEM_PROMPT = void 0;
7
+
8
+ /**
9
+ * AI prompts for document summarization
10
+ * These will be externalized in the future
11
+ */
12
+ var SUMMARY_SYSTEM_PROMPT = "You are a concise and reliable text summarizer.\n\nYour goal:\n- Produce a clear and accurate summary of the provided content\n- Keep the original meaning and key information only\n- Remove redundancy, examples, anecdotes, and minor details\n\nWriting rules:\n- Keep the same language as the provided input. For example, if it's french, keep french\n- Be concise and use simple phrasing\n- Do not add new information\n- Do not guess what is not explicitly stated\n\nOutput:\n- A single coherent paragraph unless otherwise specified\n- Do not add any extra information or interpret anything beyond the explicit task";
13
+ /**
14
+ * Generate user prompt for document summarization
15
+ * @param {string} textContent - The text content to summarize
16
+ * @returns {string} The formatted user prompt
17
+ */
18
+
19
+ exports.SUMMARY_SYSTEM_PROMPT = SUMMARY_SYSTEM_PROMPT;
20
+
21
+ var getSummaryUserPrompt = function getSummaryUserPrompt(textContent) {
22
+ return "Summarize the following content:\n\n".concat(textContent);
23
+ };
24
+
25
+ exports.getSummaryUserPrompt = getSummaryUserPrompt;
@@ -1,24 +1,2 @@
1
- export default ViewerContainerWrapper;
2
- declare function ViewerContainerWrapper({ disableModal, ...props }: {
3
- [x: string]: any;
4
- disableModal: any;
5
- }): JSX.Element;
6
- declare namespace ViewerContainerWrapper {
7
- namespace defaultProps {
8
- namespace componentsProps {
9
- namespace modalProps {
10
- let open: boolean;
11
- let fullScreen: boolean;
12
- let fullWidth: boolean;
13
- }
14
- }
15
- }
16
- namespace propTypes {
17
- export let disableModal: PropTypes.Requireable<boolean>;
18
- let componentsProps_1: PropTypes.Requireable<PropTypes.InferProps<{
19
- modalProps: PropTypes.Requireable<object>;
20
- }>>;
21
- export { componentsProps_1 as componentsProps };
22
- }
23
- }
24
- import PropTypes from 'prop-types';
1
+ declare const _default: any;
2
+ export default _default;
@@ -47,6 +47,8 @@ var _Viewer = _interopRequireDefault(require("./Viewer"));
47
47
 
48
48
  var _ViewerInformationsWrapper = _interopRequireDefault(require("./ViewerInformationsWrapper"));
49
49
 
50
+ var _withViewerLocales = require("./hoc/withViewerLocales");
51
+
50
52
  var _locales = require("./locales");
51
53
 
52
54
  var _proptypes2 = require("./proptypes");
@@ -303,5 +305,7 @@ ViewerContainerWrapper.propTypes = {
303
305
  modalProps: _propTypes.default.object
304
306
  })
305
307
  };
306
- var _default = ViewerContainerWrapper;
308
+
309
+ var _default = (0, _withViewerLocales.withViewerLocales)(ViewerContainerWrapper);
310
+
307
311
  exports.default = _default;
@@ -9,7 +9,9 @@ exports.default = void 0;
9
9
 
10
10
  var _propTypes = _interopRequireDefault(require("prop-types"));
11
11
 
12
- var _react = _interopRequireDefault(require("react"));
12
+ var _react = _interopRequireWildcard(require("react"));
13
+
14
+ var _reactRouterDom = require("react-router-dom");
13
15
 
14
16
  var _useSetFlagshipUI = require("cozy-ui/transpiled/react/hooks/useSetFlagshipUi/useSetFlagshipUI");
15
17
 
@@ -19,12 +21,20 @@ var _styles = require("cozy-ui/transpiled/react/styles");
19
21
 
20
22
  var _FooterContent = _interopRequireDefault(require("./Footer/FooterContent"));
21
23
 
24
+ var _AIAssistantPanel = _interopRequireDefault(require("./Panel/AI/AIAssistantPanel"));
25
+
22
26
  var _PanelContent = _interopRequireDefault(require("./Panel/PanelContent"));
23
27
 
24
28
  var _Footer = _interopRequireDefault(require("./components/Footer"));
25
29
 
26
30
  var _InformationPanel = _interopRequireDefault(require("./components/InformationPanel"));
27
31
 
32
+ var _ViewerProvider = require("./providers/ViewerProvider");
33
+
34
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
35
+
36
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
37
+
28
38
  var ViewerInformationsWrapper = function ViewerInformationsWrapper(_ref) {
29
39
  var disableFooter = _ref.disableFooter,
30
40
  validForPanel = _ref.validForPanel,
@@ -35,16 +45,31 @@ var ViewerInformationsWrapper = function ViewerInformationsWrapper(_ref) {
35
45
  var _useCozyTheme = (0, _CozyTheme.useCozyTheme)(),
36
46
  isLight = _useCozyTheme.isLight;
37
47
 
48
+ var _useViewer = (0, _ViewerProvider.useViewer)(),
49
+ isOpenAiAssistant = _useViewer.isOpenAiAssistant,
50
+ setIsOpenAiAssistant = _useViewer.setIsOpenAiAssistant;
51
+
38
52
  var sidebar = document.querySelector('[class*="sidebar"]');
53
+ var location = (0, _reactRouterDom.useLocation)();
54
+ (0, _react.useEffect)(function () {
55
+ var _location$state;
56
+
57
+ if (location !== null && location !== void 0 && (_location$state = location.state) !== null && _location$state !== void 0 && _location$state.showAIAssistant) {
58
+ setIsOpenAiAssistant(true);
59
+ }
60
+ }, [location, setIsOpenAiAssistant]);
39
61
  (0, _useSetFlagshipUI.useSetFlagshipUI)({
40
62
  bottomBackground: theme.palette.background.paper,
41
63
  bottomTheme: isLight ? 'dark' : 'light'
42
64
  }, {
43
65
  bottomBackground: theme.palette.background[sidebar ? 'default' : 'paper']
44
66
  });
45
- return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, !disableFooter && /*#__PURE__*/_react.default.createElement(_Footer.default, null, /*#__PURE__*/_react.default.createElement(_FooterContent.default, {
67
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, isOpenAiAssistant ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, !disableFooter && /*#__PURE__*/_react.default.createElement(_Footer.default, null, /*#__PURE__*/_react.default.createElement(_FooterContent.default, {
68
+ toolbarRef: toolbarRef,
69
+ isDisplayChildrenDirectly: true
70
+ }, /*#__PURE__*/_react.default.createElement(_AIAssistantPanel.default, null))), validForPanel && /*#__PURE__*/_react.default.createElement(_InformationPanel.default, null, /*#__PURE__*/_react.default.createElement(_AIAssistantPanel.default, null))) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, !disableFooter && /*#__PURE__*/_react.default.createElement(_Footer.default, null, /*#__PURE__*/_react.default.createElement(_FooterContent.default, {
46
71
  toolbarRef: toolbarRef
47
- }, children)), validForPanel && /*#__PURE__*/_react.default.createElement(_InformationPanel.default, null, /*#__PURE__*/_react.default.createElement(_PanelContent.default, null)));
72
+ }, children)), validForPanel && /*#__PURE__*/_react.default.createElement(_InformationPanel.default, null, /*#__PURE__*/_react.default.createElement(_PanelContent.default, null))));
48
73
  };
49
74
 
50
75
  ViewerInformationsWrapper.propTypes = {
@@ -3,6 +3,7 @@ export const MAX_SCALE: 3;
3
3
  export const MAX_PAGES: 40;
4
4
  export const MAX_SIZE_FILE: 10485760;
5
5
  export class PdfJsViewer extends React.Component<any, any, any> {
6
+ static contextType: React.Context<any>;
6
7
  constructor();
7
8
  state: {
8
9
  totalPages: number;
@@ -45,6 +45,8 @@ var _withFileUrl = _interopRequireDefault(require("../hoc/withFileUrl"));
45
45
 
46
46
  var _withViewerLocales = require("../hoc/withViewerLocales");
47
47
 
48
+ var _ViewerProvider = require("../providers/ViewerProvider");
49
+
48
50
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
49
51
 
50
52
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
@@ -151,7 +153,12 @@ var PdfJsViewer = /*#__PURE__*/function (_Component) {
151
153
  totalPages: numPages,
152
154
  renderAllPages: numPages <= MAX_PAGES && parseInt(_this.props.file.size, 10) <= MAX_SIZE_FILE,
153
155
  loaded: true
154
- });
156
+ }); // Update page count in ViewerContext for AI summary compatibility check
157
+
158
+
159
+ if (_this.context && _this.context.setPdfPageCount) {
160
+ _this.context.setPdfPageCount(numPages);
161
+ }
155
162
  });
156
163
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onLoadError", function (error) {
157
164
  // eslint-disable-next-line no-console
@@ -378,6 +385,7 @@ var PdfJsViewer = /*#__PURE__*/function (_Component) {
378
385
  }(_react.Component);
379
386
 
380
387
  exports.PdfJsViewer = PdfJsViewer;
388
+ (0, _defineProperty2.default)(PdfJsViewer, "contextType", _ViewerProvider.ViewerContext);
381
389
  PdfJsViewer.propTypes = {
382
390
  url: _propTypes.default.string.isRequired,
383
391
  gestures: _propTypes.default.object,
@@ -21,7 +21,8 @@ var styles = {
21
21
  "--expanded": "styles__--expanded___1sp4Q",
22
22
  "viewer-toolbar": "styles__viewer-toolbar___1GLOA",
23
23
  "viewer-toolbar--hidden": "styles__viewer-toolbar--hidden___Zq97m",
24
- "viewer-footer": "styles__viewer-footer___iGv8J"
24
+ "viewer-footer": "styles__viewer-footer___iGv8J",
25
+ "viewer-ai-summarise-btn": "styles__viewer-ai-summarise-btn___2YOrl"
25
26
  };
26
27
 
27
28
  var Footer = function Footer(_ref) {
@@ -29,7 +29,8 @@ var styles = {
29
29
  "--expanded": "styles__--expanded___1sp4Q",
30
30
  "viewer-toolbar": "styles__viewer-toolbar___1GLOA",
31
31
  "viewer-toolbar--hidden": "styles__viewer-toolbar--hidden___Zq97m",
32
- "viewer-footer": "styles__viewer-footer___iGv8J"
32
+ "viewer-footer": "styles__viewer-footer___iGv8J",
33
+ "viewer-ai-summarise-btn": "styles__viewer-ai-summarise-btn___2YOrl"
33
34
  };
34
35
 
35
36
  var Navigation = function Navigation(_ref) {