@monterosa/sdk-interact-kit 0.19.0-rc.2 → 0.19.0-rc.4

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.
@@ -28,7 +28,8 @@ export declare enum Klass {
28
28
  Poll = "p",
29
29
  Feedback = "fb",
30
30
  Eoc = "eoc",
31
- Vote = "v"
31
+ Vote = "v",
32
+ SubsCounter = "subscounter"
32
33
  }
33
34
  /**
34
35
  * @internal
@@ -11,3 +11,4 @@ export * from './connection_health';
11
11
  export * from './project';
12
12
  export * from './event';
13
13
  export * from './element';
14
+ export * from './presence_counter';
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @license
3
+ * @monterosa/sdk-interact-kit
4
+ *
5
+ * Copyright © 2025 Monterosa Productions Limited. All rights reserved.
6
+ *
7
+ * More details on the license can be found at https://www.monterosa.co/sdk/license
8
+ */
9
+ import { Unsubscribe } from '@monterosa/sdk-util';
10
+ import { PresenceCounter } from './types';
11
+ import { InteractProject } from '../project';
12
+ export declare const presenceCounters: Map<string, PresenceCounter>;
13
+ export declare function getPresenceCounter(project?: InteractProject): Promise<PresenceCounter>;
14
+ export declare function onPresenceCounterUpdate(presenceCounter: PresenceCounter, callback: (count: number) => void): Unsubscribe;
15
+ export declare function onPresenceCounterOpen(presenceCounter: PresenceCounter, callback: () => void): Unsubscribe;
16
+ export declare function onPresenceCounterClose(presenceCounter: PresenceCounter, callback: () => void): Unsubscribe;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @license
3
+ * @monterosa/sdk-interact-kit
4
+ *
5
+ * Copyright © 2025 Monterosa Productions Limited. All rights reserved.
6
+ *
7
+ * More details on the license can be found at https://www.monterosa.co/sdk/license
8
+ */
9
+ export { getPresenceCounter, onPresenceCounterUpdate, onPresenceCounterOpen, onPresenceCounterClose, } from './api';
10
+ export { PresenceCounter, PresenceCounterState } from './types';
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @license
3
+ * @monterosa/sdk-interact-kit
4
+ *
5
+ * Copyright © 2025 Monterosa Productions Limited. All rights reserved.
6
+ *
7
+ * More details on the license can be found at https://www.monterosa.co/sdk/license
8
+ */
9
+ import { Emitter } from '@monterosa/sdk-util';
10
+ import { PresenceCounter } from './types';
11
+ export declare class PresenceCounterImpl extends Emitter implements PresenceCounter {
12
+ private host;
13
+ private id;
14
+ private state;
15
+ lastCount: number;
16
+ private connect;
17
+ private closeTimeout?;
18
+ private boundHandleMessage;
19
+ private boundHandleTimeout;
20
+ constructor(host: string, id: string);
21
+ init(): Promise<void>;
22
+ get isOpened(): boolean;
23
+ private handleMessage;
24
+ private handleCounterUpdate;
25
+ private handleTimeout;
26
+ private resetTimeout;
27
+ destroy(): void;
28
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @license
3
+ * @monterosa/sdk-interact-kit
4
+ *
5
+ * Copyright © 2025 Monterosa Productions Limited. All rights reserved.
6
+ *
7
+ * More details on the license can be found at https://www.monterosa.co/sdk/license
8
+ */
9
+ import { Emitter } from '@monterosa/sdk-util';
10
+ export interface PresenceCounter extends Emitter {
11
+ readonly isOpened: boolean;
12
+ readonly lastCount: number;
13
+ }
14
+ export declare enum PresenceCounterState {
15
+ Opened = "opened",
16
+ Closed = "closed"
17
+ }
18
+ export type PresenceCounterData = {
19
+ counter: number;
20
+ next_update_at: number;
21
+ };
package/dist/index.cjs.js CHANGED
@@ -200,6 +200,7 @@ exports.Klass = void 0;
200
200
  Klass["Feedback"] = "fb";
201
201
  Klass["Eoc"] = "eoc";
202
202
  Klass["Vote"] = "v";
203
+ Klass["SubsCounter"] = "subscounter";
203
204
  })(exports.Klass || (exports.Klass = {}));
204
205
  /**
205
206
  * @internal
@@ -2172,55 +2173,6 @@ var ElementImpl = /** @class */ (function (_super) {
2172
2173
  return ElementImpl;
2173
2174
  }(sdkUtil.Emitter));
2174
2175
 
2175
- /**
2176
- * @license
2177
- * @monterosa/sdk-interact-kit
2178
- *
2179
- * Copyright © 2022 Monterosa Productions Limited. All rights reserved.
2180
- *
2181
- * More details on the license can be found at https://www.monterosa.co/sdk/license
2182
- */
2183
- var calculatePercentage = function (values) {
2184
- // Calculate sum of all votes
2185
- var sum = values.reduce(function (memo, value) { return memo + value; }, 0);
2186
- // create array of hashes
2187
- var results = values.map(function (value, idx) { return ({
2188
- idx: idx,
2189
- votes: value,
2190
- percentage: Math.round((100 * value) / sum) || 0,
2191
- }); });
2192
- // Sum them all up - this can be less, equal or greater than a 100%
2193
- var total = results.reduce(function (memo, _a) {
2194
- var percentage = _a.percentage;
2195
- return memo + percentage;
2196
- }, 0);
2197
- total = total || 100;
2198
- // Calculate number of percent that we are missing or that we need to lose
2199
- var delta = 100 - total;
2200
- var sign = delta >= 0 ? 1 : -1;
2201
- // Order all options by number of votes
2202
- results.sort(function (a, b) {
2203
- var result = sign * (b.votes - a.votes);
2204
- if (result !== 0) {
2205
- return result;
2206
- }
2207
- return sign * (a.idx - b.idx);
2208
- });
2209
- // If we have percents to lose then take one percent off lowest options
2210
- // If we are missing percents then add one percent to highest options
2211
- var i = 0;
2212
- while (delta !== 0) {
2213
- if (results[i].votes > 0) {
2214
- results[i].percentage += sign;
2215
- delta -= sign;
2216
- }
2217
- i++;
2218
- }
2219
- // Restore options order
2220
- results.sort(function (a, b) { return a.idx - b.idx; });
2221
- return results.map(function (item) { return item.percentage; });
2222
- };
2223
-
2224
2176
  /**
2225
2177
  * @license
2226
2178
  * @monterosa/sdk-interact-kit
@@ -2377,7 +2329,7 @@ function handleFeedbackMessage(message) {
2377
2329
  return [2 /*return*/];
2378
2330
  }
2379
2331
  votes = counters.split(':').map(function (value) { return +value; });
2380
- percentages = calculatePercentage(votes);
2332
+ percentages = sdkUtil.calculatePercentage(votes);
2381
2333
  results = votes.map(function (item, idx) { return ({
2382
2334
  percentage: percentages[idx],
2383
2335
  votes: item,
@@ -2660,6 +2612,198 @@ function onElementRevoked(event, callback) {
2660
2612
  return sdkUtil.subscribe(event, 'revoke', callback);
2661
2613
  }
2662
2614
 
2615
+ /**
2616
+ * @license
2617
+ * @monterosa/sdk-interact-kit
2618
+ *
2619
+ * Copyright © 2025 Monterosa Productions Limited. All rights reserved.
2620
+ *
2621
+ * More details on the license can be found at https://www.monterosa.co/sdk/license
2622
+ */
2623
+ exports.PresenceCounterState = void 0;
2624
+ (function (PresenceCounterState) {
2625
+ PresenceCounterState["Opened"] = "opened";
2626
+ PresenceCounterState["Closed"] = "closed";
2627
+ })(exports.PresenceCounterState || (exports.PresenceCounterState = {}));
2628
+
2629
+ /**
2630
+ * @license
2631
+ * @monterosa/sdk-interact-kit
2632
+ *
2633
+ * Copyright © 2023 Monterosa Productions Limited. All rights reserved.
2634
+ *
2635
+ * More details on the license can be found at https://www.monterosa.co/sdk/license
2636
+ */
2637
+ var logger = new sdkCore.Logger('@monterosa/sdk-interact-kit');
2638
+
2639
+ /**
2640
+ * @license
2641
+ * @monterosa/sdk-interact-kit
2642
+ *
2643
+ * Copyright © 2025 Monterosa Productions Limited. All rights reserved.
2644
+ *
2645
+ * More details on the license can be found at https://www.monterosa.co/sdk/license
2646
+ */
2647
+ var PresenceCounterImpl = /** @class */ (function (_super) {
2648
+ __extends(PresenceCounterImpl, _super);
2649
+ function PresenceCounterImpl(host, id) {
2650
+ var _this = _super.call(this) || this;
2651
+ _this.host = host;
2652
+ _this.id = id;
2653
+ _this.state = exports.PresenceCounterState.Closed;
2654
+ _this.lastCount = 0;
2655
+ _this.connect = null;
2656
+ _this.boundHandleMessage = _this.handleMessage.bind(_this);
2657
+ _this.boundHandleTimeout = _this.handleTimeout.bind(_this);
2658
+ return _this;
2659
+ }
2660
+ PresenceCounterImpl.prototype.init = function () {
2661
+ return __awaiter(this, void 0, void 0, function () {
2662
+ var _a;
2663
+ return __generator(this, function (_b) {
2664
+ switch (_b.label) {
2665
+ case 0:
2666
+ _a = this;
2667
+ return [4 /*yield*/, getConnect(this.host)];
2668
+ case 1:
2669
+ _a.connect = _b.sent();
2670
+ this.connect.on('message', this.boundHandleMessage);
2671
+ return [2 /*return*/];
2672
+ }
2673
+ });
2674
+ });
2675
+ };
2676
+ Object.defineProperty(PresenceCounterImpl.prototype, "isOpened", {
2677
+ get: function () {
2678
+ return this.state === exports.PresenceCounterState.Opened;
2679
+ },
2680
+ enumerable: false,
2681
+ configurable: true
2682
+ });
2683
+ PresenceCounterImpl.prototype.handleMessage = function (message) {
2684
+ return __awaiter(this, void 0, void 0, function () {
2685
+ var id, klass, data, subsData;
2686
+ return __generator(this, function (_a) {
2687
+ id = message.id, klass = message.klass, data = message.data;
2688
+ if (id !== this.id || klass !== exports.Klass.SubsCounter) {
2689
+ return [2 /*return*/];
2690
+ }
2691
+ try {
2692
+ subsData = JSON.parse(data[0]);
2693
+ this.handleCounterUpdate(subsData.counter);
2694
+ this.resetTimeout(subsData.next_update_at);
2695
+ }
2696
+ catch (e) {
2697
+ logger.warn("Couldn't parse subscounter message.");
2698
+ }
2699
+ return [2 /*return*/];
2700
+ });
2701
+ });
2702
+ };
2703
+ PresenceCounterImpl.prototype.handleCounterUpdate = function (count) {
2704
+ if (count < 0) {
2705
+ return;
2706
+ }
2707
+ var shouldEmitUpdated = false;
2708
+ var shouldEmitState = false;
2709
+ if (this.lastCount !== count) {
2710
+ shouldEmitUpdated = true;
2711
+ this.lastCount = count;
2712
+ }
2713
+ if (this.state === exports.PresenceCounterState.Closed) {
2714
+ shouldEmitState = true;
2715
+ this.state = exports.PresenceCounterState.Opened;
2716
+ }
2717
+ if (shouldEmitUpdated) {
2718
+ this.emit('updated', this.lastCount);
2719
+ }
2720
+ if (shouldEmitState) {
2721
+ this.emit('state', exports.PresenceCounterState.Opened);
2722
+ }
2723
+ };
2724
+ PresenceCounterImpl.prototype.handleTimeout = function () {
2725
+ this.state = exports.PresenceCounterState.Closed;
2726
+ this.emit('state', exports.PresenceCounterState.Closed);
2727
+ };
2728
+ PresenceCounterImpl.prototype.resetTimeout = function (nextUpdateAt) {
2729
+ clearTimeout(this.closeTimeout);
2730
+ this.closeTimeout = setTimeout(this.boundHandleTimeout,
2731
+ // because of the time difference between the server and the client,
2732
+ // we need to add 3 seconds to the timeout
2733
+ (nextUpdateAt - sdkUtil.now() + 3) * 1000);
2734
+ };
2735
+ PresenceCounterImpl.prototype.destroy = function () {
2736
+ if (this.connect !== null) {
2737
+ this.connect.off('message', this.boundHandleMessage);
2738
+ }
2739
+ };
2740
+ return PresenceCounterImpl;
2741
+ }(sdkUtil.Emitter));
2742
+
2743
+ /**
2744
+ * @license
2745
+ * @monterosa/sdk-interact-kit
2746
+ *
2747
+ * Copyright © 2025 Monterosa Productions Limited. All rights reserved.
2748
+ *
2749
+ * More details on the license can be found at https://www.monterosa.co/sdk/license
2750
+ */
2751
+ var presenceCounters = new Map();
2752
+ var getPresenceCounterMemoized = sdkUtil.memoizePromise(function (host, id) { return __awaiter(void 0, void 0, void 0, function () {
2753
+ var presenceCounter;
2754
+ return __generator(this, function (_a) {
2755
+ switch (_a.label) {
2756
+ case 0:
2757
+ if (presenceCounters.has(id)) {
2758
+ return [2 /*return*/, presenceCounters.get(id)];
2759
+ }
2760
+ presenceCounter = new PresenceCounterImpl(host, id);
2761
+ return [4 /*yield*/, presenceCounter.init()];
2762
+ case 1:
2763
+ _a.sent();
2764
+ presenceCounters.set(id, presenceCounter);
2765
+ return [2 /*return*/, presenceCounter];
2766
+ }
2767
+ });
2768
+ }); }, function (_, id) { return id; });
2769
+ function getPresenceCounter(project) {
2770
+ return __awaiter(this, void 0, void 0, function () {
2771
+ return __generator(this, function (_a) {
2772
+ switch (_a.label) {
2773
+ case 0:
2774
+ if (!(project === undefined)) return [3 /*break*/, 2];
2775
+ return [4 /*yield*/, getProject()];
2776
+ case 1:
2777
+ project = _a.sent();
2778
+ _a.label = 2;
2779
+ case 2: return [2 /*return*/, getPresenceCounterMemoized(project.context.sdk.options.host, project.id)];
2780
+ }
2781
+ });
2782
+ });
2783
+ }
2784
+ function onPresenceCounterUpdate(presenceCounter, callback) {
2785
+ presenceCounter.on('updated', callback);
2786
+ return function () { return presenceCounter.off('updated', callback); };
2787
+ }
2788
+ function onPresenceCounterOpen(presenceCounter, callback) {
2789
+ var handler = function (state) {
2790
+ if (state === exports.PresenceCounterState.Opened) {
2791
+ callback();
2792
+ }
2793
+ };
2794
+ presenceCounter.on('state', handler);
2795
+ return function () { return presenceCounter.off('state', handler); };
2796
+ }
2797
+ function onPresenceCounterClose(presenceCounter, callback) {
2798
+ var handler = function (state) {
2799
+ if (state === exports.PresenceCounterState.Closed) {
2800
+ callback();
2801
+ }
2802
+ };
2803
+ presenceCounter.on('state', handler);
2804
+ return function () { return presenceCounter.off('state', handler); };
2805
+ }
2806
+
2663
2807
  exports.Answer = Answer;
2664
2808
  exports.ElementImpl = ElementImpl;
2665
2809
  exports.EventImpl = EventImpl;
@@ -2676,6 +2820,7 @@ exports.getEvent = getEvent;
2676
2820
  exports.getEventMemoized = getEventMemoized;
2677
2821
  exports.getEvents = getEvents;
2678
2822
  exports.getEventsMemoized = getEventsMemoized;
2823
+ exports.getPresenceCounter = getPresenceCounter;
2679
2824
  exports.getProject = getProject;
2680
2825
  exports.getProjectMemoized = getProjectMemoized;
2681
2826
  exports.login = login;
@@ -2690,6 +2835,9 @@ exports.onEventPublished = onEventPublished;
2690
2835
  exports.onEventRemoved = onEventRemoved;
2691
2836
  exports.onEventState = onEventState;
2692
2837
  exports.onEventUpdated = onEventUpdated;
2838
+ exports.onPresenceCounterClose = onPresenceCounterClose;
2839
+ exports.onPresenceCounterOpen = onPresenceCounterOpen;
2840
+ exports.onPresenceCounterUpdate = onPresenceCounterUpdate;
2693
2841
  exports.onProjectFieldsUpdated = onProjectFieldsUpdated;
2694
2842
  exports.onProjectListingsUpdated = onProjectListingsUpdated;
2695
2843
  exports.validateAnswer = validateAnswer;