polfan-server-js-client 0.4.1 → 0.4.2

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.
@@ -4,7 +4,7 @@
4
4
  <option name="autoReloadType" value="SELECTIVE" />
5
5
  </component>
6
6
  <component name="ChangeListManager">
7
- <list default="true" id="831dae43-0da1-47fd-a5f7-33dd5eec2992" name="Changes" comment="Reacting changes" />
7
+ <list default="true" id="831dae43-0da1-47fd-a5f7-33dd5eec2992" name="Changes" comment="Revert &quot;User presence status support&quot;&#10;&#10;This reverts commit b9ff2004" />
8
8
  <option name="SHOW_DIALOG" value="false" />
9
9
  <option name="HIGHLIGHT_CONFLICTS" value="true" />
10
10
  <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
@@ -17,16 +17,22 @@
17
17
  <option name="cachedIndexableFilesCount" value="213" />
18
18
  </component>
19
19
  <component name="Git.Rebase.Settings">
20
- <option name="NEW_BASE" value="origin/main" />
20
+ <option name="NEW_BASE" value="master" />
21
+ <option name="OPTIONS">
22
+ <set>
23
+ <option value="INTERACTIVE" />
24
+ </set>
25
+ </option>
21
26
  </component>
22
27
  <component name="Git.Settings">
23
28
  <option name="RECENT_BRANCH_BY_REPOSITORY">
24
29
  <map>
25
- <entry key="$PROJECT_DIR$" value="claude/room-messages-reconnect-history-kfddmm" />
30
+ <entry key="$PROJECT_DIR$" value="claude/chat-reactions-polls-system-hwea5i" />
26
31
  <entry key="$PROJECT_DIR$/src/types" value="main" />
27
32
  </map>
28
33
  </option>
29
- <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/src/types" />
34
+ <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
35
+ <option name="RESET_MODE" value="HARD" />
30
36
  <option name="ROOT_SYNC" value="DONT_SYNC" />
31
37
  </component>
32
38
  <component name="GitHubPullRequestSearchHistory">{
@@ -38,12 +44,12 @@
38
44
  <component name="GitRewordedCommitMessages">
39
45
  <option name="commitMessagesMapping">
40
46
  <RewordedCommitMessageMapping>
41
- <option name="originalMessage" value="Custom avatars support" />
42
- <option name="rewordedMessage" value="Custom avatars support" />
47
+ <option name="originalMessage" value="Message reactions and polls&#10;&#10;The history window keeps the global counters on the messages themselves and the&#10;connected user's own votes in a map beside them, so what everybody sees stays&#10;identical and only the active state differs per user. `MessageReactionChanged`&#10;overwrites a counter in place (a pill must not jump around as its number moves)&#10;and retires it at zero; `ReactionToggled` moves the user's own entry.&#10;&#10;A GetMessages response is the truth for every message it covers, so the map is&#10;refreshed from it rather than merged - a vote withdrawn from another device does&#10;not survive a reload.&#10;&#10;The four near-identical fetchers now share one request helper, which is also&#10;where `includeMyReactions` is attached." />
48
+ <option name="rewordedMessage" value="Message reactions and polls" />
43
49
  </RewordedCommitMessageMapping>
44
50
  </option>
45
51
  <option name="currentCommit" value="1" />
46
- <option name="onto" value="6a2d671a2ea3742ea3977b1d035f4d4bed40c7eb" />
52
+ <option name="onto" value="79acd57a1c49b90da43379eaa1805f46ad9a655e" />
47
53
  </component>
48
54
  <component name="GithubPullRequestsUISettings">{
49
55
  &quot;selectedUrlAndAccountId&quot;: {
@@ -77,7 +83,7 @@
77
83
  "RunOnceActivity.typescript.service.memoryLimit.init": "true",
78
84
  "codeWithMe.voiceChat.enabledByDefault": "false",
79
85
  "com.intellij.ml.llm.matterhorn.ej.ui.settings.DefaultModelSelectionForGA.v1": "true",
80
- "git-widget-placeholder": "claude/chat-reactions-polls-system-hwea5i",
86
+ "git-widget-placeholder": "master",
81
87
  "git.auto.fetch.suggestion.counter": "3",
82
88
  "ignore.virus.scanning.warn.message": "true",
83
89
  "junie.onboarding.icon.badge.shown": "true",
@@ -247,6 +253,7 @@
247
253
  <workItem from="1786526830597" duration="598000" />
248
254
  <workItem from="1787125977456" duration="278000" />
249
255
  <workItem from="1787576741803" duration="2076000" />
256
+ <workItem from="1787648458595" duration="967000" />
250
257
  </task>
251
258
  <task id="LOCAL-00067" summary="Ping-pong connection monitoring">
252
259
  <option name="closed" value="true" />
@@ -654,17 +661,17 @@
654
661
  <list>
655
662
  <RecentGroup>
656
663
  <option name="FILTER_VALUES">
657
- <option value="claude/chat-reactions-polls-system-hwea5i" />
664
+ <option value="master" />
658
665
  </option>
659
666
  </RecentGroup>
660
667
  <RecentGroup>
661
668
  <option name="FILTER_VALUES">
662
- <option value="claude/avatars-room-space-support-bvrcaz" />
669
+ <option value="claude/chat-reactions-polls-system-hwea5i" />
663
670
  </option>
664
671
  </RecentGroup>
665
672
  <RecentGroup>
666
673
  <option name="FILTER_VALUES">
667
- <option value="master" />
674
+ <option value="claude/avatars-room-space-support-bvrcaz" />
668
675
  </option>
669
676
  </RecentGroup>
670
677
  <RecentGroup>
@@ -697,7 +704,7 @@
697
704
  <entry key="branch">
698
705
  <value>
699
706
  <list>
700
- <option value="claude/chat-reactions-polls-system-hwea5i" />
707
+ <option value="master" />
701
708
  </list>
702
709
  </value>
703
710
  </entry>
@@ -710,7 +717,6 @@
710
717
  </option>
711
718
  </component>
712
719
  <component name="VcsManagerConfiguration">
713
- <MESSAGE value="Update Topic on redacted message" />
714
720
  <MESSAGE value="Fix room member update event handle" />
715
721
  <MESSAGE value="Fix room member update event handle" />
716
722
  <MESSAGE value="Add jumpTo message support" />
@@ -735,7 +741,8 @@
735
741
  <MESSAGE value="Custom avatars support" />
736
742
  <MESSAGE value="User presence status support" />
737
743
  <MESSAGE value="Reacting changes" />
738
- <option name="LAST_COMMIT_MESSAGE" value="Reacting changes" />
744
+ <MESSAGE value="Revert &quot;User presence status support&quot;&#10;&#10;This reverts commit b9ff2004" />
745
+ <option name="LAST_COMMIT_MESSAGE" value="Revert &quot;User presence status support&quot;&#10;&#10;This reverts commit b9ff2004" />
739
746
  </component>
740
747
  <component name="XSLT-Support.FileAssociations.UIState">
741
748
  <expand />
@@ -718,6 +718,7 @@ var PromiseRegistry = /*#__PURE__*/function () {
718
718
  }();
719
719
  ;// ./src/state-tracker/TopicHistoryWindow.ts
720
720
  function TopicHistoryWindow_typeof(o) { "@babel/helpers - typeof"; return TopicHistoryWindow_typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, TopicHistoryWindow_typeof(o); }
721
+ function TopicHistoryWindow_createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = TopicHistoryWindow_unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, 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 o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
721
722
  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; }
722
723
  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) { TopicHistoryWindow_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; }
723
724
  function TopicHistoryWindow_superPropGet(t, o, e, r) { var p = TopicHistoryWindow_get(TopicHistoryWindow_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && "function" == typeof p ? function (t) { return p.apply(e, t); } : p; }
@@ -1164,6 +1165,8 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1164
1165
  _this3.topicId = topicId;
1165
1166
  _this3.tracker = tracker;
1166
1167
  _this3.internalState.traverseLock = false;
1168
+ _this3.internalState.includeMyReactions = true;
1169
+ _this3.internalState.myReactions = {};
1167
1170
  if (bindEvents) {
1168
1171
  _this3.tracker.client.on('NewMessage', function (ev) {
1169
1172
  return _this3.handleNewMessage(ev);
@@ -1171,6 +1174,12 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1171
1174
  _this3.tracker.client.on('MessagesRedacted', function (ev) {
1172
1175
  return _this3.handleMessagesRedacted(ev);
1173
1176
  });
1177
+ _this3.tracker.client.on('ReactionUpdated', function (ev) {
1178
+ return _this3.handleReactionUpdated(ev);
1179
+ });
1180
+ _this3.tracker.client.on('Reacted', function (ev) {
1181
+ return _this3.handleReacted(ev);
1182
+ });
1174
1183
  }
1175
1184
  return _this3;
1176
1185
  }
@@ -1189,6 +1198,29 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1189
1198
  get: function get() {
1190
1199
  return this.internalState.traverseLock;
1191
1200
  }
1201
+
1202
+ /**
1203
+ * What the connected user has reacted with, keyed by message id. Kept apart from
1204
+ * the messages, so the history itself is identical for every user.
1205
+ */
1206
+ }, {
1207
+ key: "myReactions",
1208
+ get: function get() {
1209
+ return this.internalState.myReactions;
1210
+ }
1211
+
1212
+ /**
1213
+ * Whether the history is fetched together with the reactions of the connected
1214
+ * user. Turn it off only where the active state of a reaction is never rendered.
1215
+ */
1216
+ }, {
1217
+ key: "includeMyReactions",
1218
+ get: function get() {
1219
+ return this.internalState.includeMyReactions;
1220
+ },
1221
+ set: function set(value) {
1222
+ this.internalState.includeMyReactions = value;
1223
+ }
1192
1224
  }, {
1193
1225
  key: "setTraverseLock",
1194
1226
  value: function () {
@@ -1324,35 +1356,14 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1324
1356
  value: function () {
1325
1357
  var _fetchItemsAfter = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee1() {
1326
1358
  var _this$getAt;
1327
- var afterId, result;
1359
+ var afterId;
1328
1360
  return _regenerator().w(function (_context1) {
1329
1361
  while (1) switch (_context1.n) {
1330
1362
  case 0:
1331
- afterId = (_this$getAt = this.getAt(this.length - 1)) === null || _this$getAt === void 0 ? void 0 : _this$getAt.id;
1332
- if (afterId) {
1333
- _context1.n = 1;
1334
- break;
1335
- }
1336
- return _context1.a(2, null);
1337
- case 1:
1338
- _context1.n = 2;
1339
- return this.tracker.client.send('GetMessages', {
1340
- location: {
1341
- roomId: this.roomId,
1342
- topicId: this.topicId
1343
- },
1344
- after: afterId,
1345
- limit: this.internalState.fetchLimit
1346
- });
1347
- case 2:
1348
- result = _context1.v;
1349
- if (!result.error) {
1350
- _context1.n = 3;
1351
- break;
1352
- }
1353
- throw new Error("Cannot fetch messages: ".concat(result.error.message));
1354
- case 3:
1355
- return _context1.a(2, result.data.messages);
1363
+ afterId = (_this$getAt = this.getAt(this.length - 1)) === null || _this$getAt === void 0 ? void 0 : _this$getAt.id; // If there is no message to refer, fetch latest
1364
+ return _context1.a(2, afterId ? this.fetchMessages({
1365
+ after: afterId
1366
+ }) : null);
1356
1367
  }
1357
1368
  }, _callee1, this);
1358
1369
  }));
@@ -1365,28 +1376,12 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1365
1376
  key: "fetchItemsAround",
1366
1377
  value: function () {
1367
1378
  var _fetchItemsAround = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee10(id) {
1368
- var result;
1369
1379
  return _regenerator().w(function (_context10) {
1370
1380
  while (1) switch (_context10.n) {
1371
1381
  case 0:
1372
- _context10.n = 1;
1373
- return this.tracker.client.send('GetMessages', {
1374
- location: {
1375
- roomId: this.roomId,
1376
- topicId: this.topicId
1377
- },
1378
- around: id,
1379
- limit: this.internalState.fetchLimit
1380
- });
1381
- case 1:
1382
- result = _context10.v;
1383
- if (!result.error) {
1384
- _context10.n = 2;
1385
- break;
1386
- }
1387
- throw new Error("Cannot fetch messages: ".concat(result.error.message));
1388
- case 2:
1389
- return _context10.a(2, result.data.messages);
1382
+ return _context10.a(2, this.fetchMessages({
1383
+ around: id
1384
+ }));
1390
1385
  }
1391
1386
  }, _callee10, this);
1392
1387
  }));
@@ -1400,35 +1395,14 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1400
1395
  value: function () {
1401
1396
  var _fetchItemsBefore = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee11() {
1402
1397
  var _this$getAt2;
1403
- var beforeId, result;
1398
+ var beforeId;
1404
1399
  return _regenerator().w(function (_context11) {
1405
1400
  while (1) switch (_context11.n) {
1406
1401
  case 0:
1407
- beforeId = (_this$getAt2 = this.getAt(0)) === null || _this$getAt2 === void 0 ? void 0 : _this$getAt2.id;
1408
- if (beforeId) {
1409
- _context11.n = 1;
1410
- break;
1411
- }
1412
- return _context11.a(2, null);
1413
- case 1:
1414
- _context11.n = 2;
1415
- return this.tracker.client.send('GetMessages', {
1416
- location: {
1417
- roomId: this.roomId,
1418
- topicId: this.topicId
1419
- },
1420
- before: beforeId,
1421
- limit: this.internalState.fetchLimit
1422
- });
1423
- case 2:
1424
- result = _context11.v;
1425
- if (!result.error) {
1426
- _context11.n = 3;
1427
- break;
1428
- }
1429
- throw new Error("Cannot fetch messages: ".concat(result.error.message));
1430
- case 3:
1431
- return _context11.a(2, result.data.messages);
1402
+ beforeId = (_this$getAt2 = this.getAt(0)) === null || _this$getAt2 === void 0 ? void 0 : _this$getAt2.id; // If there is no message to refer, fetch latest
1403
+ return _context11.a(2, beforeId ? this.fetchMessages({
1404
+ before: beforeId
1405
+ }) : null);
1432
1406
  }
1433
1407
  }, _callee11, this);
1434
1408
  }));
@@ -1441,48 +1415,94 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1441
1415
  key: "fetchLatestItems",
1442
1416
  value: function () {
1443
1417
  var _fetchLatestItems = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee12() {
1444
- var result;
1445
1418
  return _regenerator().w(function (_context12) {
1446
1419
  while (1) switch (_context12.n) {
1447
1420
  case 0:
1448
- _context12.n = 1;
1449
- return this.tracker.client.send('GetMessages', {
1421
+ return _context12.a(2, this.fetchMessages({}));
1422
+ }
1423
+ }, _callee12, this);
1424
+ }));
1425
+ function fetchLatestItems() {
1426
+ return _fetchLatestItems.apply(this, arguments);
1427
+ }
1428
+ return fetchLatestItems;
1429
+ }()
1430
+ }, {
1431
+ key: "fetchMessages",
1432
+ value: function () {
1433
+ var _fetchMessages = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee13(criteria) {
1434
+ var result;
1435
+ return _regenerator().w(function (_context13) {
1436
+ while (1) switch (_context13.n) {
1437
+ case 0:
1438
+ _context13.n = 1;
1439
+ return this.tracker.client.send('GetMessages', _objectSpread({
1450
1440
  location: {
1451
1441
  roomId: this.roomId,
1452
1442
  topicId: this.topicId
1453
1443
  },
1454
- limit: this.internalState.fetchLimit
1455
- });
1444
+ limit: this.internalState.fetchLimit,
1445
+ includeMyReactions: this.internalState.includeMyReactions
1446
+ }, criteria));
1456
1447
  case 1:
1457
- result = _context12.v;
1448
+ result = _context13.v;
1458
1449
  if (!result.error) {
1459
- _context12.n = 2;
1450
+ _context13.n = 2;
1460
1451
  break;
1461
1452
  }
1462
1453
  throw new Error("Cannot fetch messages: ".concat(result.error.message));
1463
1454
  case 2:
1464
- return _context12.a(2, result.data.messages);
1455
+ this.storeMyReactions(result.data.messages, result.data.myReactions);
1456
+ return _context13.a(2, result.data.messages);
1465
1457
  }
1466
- }, _callee12, this);
1458
+ }, _callee13, this);
1467
1459
  }));
1468
- function fetchLatestItems() {
1469
- return _fetchLatestItems.apply(this, arguments);
1460
+ function fetchMessages(_x5) {
1461
+ return _fetchMessages.apply(this, arguments);
1470
1462
  }
1471
- return fetchLatestItems;
1463
+ return fetchMessages;
1472
1464
  }()
1465
+ /**
1466
+ * The response is the truth for every message it covers, so a message it does not
1467
+ * mention has no reaction of this user left on it.
1468
+ */
1469
+ }, {
1470
+ key: "storeMyReactions",
1471
+ value: function storeMyReactions(messages, myReactions) {
1472
+ if (!this.internalState.includeMyReactions) {
1473
+ return;
1474
+ }
1475
+ var _iterator = TopicHistoryWindow_createForOfIteratorHelper(messages),
1476
+ _step;
1477
+ try {
1478
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
1479
+ var message = _step.value;
1480
+ var own = myReactions === null || myReactions === void 0 ? void 0 : myReactions[message.id];
1481
+ if (own !== null && own !== void 0 && own.length) {
1482
+ this.internalState.myReactions[message.id] = own;
1483
+ } else {
1484
+ delete this.internalState.myReactions[message.id];
1485
+ }
1486
+ }
1487
+ } catch (err) {
1488
+ _iterator.e(err);
1489
+ } finally {
1490
+ _iterator.f();
1491
+ }
1492
+ }
1473
1493
  }, {
1474
1494
  key: "getTopic",
1475
1495
  value: function () {
1476
- var _getTopic = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee13() {
1477
- return _regenerator().w(function (_context13) {
1478
- while (1) switch (_context13.n) {
1496
+ var _getTopic = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee14() {
1497
+ return _regenerator().w(function (_context14) {
1498
+ while (1) switch (_context14.n) {
1479
1499
  case 0:
1480
- _context13.n = 1;
1500
+ _context14.n = 1;
1481
1501
  return this.tracker.rooms.getTopics(this.roomId, [this.topicId]);
1482
1502
  case 1:
1483
- return _context13.a(2, _context13.v.get(this.topicId));
1503
+ return _context14.a(2, _context14.v.get(this.topicId));
1484
1504
  }
1485
- }, _callee13, this);
1505
+ }, _callee14, this);
1486
1506
  }));
1487
1507
  function getTopic() {
1488
1508
  return _getTopic.apply(this, arguments);
@@ -1492,43 +1512,43 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1492
1512
  }, {
1493
1513
  key: "getLatestMessageId",
1494
1514
  value: function () {
1495
- var _getLatestMessageId = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee14() {
1515
+ var _getLatestMessageId = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee15() {
1496
1516
  var _yield$this$getTopic;
1497
1517
  var _t2, _t3, _t4, _t5;
1498
- return _regenerator().w(function (_context14) {
1499
- while (1) switch (_context14.n) {
1518
+ return _regenerator().w(function (_context15) {
1519
+ while (1) switch (_context15.n) {
1500
1520
  case 0:
1501
- _context14.n = 1;
1521
+ _context15.n = 1;
1502
1522
  return this.getTopic();
1503
1523
  case 1:
1504
- _t4 = _yield$this$getTopic = _context14.v;
1524
+ _t4 = _yield$this$getTopic = _context15.v;
1505
1525
  _t3 = _t4 === null;
1506
1526
  if (_t3) {
1507
- _context14.n = 2;
1527
+ _context15.n = 2;
1508
1528
  break;
1509
1529
  }
1510
1530
  _t3 = _yield$this$getTopic === void 0;
1511
1531
  case 2:
1512
1532
  _t2 = _t3;
1513
1533
  if (_t2) {
1514
- _context14.n = 3;
1534
+ _context15.n = 3;
1515
1535
  break;
1516
1536
  }
1517
1537
  _t2 = (_yield$this$getTopic = _yield$this$getTopic.lastMessage) === null || _yield$this$getTopic === void 0;
1518
1538
  case 3:
1519
1539
  if (!_t2) {
1520
- _context14.n = 4;
1540
+ _context15.n = 4;
1521
1541
  break;
1522
1542
  }
1523
1543
  _t5 = void 0;
1524
- _context14.n = 5;
1544
+ _context15.n = 5;
1525
1545
  break;
1526
1546
  case 4:
1527
1547
  _t5 = _yield$this$getTopic.id;
1528
1548
  case 5:
1529
- return _context14.a(2, _t5);
1549
+ return _context15.a(2, _t5);
1530
1550
  }
1531
- }, _callee14, this);
1551
+ }, _callee15, this);
1532
1552
  }));
1533
1553
  function getLatestMessageId() {
1534
1554
  return _getLatestMessageId.apply(this, arguments);
@@ -1538,18 +1558,18 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1538
1558
  }, {
1539
1559
  key: "isLatestItemLoaded",
1540
1560
  value: function () {
1541
- var _isLatestItemLoaded = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee15() {
1561
+ var _isLatestItemLoaded = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee16() {
1542
1562
  var lastMessageId;
1543
- return _regenerator().w(function (_context15) {
1544
- while (1) switch (_context15.n) {
1563
+ return _regenerator().w(function (_context16) {
1564
+ while (1) switch (_context16.n) {
1545
1565
  case 0:
1546
- _context15.n = 1;
1566
+ _context16.n = 1;
1547
1567
  return this.getLatestMessageId();
1548
1568
  case 1:
1549
- lastMessageId = _context15.v;
1550
- return _context15.a(2, lastMessageId ? this.has(lastMessageId) : true);
1569
+ lastMessageId = _context16.v;
1570
+ return _context16.a(2, lastMessageId ? this.has(lastMessageId) : true);
1551
1571
  }
1552
- }, _callee15, this);
1572
+ }, _callee16, this);
1553
1573
  }));
1554
1574
  function isLatestItemLoaded() {
1555
1575
  return _isLatestItemLoaded.apply(this, arguments);
@@ -1559,10 +1579,10 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1559
1579
  }, {
1560
1580
  key: "handleNewMessage",
1561
1581
  value: function () {
1562
- var _handleNewMessage = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee16(ev) {
1582
+ var _handleNewMessage = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee17(ev) {
1563
1583
  var originalState;
1564
- return _regenerator().w(function (_context16) {
1565
- while (1) switch (_context16.n) {
1584
+ return _regenerator().w(function (_context17) {
1585
+ while (1) switch (_context17.n) {
1566
1586
  case 0:
1567
1587
  if ([WindowState.LATEST, WindowState.LIVE].includes(this.state) && ev.message.location.roomId === this.roomId && ev.message.location.topicId === this.topicId) {
1568
1588
  originalState = this.state;
@@ -1570,28 +1590,86 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1570
1590
  this.emitChangeWithDiff(true, originalState);
1571
1591
  }
1572
1592
  case 1:
1573
- return _context16.a(2);
1593
+ return _context17.a(2);
1574
1594
  }
1575
- }, _callee16, this);
1595
+ }, _callee17, this);
1576
1596
  }));
1577
- function handleNewMessage(_x5) {
1597
+ function handleNewMessage(_x6) {
1578
1598
  return _handleNewMessage.apply(this, arguments);
1579
1599
  }
1580
1600
  return handleNewMessage;
1581
1601
  }()
1602
+ /**
1603
+ * The counter arrives as the global source of truth - only it is overwritten, and
1604
+ * a reaction nobody holds any more (count 0) leaves the message.
1605
+ */
1606
+ }, {
1607
+ key: "handleReactionUpdated",
1608
+ value: function handleReactionUpdated(ev) {
1609
+ var message = this.get(ev.messageId);
1610
+ if (!message) {
1611
+ return;
1612
+ }
1613
+ var index = message.reactions.findIndex(function (reaction) {
1614
+ return reaction.type === ev.reaction.type && reaction.value === ev.reaction.value;
1615
+ });
1616
+ if (index === -1 && !ev.reaction.count) {
1617
+ return;
1618
+ }
1619
+ var reactions = TopicHistoryWindow_toConsumableArray(message.reactions);
1620
+ if (index === -1) {
1621
+ reactions.push(ev.reaction);
1622
+ } else if (ev.reaction.count) {
1623
+ reactions[index] = ev.reaction; // In place - a pill must not jump around as its counter moves
1624
+ } else {
1625
+ reactions.splice(index, 1);
1626
+ }
1627
+ this.set(_objectSpread(_objectSpread({}, message), {}, {
1628
+ reactions: reactions
1629
+ }));
1630
+ }
1631
+ }, {
1632
+ key: "handleReacted",
1633
+ value: function handleReacted(ev) {
1634
+ var _this$internalState$m;
1635
+ if (!this.has(ev.messageId)) {
1636
+ return;
1637
+ }
1638
+ var _ev$reaction = ev.reaction,
1639
+ type = _ev$reaction.type,
1640
+ value = _ev$reaction.value,
1641
+ isAdded = _ev$reaction.isAdded;
1642
+ var own = ((_this$internalState$m = this.internalState.myReactions[ev.messageId]) !== null && _this$internalState$m !== void 0 ? _this$internalState$m : []).filter(function (reaction) {
1643
+ return reaction.type !== type || reaction.value !== value;
1644
+ });
1645
+ if (isAdded) {
1646
+ own.push({
1647
+ type: type,
1648
+ value: value
1649
+ });
1650
+ }
1651
+ if (own.length) {
1652
+ this.internalState.myReactions[ev.messageId] = own;
1653
+ } else {
1654
+ delete this.internalState.myReactions[ev.messageId];
1655
+ }
1656
+ this.eventTarget.emit('change', {
1657
+ setItems: [ev.messageId]
1658
+ });
1659
+ }
1582
1660
  }, {
1583
1661
  key: "handleMessagesRedacted",
1584
1662
  value: function () {
1585
- var _handleMessagesRedacted = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee17(ev) {
1663
+ var _handleMessagesRedacted = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee18(ev) {
1586
1664
  var refTopicIds;
1587
- return _regenerator().w(function (_context17) {
1588
- while (1) switch (_context17.n) {
1665
+ return _regenerator().w(function (_context18) {
1666
+ while (1) switch (_context18.n) {
1589
1667
  case 0:
1590
1668
  if (!(ev.location.topicId !== this.topicId || ev.location.roomId !== this.roomId)) {
1591
- _context17.n = 1;
1669
+ _context18.n = 1;
1592
1670
  break;
1593
1671
  }
1594
- return _context17.a(2);
1672
+ return _context18.a(2);
1595
1673
  case 1:
1596
1674
  refTopicIds = this.items.filter(function (msg) {
1597
1675
  return msg.topicRef && ev.ids.includes(msg.id);
@@ -1600,21 +1678,21 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1600
1678
  });
1601
1679
  this["delete"].apply(this, TopicHistoryWindow_toConsumableArray(ev.ids));
1602
1680
  if (!(this.length === 0)) {
1603
- _context17.n = 2;
1681
+ _context18.n = 2;
1604
1682
  break;
1605
1683
  }
1606
- _context17.n = 2;
1684
+ _context18.n = 2;
1607
1685
  return this.resetToLatest();
1608
1686
  case 2:
1609
1687
  if (refTopicIds.length > 0) {
1610
1688
  this.eventTarget.emit('reftopicsdeleted', refTopicIds);
1611
1689
  }
1612
1690
  case 3:
1613
- return _context17.a(2);
1691
+ return _context18.a(2);
1614
1692
  }
1615
- }, _callee17, this);
1693
+ }, _callee18, this);
1616
1694
  }));
1617
- function handleMessagesRedacted(_x6) {
1695
+ function handleMessagesRedacted(_x7) {
1618
1696
  return _handleMessagesRedacted.apply(this, arguments);
1619
1697
  }
1620
1698
  return handleMessagesRedacted;
@@ -4240,6 +4318,14 @@ Permissions_defineProperty(Permissions, "list", {
4240
4318
  AddMembers: {
4241
4319
  value: 1 << 20,
4242
4320
  maxLayer: Layer.Space
4321
+ },
4322
+ React: {
4323
+ value: 1 << 21,
4324
+ maxLayer: Layer.Topic
4325
+ },
4326
+ CreatePolls: {
4327
+ value: 1 << 22,
4328
+ maxLayer: Layer.Topic
4243
4329
  }
4244
4330
  });
4245
4331
  ;// ./src/state-tracker/PermissionsManager.ts