@atlaskit/smart-card 26.48.2 → 26.48.3

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
@@ -1,5 +1,11 @@
1
1
  # @atlaskit/smart-card
2
2
 
3
+ ## 26.48.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#76801](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/76801) [`22c2b23f0f4a`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/22c2b23f0f4a) - Allow multiple subscribers to the same AI Summary Service.
8
+
3
9
  ## 26.48.2
4
10
 
5
11
  ### Patch Changes
@@ -11,6 +11,9 @@ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/cl
11
11
  var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
12
12
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
13
13
  var _utils = require("./utils");
14
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
15
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
16
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
14
17
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
15
18
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
16
19
  function _asyncIterator(r) { var n, t, o, e = 2; for ("undefined" != typeof Symbol && (t = Symbol.asyncIterator, o = Symbol.iterator); e--;) { if (t && null != (n = r[t])) return n.call(r); if (o && null != (n = r[o])) return new AsyncFromSyncIterator(n.call(r)); t = "@@asyncIterator", o = "@@iterator"; } throw new TypeError("Object is not async iterable"); }
@@ -23,7 +26,7 @@ var AISummaryService = exports.AISummaryService = /*#__PURE__*/function () {
23
26
  content: '',
24
27
  status: 'ready'
25
28
  });
26
- (0, _defineProperty2.default)(this, "subscribedStateSetter", function (state) {});
29
+ (0, _defineProperty2.default)(this, "subscribedStateSetters", new Set());
27
30
  (0, _defineProperty2.default)(this, "fetchStream", /*#__PURE__*/function () {
28
31
  var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(summaryStyle) {
29
32
  var payload, options, path, requestUrl, response;
@@ -79,6 +82,9 @@ var AISummaryService = exports.AISummaryService = /*#__PURE__*/function () {
79
82
  value: function () {
80
83
  var _summariseUrl = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2() {
81
84
  var summaryStyle,
85
+ _iterator2,
86
+ _step2,
87
+ _subscriber,
82
88
  stream,
83
89
  bufferContent,
84
90
  _iteratorAbruptCompletion,
@@ -87,6 +93,12 @@ var AISummaryService = exports.AISummaryService = /*#__PURE__*/function () {
87
93
  _iterator,
88
94
  _step,
89
95
  chunk,
96
+ _iterator3,
97
+ _step3,
98
+ subscriber,
99
+ _iterator4,
100
+ _step4,
101
+ _subscriber2,
90
102
  _args2 = arguments;
91
103
  return _regenerator.default.wrap(function _callee2$(_context2) {
92
104
  while (1) switch (_context2.prev = _context2.next) {
@@ -95,74 +107,104 @@ var AISummaryService = exports.AISummaryService = /*#__PURE__*/function () {
95
107
  this.state = _objectSpread(_objectSpread({}, this.state), {}, {
96
108
  status: 'loading'
97
109
  });
98
- this.subscribedStateSetter(this.state);
99
- _context2.next = 5;
110
+ _iterator2 = _createForOfIteratorHelper(this.subscribedStateSetters);
111
+ try {
112
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
113
+ _subscriber = _step2.value;
114
+ _subscriber(this.state);
115
+ }
116
+ } catch (err) {
117
+ _iterator2.e(err);
118
+ } finally {
119
+ _iterator2.f();
120
+ }
121
+ _context2.next = 6;
100
122
  return this.fetchStream(summaryStyle);
101
- case 5:
123
+ case 6:
102
124
  stream = _context2.sent;
103
125
  bufferContent = '';
104
126
  _iteratorAbruptCompletion = false;
105
127
  _didIteratorError = false;
106
- _context2.prev = 9;
128
+ _context2.prev = 10;
107
129
  _iterator = _asyncIterator(stream);
108
- case 11:
109
- _context2.next = 13;
130
+ case 12:
131
+ _context2.next = 14;
110
132
  return _iterator.next();
111
- case 13:
133
+ case 14:
112
134
  if (!(_iteratorAbruptCompletion = !(_step = _context2.sent).done)) {
113
- _context2.next = 19;
135
+ _context2.next = 20;
114
136
  break;
115
137
  }
116
138
  chunk = _step.value;
117
139
  if (chunk.type === 'ANSWER_PART') {
118
140
  bufferContent += chunk.message.content;
119
- this.subscribedStateSetter(_objectSpread(_objectSpread({}, this.state), {}, {
120
- content: bufferContent
121
- }));
141
+ _iterator3 = _createForOfIteratorHelper(this.subscribedStateSetters);
142
+ try {
143
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
144
+ subscriber = _step3.value;
145
+ subscriber(_objectSpread(_objectSpread({}, this.state), {}, {
146
+ content: bufferContent
147
+ }));
148
+ }
149
+ } catch (err) {
150
+ _iterator3.e(err);
151
+ } finally {
152
+ _iterator3.f();
153
+ }
122
154
  }
123
- case 16:
155
+ case 17:
124
156
  _iteratorAbruptCompletion = false;
125
- _context2.next = 11;
157
+ _context2.next = 12;
126
158
  break;
127
- case 19:
128
- _context2.next = 25;
159
+ case 20:
160
+ _context2.next = 26;
129
161
  break;
130
- case 21:
131
- _context2.prev = 21;
132
- _context2.t0 = _context2["catch"](9);
162
+ case 22:
163
+ _context2.prev = 22;
164
+ _context2.t0 = _context2["catch"](10);
133
165
  _didIteratorError = true;
134
166
  _iteratorError = _context2.t0;
135
- case 25:
136
- _context2.prev = 25;
167
+ case 26:
137
168
  _context2.prev = 26;
169
+ _context2.prev = 27;
138
170
  if (!(_iteratorAbruptCompletion && _iterator.return != null)) {
139
- _context2.next = 30;
171
+ _context2.next = 31;
140
172
  break;
141
173
  }
142
- _context2.next = 30;
174
+ _context2.next = 31;
143
175
  return _iterator.return();
144
- case 30:
145
- _context2.prev = 30;
176
+ case 31:
177
+ _context2.prev = 31;
146
178
  if (!_didIteratorError) {
147
- _context2.next = 33;
179
+ _context2.next = 34;
148
180
  break;
149
181
  }
150
182
  throw _iteratorError;
151
- case 33:
152
- return _context2.finish(30);
153
183
  case 34:
154
- return _context2.finish(25);
184
+ return _context2.finish(31);
155
185
  case 35:
186
+ return _context2.finish(26);
187
+ case 36:
156
188
  this.state = {
157
189
  status: 'done',
158
190
  content: bufferContent
159
191
  };
160
- this.subscribedStateSetter(this.state);
161
- case 37:
192
+ _iterator4 = _createForOfIteratorHelper(this.subscribedStateSetters);
193
+ try {
194
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
195
+ _subscriber2 = _step4.value;
196
+ _subscriber2(this.state);
197
+ }
198
+ } catch (err) {
199
+ _iterator4.e(err);
200
+ } finally {
201
+ _iterator4.f();
202
+ }
203
+ case 39:
162
204
  case "end":
163
205
  return _context2.stop();
164
206
  }
165
- }, _callee2, this, [[9, 21, 25, 35], [26,, 30, 34]]);
207
+ }, _callee2, this, [[10, 22, 26, 36], [27,, 31, 35]]);
166
208
  }));
167
209
  function summariseUrl() {
168
210
  return _summariseUrl.apply(this, arguments);
@@ -172,7 +214,11 @@ var AISummaryService = exports.AISummaryService = /*#__PURE__*/function () {
172
214
  }, {
173
215
  key: "subscribe",
174
216
  value: function subscribe(stateSetter) {
175
- this.subscribedStateSetter = stateSetter;
217
+ var _this2 = this;
218
+ this.subscribedStateSetters.add(stateSetter);
219
+ return function () {
220
+ _this2.subscribedStateSetters.delete(stateSetter);
221
+ };
176
222
  }
177
223
  }]);
178
224
  return AISummaryService;
@@ -10,34 +10,59 @@ var _react = require("react");
10
10
  var _store = require("./ai-summary-service/store");
11
11
  var _aiSummaryService = require("./ai-summary-service");
12
12
  var useAISummary = exports.useAISummary = function useAISummary(props) {
13
- var url = props.url;
14
- var aISummaryService = _store.AISummariesStore.get(url);
15
- var isAISummaryServiceInitiated = !!aISummaryService;
16
- var _useState = (0, _react.useState)(isAISummaryServiceInitiated ? aISummaryService.state : {
13
+ var _AISummariesStore$get;
14
+ var url = props.url,
15
+ baseUrl = props.baseUrl,
16
+ product = props.product,
17
+ headers = props.headers;
18
+ var _useState = (0, _react.useState)(((_AISummariesStore$get = _store.AISummariesStore.get(url)) === null || _AISummariesStore$get === void 0 ? void 0 : _AISummariesStore$get.state) || {
17
19
  status: 'ready',
18
20
  content: ''
19
21
  }),
20
22
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
21
23
  state = _useState2[0],
22
24
  setState = _useState2[1];
23
- var isSummarised = isAISummaryServiceInitiated && state.status === 'done';
25
+
26
+ // Can be used to know the summary status upon mounting a component (HoverCard UI state for example).
27
+ // For other scenarios, opt for dynamic status updates via state.status.
28
+ var isSummarisedOnMount = (0, _react.useMemo)(function () {
29
+ var _AISummariesStore$get2;
30
+ return ((_AISummariesStore$get2 = _store.AISummariesStore.get(url)) === null || _AISummariesStore$get2 === void 0 ? void 0 : _AISummariesStore$get2.state.status) === 'done';
31
+ }, [url]);
24
32
  (0, _react.useEffect)(function () {
25
- if (!isSummarised) {
26
- var _AISummariesStore$get;
27
- if (!isAISummaryServiceInitiated) {
28
- _store.AISummariesStore.set(url, new _aiSummaryService.AISummaryService(props));
33
+ // Create or subscribe to an AI service only if a summary has not been previously generated.
34
+ // Otherwise, use the data from the current state synchronized with a cache (AISummariesStore).
35
+ if (!isSummarisedOnMount) {
36
+ var aISummaryService = _store.AISummariesStore.get(url);
37
+ var isAISummaryServiceInitiated = !!aISummaryService;
38
+ if (isAISummaryServiceInitiated) {
39
+ //if we want to subscribe to updates from an existing AI service that has not yet provided a summary or is currently in progress.
40
+ var unsubscribe = aISummaryService.subscribe(setState);
41
+ return function () {
42
+ return unsubscribe();
43
+ };
44
+ } else {
45
+ var _AISummariesStore$get3;
46
+ //if we want to create a new AI service and wish to subscribe for updates
47
+ _store.AISummariesStore.set(url, new _aiSummaryService.AISummaryService({
48
+ url: url,
49
+ baseUrl: baseUrl,
50
+ product: product,
51
+ headers: headers
52
+ }));
53
+ var _unsubscribe = (_AISummariesStore$get3 = _store.AISummariesStore.get(url)) === null || _AISummariesStore$get3 === void 0 ? void 0 : _AISummariesStore$get3.subscribe(setState);
54
+ return function () {
55
+ return _unsubscribe && _unsubscribe();
56
+ };
29
57
  }
30
- return (_AISummariesStore$get = _store.AISummariesStore.get(url)) === null || _AISummariesStore$get === void 0 ? void 0 : _AISummariesStore$get.subscribe(setState);
31
58
  }
32
- }, [isSummarised, isAISummaryServiceInitiated, url, props]);
59
+ }, [isSummarisedOnMount, url, baseUrl, product, headers]);
33
60
  var summariseUrl = function summariseUrl() {
34
- if (isAISummaryServiceInitiated) {
35
- return aISummaryService.summariseUrl();
36
- }
37
- return;
61
+ var _AISummariesStore$get4;
62
+ return (_AISummariesStore$get4 = _store.AISummariesStore.get(url)) === null || _AISummariesStore$get4 === void 0 ? void 0 : _AISummariesStore$get4.summariseUrl();
38
63
  };
39
64
  return {
40
- isSummarised: isSummarised,
65
+ isSummarisedOnMount: isSummarisedOnMount,
41
66
  summariseUrl: summariseUrl,
42
67
  state: state
43
68
  };
@@ -22,7 +22,7 @@ var ANALYTICS_CHANNEL = exports.ANALYTICS_CHANNEL = 'media';
22
22
  var context = exports.context = {
23
23
  componentName: 'smart-cards',
24
24
  packageName: "@atlaskit/smart-card",
25
- packageVersion: "26.48.2"
25
+ packageVersion: "26.48.3"
26
26
  };
27
27
  var TrackQuickActionType = exports.TrackQuickActionType = /*#__PURE__*/function (TrackQuickActionType) {
28
28
  TrackQuickActionType["StatusUpdate"] = "StatusUpdate";
@@ -210,5 +210,5 @@ var getIsAISummaryEnabled = exports.getIsAISummaryEnabled = function getIsAISumm
210
210
  var _response$meta;
211
211
  var isAdminHubAIEnabled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
212
212
  var response = arguments.length > 1 ? arguments[1] : undefined;
213
- return Boolean((0, _platformFeatureFlags.getBooleanFF)('platform.linking-platform.smart-card.hover-card-ai-summaries') && isAdminHubAIEnabled && (response === null || response === void 0 || (_response$meta = response.meta) === null || _response$meta === void 0 || (_response$meta = _response$meta.supportedFeatures) === null || _response$meta === void 0 ? void 0 : _response$meta.includes('AISummary')));
213
+ return Boolean((0, _platformFeatureFlags.getBooleanFF)('platform.linking-platform.smart-card.hover-card-ai-summaries') && isAdminHubAIEnabled && (response === null || response === void 0 || (_response$meta = response.meta) === null || _response$meta === void 0 || (_response$meta = _response$meta.supportedFeature) === null || _response$meta === void 0 ? void 0 : _response$meta.includes('AISummary')));
214
214
  };
@@ -17,7 +17,7 @@ var _excluded = ["href", "children", "checkSafety", "onClick", "testId"],
17
17
  _excluded2 = ["isLinkSafe", "showSafetyWarningModal"];
18
18
  var PACKAGE_DATA = {
19
19
  packageName: "@atlaskit/smart-card",
20
- packageVersion: "26.48.2",
20
+ packageVersion: "26.48.3",
21
21
  componentName: 'linkUrl'
22
22
  };
23
23
  var Link = (0, _click.withLinkClickedEvent)('a');
@@ -6,7 +6,7 @@ export class AISummaryService {
6
6
  content: '',
7
7
  status: 'ready'
8
8
  });
9
- _defineProperty(this, "subscribedStateSetter", state => {});
9
+ _defineProperty(this, "subscribedStateSetters", new Set());
10
10
  _defineProperty(this, "fetchStream", async summaryStyle => {
11
11
  const payload = {
12
12
  recipient_agent_named_id: 'summary_agent',
@@ -47,25 +47,34 @@ export class AISummaryService {
47
47
  ...this.state,
48
48
  status: 'loading'
49
49
  };
50
- this.subscribedStateSetter(this.state);
50
+ for (const subscriber of this.subscribedStateSetters) {
51
+ subscriber(this.state);
52
+ }
51
53
  const stream = await this.fetchStream(summaryStyle);
52
54
  let bufferContent = '';
53
55
  for await (const chunk of stream) {
54
56
  if (chunk.type === 'ANSWER_PART') {
55
57
  bufferContent += chunk.message.content;
56
- this.subscribedStateSetter({
57
- ...this.state,
58
- content: bufferContent
59
- });
58
+ for (const subscriber of this.subscribedStateSetters) {
59
+ subscriber({
60
+ ...this.state,
61
+ content: bufferContent
62
+ });
63
+ }
60
64
  }
61
65
  }
62
66
  this.state = {
63
67
  status: 'done',
64
68
  content: bufferContent
65
69
  };
66
- this.subscribedStateSetter(this.state);
70
+ for (const subscriber of this.subscribedStateSetters) {
71
+ subscriber(this.state);
72
+ }
67
73
  }
68
74
  subscribe(stateSetter) {
69
- this.subscribedStateSetter = stateSetter;
75
+ this.subscribedStateSetters.add(stateSetter);
76
+ return () => {
77
+ this.subscribedStateSetters.delete(stateSetter);
78
+ };
70
79
  }
71
80
  }
@@ -1,34 +1,55 @@
1
- import { useState, useEffect } from 'react';
1
+ import { useState, useEffect, useMemo } from 'react';
2
2
  import { AISummariesStore } from './ai-summary-service/store';
3
3
  import { AISummaryService } from './ai-summary-service';
4
4
  export const useAISummary = props => {
5
+ var _AISummariesStore$get;
5
6
  const {
6
- url
7
+ url,
8
+ baseUrl,
9
+ product,
10
+ headers
7
11
  } = props;
8
- const aISummaryService = AISummariesStore.get(url);
9
- const isAISummaryServiceInitiated = !!aISummaryService;
10
- const [state, setState] = useState(isAISummaryServiceInitiated ? aISummaryService.state : {
12
+ const [state, setState] = useState(((_AISummariesStore$get = AISummariesStore.get(url)) === null || _AISummariesStore$get === void 0 ? void 0 : _AISummariesStore$get.state) || {
11
13
  status: 'ready',
12
14
  content: ''
13
15
  });
14
- const isSummarised = isAISummaryServiceInitiated && state.status === 'done';
16
+
17
+ // Can be used to know the summary status upon mounting a component (HoverCard UI state for example).
18
+ // For other scenarios, opt for dynamic status updates via state.status.
19
+ const isSummarisedOnMount = useMemo(() => {
20
+ var _AISummariesStore$get2;
21
+ return ((_AISummariesStore$get2 = AISummariesStore.get(url)) === null || _AISummariesStore$get2 === void 0 ? void 0 : _AISummariesStore$get2.state.status) === 'done';
22
+ }, [url]);
15
23
  useEffect(() => {
16
- if (!isSummarised) {
17
- var _AISummariesStore$get;
18
- if (!isAISummaryServiceInitiated) {
19
- AISummariesStore.set(url, new AISummaryService(props));
24
+ // Create or subscribe to an AI service only if a summary has not been previously generated.
25
+ // Otherwise, use the data from the current state synchronized with a cache (AISummariesStore).
26
+ if (!isSummarisedOnMount) {
27
+ const aISummaryService = AISummariesStore.get(url);
28
+ const isAISummaryServiceInitiated = !!aISummaryService;
29
+ if (isAISummaryServiceInitiated) {
30
+ //if we want to subscribe to updates from an existing AI service that has not yet provided a summary or is currently in progress.
31
+ const unsubscribe = aISummaryService.subscribe(setState);
32
+ return () => unsubscribe();
33
+ } else {
34
+ var _AISummariesStore$get3;
35
+ //if we want to create a new AI service and wish to subscribe for updates
36
+ AISummariesStore.set(url, new AISummaryService({
37
+ url,
38
+ baseUrl,
39
+ product,
40
+ headers
41
+ }));
42
+ const unsubscribe = (_AISummariesStore$get3 = AISummariesStore.get(url)) === null || _AISummariesStore$get3 === void 0 ? void 0 : _AISummariesStore$get3.subscribe(setState);
43
+ return () => unsubscribe && unsubscribe();
20
44
  }
21
- return (_AISummariesStore$get = AISummariesStore.get(url)) === null || _AISummariesStore$get === void 0 ? void 0 : _AISummariesStore$get.subscribe(setState);
22
45
  }
23
- }, [isSummarised, isAISummaryServiceInitiated, url, props]);
46
+ }, [isSummarisedOnMount, url, baseUrl, product, headers]);
24
47
  const summariseUrl = () => {
25
- if (isAISummaryServiceInitiated) {
26
- return aISummaryService.summariseUrl();
27
- }
28
- return;
48
+ var _AISummariesStore$get4;
49
+ return (_AISummariesStore$get4 = AISummariesStore.get(url)) === null || _AISummariesStore$get4 === void 0 ? void 0 : _AISummariesStore$get4.summariseUrl();
29
50
  };
30
51
  return {
31
- isSummarised,
52
+ isSummarisedOnMount,
32
53
  summariseUrl,
33
54
  state
34
55
  };
@@ -4,7 +4,7 @@ export const ANALYTICS_CHANNEL = 'media';
4
4
  export const context = {
5
5
  componentName: 'smart-cards',
6
6
  packageName: "@atlaskit/smart-card",
7
- packageVersion: "26.48.2"
7
+ packageVersion: "26.48.3"
8
8
  };
9
9
  export let TrackQuickActionType = /*#__PURE__*/function (TrackQuickActionType) {
10
10
  TrackQuickActionType["StatusUpdate"] = "StatusUpdate";
@@ -204,5 +204,5 @@ export const getSimulatedBetterMetadata = (extensionKey = '', data) => {
204
204
  };
205
205
  export const getIsAISummaryEnabled = (isAdminHubAIEnabled = false, response) => {
206
206
  var _response$meta, _response$meta$suppor;
207
- return Boolean(getBooleanFF('platform.linking-platform.smart-card.hover-card-ai-summaries') && isAdminHubAIEnabled && (response === null || response === void 0 ? void 0 : (_response$meta = response.meta) === null || _response$meta === void 0 ? void 0 : (_response$meta$suppor = _response$meta.supportedFeatures) === null || _response$meta$suppor === void 0 ? void 0 : _response$meta$suppor.includes('AISummary')));
207
+ return Boolean(getBooleanFF('platform.linking-platform.smart-card.hover-card-ai-summaries') && isAdminHubAIEnabled && (response === null || response === void 0 ? void 0 : (_response$meta = response.meta) === null || _response$meta === void 0 ? void 0 : (_response$meta$suppor = _response$meta.supportedFeature) === null || _response$meta$suppor === void 0 ? void 0 : _response$meta$suppor.includes('AISummary')));
208
208
  };
@@ -7,7 +7,7 @@ import { useLinkWarningModal } from './LinkWarningModal/hooks/use-link-warning-m
7
7
  import LinkWarningModal from './LinkWarningModal';
8
8
  const PACKAGE_DATA = {
9
9
  packageName: "@atlaskit/smart-card",
10
- packageVersion: "26.48.2",
10
+ packageVersion: "26.48.3",
11
11
  componentName: 'linkUrl'
12
12
  };
13
13
  const Link = withLinkClickedEvent('a');
@@ -2,6 +2,9 @@ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
2
  import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
3
3
  import _createClass from "@babel/runtime/helpers/createClass";
4
4
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
5
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
6
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
7
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
5
8
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
6
9
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
7
10
  import _regeneratorRuntime from "@babel/runtime/regenerator";
@@ -16,7 +19,7 @@ export var AISummaryService = /*#__PURE__*/function () {
16
19
  content: '',
17
20
  status: 'ready'
18
21
  });
19
- _defineProperty(this, "subscribedStateSetter", function (state) {});
22
+ _defineProperty(this, "subscribedStateSetters", new Set());
20
23
  _defineProperty(this, "fetchStream", /*#__PURE__*/function () {
21
24
  var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(summaryStyle) {
22
25
  var payload, options, path, requestUrl, response;
@@ -72,6 +75,9 @@ export var AISummaryService = /*#__PURE__*/function () {
72
75
  value: function () {
73
76
  var _summariseUrl = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
74
77
  var summaryStyle,
78
+ _iterator2,
79
+ _step2,
80
+ _subscriber,
75
81
  stream,
76
82
  bufferContent,
77
83
  _iteratorAbruptCompletion,
@@ -80,6 +86,12 @@ export var AISummaryService = /*#__PURE__*/function () {
80
86
  _iterator,
81
87
  _step,
82
88
  chunk,
89
+ _iterator3,
90
+ _step3,
91
+ subscriber,
92
+ _iterator4,
93
+ _step4,
94
+ _subscriber2,
83
95
  _args2 = arguments;
84
96
  return _regeneratorRuntime.wrap(function _callee2$(_context2) {
85
97
  while (1) switch (_context2.prev = _context2.next) {
@@ -88,74 +100,104 @@ export var AISummaryService = /*#__PURE__*/function () {
88
100
  this.state = _objectSpread(_objectSpread({}, this.state), {}, {
89
101
  status: 'loading'
90
102
  });
91
- this.subscribedStateSetter(this.state);
92
- _context2.next = 5;
103
+ _iterator2 = _createForOfIteratorHelper(this.subscribedStateSetters);
104
+ try {
105
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
106
+ _subscriber = _step2.value;
107
+ _subscriber(this.state);
108
+ }
109
+ } catch (err) {
110
+ _iterator2.e(err);
111
+ } finally {
112
+ _iterator2.f();
113
+ }
114
+ _context2.next = 6;
93
115
  return this.fetchStream(summaryStyle);
94
- case 5:
116
+ case 6:
95
117
  stream = _context2.sent;
96
118
  bufferContent = '';
97
119
  _iteratorAbruptCompletion = false;
98
120
  _didIteratorError = false;
99
- _context2.prev = 9;
121
+ _context2.prev = 10;
100
122
  _iterator = _asyncIterator(stream);
101
- case 11:
102
- _context2.next = 13;
123
+ case 12:
124
+ _context2.next = 14;
103
125
  return _iterator.next();
104
- case 13:
126
+ case 14:
105
127
  if (!(_iteratorAbruptCompletion = !(_step = _context2.sent).done)) {
106
- _context2.next = 19;
128
+ _context2.next = 20;
107
129
  break;
108
130
  }
109
131
  chunk = _step.value;
110
132
  if (chunk.type === 'ANSWER_PART') {
111
133
  bufferContent += chunk.message.content;
112
- this.subscribedStateSetter(_objectSpread(_objectSpread({}, this.state), {}, {
113
- content: bufferContent
114
- }));
134
+ _iterator3 = _createForOfIteratorHelper(this.subscribedStateSetters);
135
+ try {
136
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
137
+ subscriber = _step3.value;
138
+ subscriber(_objectSpread(_objectSpread({}, this.state), {}, {
139
+ content: bufferContent
140
+ }));
141
+ }
142
+ } catch (err) {
143
+ _iterator3.e(err);
144
+ } finally {
145
+ _iterator3.f();
146
+ }
115
147
  }
116
- case 16:
148
+ case 17:
117
149
  _iteratorAbruptCompletion = false;
118
- _context2.next = 11;
150
+ _context2.next = 12;
119
151
  break;
120
- case 19:
121
- _context2.next = 25;
152
+ case 20:
153
+ _context2.next = 26;
122
154
  break;
123
- case 21:
124
- _context2.prev = 21;
125
- _context2.t0 = _context2["catch"](9);
155
+ case 22:
156
+ _context2.prev = 22;
157
+ _context2.t0 = _context2["catch"](10);
126
158
  _didIteratorError = true;
127
159
  _iteratorError = _context2.t0;
128
- case 25:
129
- _context2.prev = 25;
160
+ case 26:
130
161
  _context2.prev = 26;
162
+ _context2.prev = 27;
131
163
  if (!(_iteratorAbruptCompletion && _iterator.return != null)) {
132
- _context2.next = 30;
164
+ _context2.next = 31;
133
165
  break;
134
166
  }
135
- _context2.next = 30;
167
+ _context2.next = 31;
136
168
  return _iterator.return();
137
- case 30:
138
- _context2.prev = 30;
169
+ case 31:
170
+ _context2.prev = 31;
139
171
  if (!_didIteratorError) {
140
- _context2.next = 33;
172
+ _context2.next = 34;
141
173
  break;
142
174
  }
143
175
  throw _iteratorError;
144
- case 33:
145
- return _context2.finish(30);
146
176
  case 34:
147
- return _context2.finish(25);
177
+ return _context2.finish(31);
148
178
  case 35:
179
+ return _context2.finish(26);
180
+ case 36:
149
181
  this.state = {
150
182
  status: 'done',
151
183
  content: bufferContent
152
184
  };
153
- this.subscribedStateSetter(this.state);
154
- case 37:
185
+ _iterator4 = _createForOfIteratorHelper(this.subscribedStateSetters);
186
+ try {
187
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
188
+ _subscriber2 = _step4.value;
189
+ _subscriber2(this.state);
190
+ }
191
+ } catch (err) {
192
+ _iterator4.e(err);
193
+ } finally {
194
+ _iterator4.f();
195
+ }
196
+ case 39:
155
197
  case "end":
156
198
  return _context2.stop();
157
199
  }
158
- }, _callee2, this, [[9, 21, 25, 35], [26,, 30, 34]]);
200
+ }, _callee2, this, [[10, 22, 26, 36], [27,, 31, 35]]);
159
201
  }));
160
202
  function summariseUrl() {
161
203
  return _summariseUrl.apply(this, arguments);
@@ -165,7 +207,11 @@ export var AISummaryService = /*#__PURE__*/function () {
165
207
  }, {
166
208
  key: "subscribe",
167
209
  value: function subscribe(stateSetter) {
168
- this.subscribedStateSetter = stateSetter;
210
+ var _this2 = this;
211
+ this.subscribedStateSetters.add(stateSetter);
212
+ return function () {
213
+ _this2.subscribedStateSetters.delete(stateSetter);
214
+ };
169
215
  }
170
216
  }]);
171
217
  return AISummaryService;
@@ -1,36 +1,61 @@
1
1
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
- import { useState, useEffect } from 'react';
2
+ import { useState, useEffect, useMemo } from 'react';
3
3
  import { AISummariesStore } from './ai-summary-service/store';
4
4
  import { AISummaryService } from './ai-summary-service';
5
5
  export var useAISummary = function useAISummary(props) {
6
- var url = props.url;
7
- var aISummaryService = AISummariesStore.get(url);
8
- var isAISummaryServiceInitiated = !!aISummaryService;
9
- var _useState = useState(isAISummaryServiceInitiated ? aISummaryService.state : {
6
+ var _AISummariesStore$get;
7
+ var url = props.url,
8
+ baseUrl = props.baseUrl,
9
+ product = props.product,
10
+ headers = props.headers;
11
+ var _useState = useState(((_AISummariesStore$get = AISummariesStore.get(url)) === null || _AISummariesStore$get === void 0 ? void 0 : _AISummariesStore$get.state) || {
10
12
  status: 'ready',
11
13
  content: ''
12
14
  }),
13
15
  _useState2 = _slicedToArray(_useState, 2),
14
16
  state = _useState2[0],
15
17
  setState = _useState2[1];
16
- var isSummarised = isAISummaryServiceInitiated && state.status === 'done';
18
+
19
+ // Can be used to know the summary status upon mounting a component (HoverCard UI state for example).
20
+ // For other scenarios, opt for dynamic status updates via state.status.
21
+ var isSummarisedOnMount = useMemo(function () {
22
+ var _AISummariesStore$get2;
23
+ return ((_AISummariesStore$get2 = AISummariesStore.get(url)) === null || _AISummariesStore$get2 === void 0 ? void 0 : _AISummariesStore$get2.state.status) === 'done';
24
+ }, [url]);
17
25
  useEffect(function () {
18
- if (!isSummarised) {
19
- var _AISummariesStore$get;
20
- if (!isAISummaryServiceInitiated) {
21
- AISummariesStore.set(url, new AISummaryService(props));
26
+ // Create or subscribe to an AI service only if a summary has not been previously generated.
27
+ // Otherwise, use the data from the current state synchronized with a cache (AISummariesStore).
28
+ if (!isSummarisedOnMount) {
29
+ var aISummaryService = AISummariesStore.get(url);
30
+ var isAISummaryServiceInitiated = !!aISummaryService;
31
+ if (isAISummaryServiceInitiated) {
32
+ //if we want to subscribe to updates from an existing AI service that has not yet provided a summary or is currently in progress.
33
+ var unsubscribe = aISummaryService.subscribe(setState);
34
+ return function () {
35
+ return unsubscribe();
36
+ };
37
+ } else {
38
+ var _AISummariesStore$get3;
39
+ //if we want to create a new AI service and wish to subscribe for updates
40
+ AISummariesStore.set(url, new AISummaryService({
41
+ url: url,
42
+ baseUrl: baseUrl,
43
+ product: product,
44
+ headers: headers
45
+ }));
46
+ var _unsubscribe = (_AISummariesStore$get3 = AISummariesStore.get(url)) === null || _AISummariesStore$get3 === void 0 ? void 0 : _AISummariesStore$get3.subscribe(setState);
47
+ return function () {
48
+ return _unsubscribe && _unsubscribe();
49
+ };
22
50
  }
23
- return (_AISummariesStore$get = AISummariesStore.get(url)) === null || _AISummariesStore$get === void 0 ? void 0 : _AISummariesStore$get.subscribe(setState);
24
51
  }
25
- }, [isSummarised, isAISummaryServiceInitiated, url, props]);
52
+ }, [isSummarisedOnMount, url, baseUrl, product, headers]);
26
53
  var summariseUrl = function summariseUrl() {
27
- if (isAISummaryServiceInitiated) {
28
- return aISummaryService.summariseUrl();
29
- }
30
- return;
54
+ var _AISummariesStore$get4;
55
+ return (_AISummariesStore$get4 = AISummariesStore.get(url)) === null || _AISummariesStore$get4 === void 0 ? void 0 : _AISummariesStore$get4.summariseUrl();
31
56
  };
32
57
  return {
33
- isSummarised: isSummarised,
58
+ isSummarisedOnMount: isSummarisedOnMount,
34
59
  summariseUrl: summariseUrl,
35
60
  state: state
36
61
  };
@@ -15,7 +15,7 @@ export var ANALYTICS_CHANNEL = 'media';
15
15
  export var context = {
16
16
  componentName: 'smart-cards',
17
17
  packageName: "@atlaskit/smart-card",
18
- packageVersion: "26.48.2"
18
+ packageVersion: "26.48.3"
19
19
  };
20
20
  export var TrackQuickActionType = /*#__PURE__*/function (TrackQuickActionType) {
21
21
  TrackQuickActionType["StatusUpdate"] = "StatusUpdate";
@@ -203,5 +203,5 @@ export var getIsAISummaryEnabled = function getIsAISummaryEnabled() {
203
203
  var _response$meta;
204
204
  var isAdminHubAIEnabled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
205
205
  var response = arguments.length > 1 ? arguments[1] : undefined;
206
- return Boolean(getBooleanFF('platform.linking-platform.smart-card.hover-card-ai-summaries') && isAdminHubAIEnabled && (response === null || response === void 0 || (_response$meta = response.meta) === null || _response$meta === void 0 || (_response$meta = _response$meta.supportedFeatures) === null || _response$meta === void 0 ? void 0 : _response$meta.includes('AISummary')));
206
+ return Boolean(getBooleanFF('platform.linking-platform.smart-card.hover-card-ai-summaries') && isAdminHubAIEnabled && (response === null || response === void 0 || (_response$meta = response.meta) === null || _response$meta === void 0 || (_response$meta = _response$meta.supportedFeature) === null || _response$meta === void 0 ? void 0 : _response$meta.includes('AISummary')));
207
207
  };
@@ -10,7 +10,7 @@ import { useLinkWarningModal } from './LinkWarningModal/hooks/use-link-warning-m
10
10
  import LinkWarningModal from './LinkWarningModal';
11
11
  var PACKAGE_DATA = {
12
12
  packageName: "@atlaskit/smart-card",
13
- packageVersion: "26.48.2",
13
+ packageVersion: "26.48.3",
14
14
  componentName: 'linkUrl'
15
15
  };
16
16
  var Link = withLinkClickedEvent('a');
@@ -3,9 +3,9 @@ export declare class AISummaryService implements AISummaryServiceInt {
3
3
  state: AISummaryState;
4
4
  private config;
5
5
  private url;
6
- private subscribedStateSetter;
6
+ private subscribedStateSetters;
7
7
  constructor(props: AISummaryServiceProps);
8
8
  private fetchStream;
9
9
  summariseUrl(summaryStyle?: SummaryStyle): Promise<void>;
10
- subscribe(stateSetter: StateSetter): void;
10
+ subscribe(stateSetter: StateSetter): () => void;
11
11
  }
@@ -2,7 +2,7 @@
2
2
  export interface AISummaryServiceInt {
3
3
  summariseUrl: () => Promise<void>;
4
4
  state: AISummaryState;
5
- subscribe: (stateSetter: StateSetter) => void;
5
+ subscribe: (stateSetter: StateSetter) => () => void;
6
6
  }
7
7
  export type AISummaryServiceProps = {
8
8
  baseUrl?: string;
@@ -1,6 +1,6 @@
1
1
  import type { AISummaryServiceProps, AISummaryStatus } from './ai-summary-service/types';
2
2
  export declare const useAISummary: (props: AISummaryServiceProps) => {
3
- isSummarised: boolean;
3
+ isSummarisedOnMount: boolean;
4
4
  summariseUrl: () => Promise<void> | undefined;
5
5
  state: {
6
6
  status: AISummaryStatus;
@@ -3,9 +3,9 @@ export declare class AISummaryService implements AISummaryServiceInt {
3
3
  state: AISummaryState;
4
4
  private config;
5
5
  private url;
6
- private subscribedStateSetter;
6
+ private subscribedStateSetters;
7
7
  constructor(props: AISummaryServiceProps);
8
8
  private fetchStream;
9
9
  summariseUrl(summaryStyle?: SummaryStyle): Promise<void>;
10
- subscribe(stateSetter: StateSetter): void;
10
+ subscribe(stateSetter: StateSetter): () => void;
11
11
  }
@@ -2,7 +2,7 @@
2
2
  export interface AISummaryServiceInt {
3
3
  summariseUrl: () => Promise<void>;
4
4
  state: AISummaryState;
5
- subscribe: (stateSetter: StateSetter) => void;
5
+ subscribe: (stateSetter: StateSetter) => () => void;
6
6
  }
7
7
  export type AISummaryServiceProps = {
8
8
  baseUrl?: string;
@@ -1,6 +1,6 @@
1
1
  import type { AISummaryServiceProps, AISummaryStatus } from './ai-summary-service/types';
2
2
  export declare const useAISummary: (props: AISummaryServiceProps) => {
3
- isSummarised: boolean;
3
+ isSummarisedOnMount: boolean;
4
4
  summariseUrl: () => Promise<void> | undefined;
5
5
  state: {
6
6
  status: AISummaryStatus;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/smart-card",
3
- "version": "26.48.2",
3
+ "version": "26.48.3",
4
4
  "description": "Smart card component",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -48,7 +48,7 @@
48
48
  "@atlaskit/outbound-auth-flow-client": "^3.4.0",
49
49
  "@atlaskit/platform-feature-flags": "^0.2.1",
50
50
  "@atlaskit/popup": "^1.12.0",
51
- "@atlaskit/primitives": "^3.0.0",
51
+ "@atlaskit/primitives": "^3.1.0",
52
52
  "@atlaskit/spinner": "^16.0.0",
53
53
  "@atlaskit/theme": "^12.6.0",
54
54
  "@atlaskit/tokens": "^1.38.0",