@rimori/client 2.3.0-next.6 → 2.3.0-next.8

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/README.md CHANGED
@@ -155,7 +155,7 @@ Use `client.runtime.fetchBackend` for authenticated calls to Rimori-managed HTTP
155
155
  - `on(topic, handler)` / `once(topic, handler)` / `respond(topic, handler)` – subscribe and reply (each call returns an object with `off()` for cleanup).
156
156
  - `emitAccomplishment(payload)` / `onAccomplishment(topic, handler)` – report learning milestones.
157
157
  - `emitSidebarAction(pluginId, actionKey, text?)` – trigger sidebar plugins.
158
- - `onMainPanelAction(handler, actionsToListen?)` – react to dashboard actions.
158
+ - `onMainPanelAction(handler, actionsToListen?)` – react to dashboard actions. Returns an `EventListener` with an `off()` method. **Important:** Call `listener.off()` when your component unmounts or when you no longer need to listen, especially to prevent the event from firing again when navigating away from or returning to the page.
159
159
  - `client.navigation.toDashboard()` – navigate the user back to Rimori.
160
160
 
161
161
  ### Community Content
@@ -5,7 +5,7 @@ import { ObjectRequest } from '../controller/ObjectController';
5
5
  import { UserInfo } from '../controller/SettingsController';
6
6
  import { SharedContent, SharedContentFilter, SharedContentObjectRequest } from '../controller/SharedContentController';
7
7
  import { CreateExerciseParams } from '../controller/ExerciseController';
8
- import { EventBusMessage, EventHandler, EventPayload } from '../fromRimori/EventBus';
8
+ import { EventBusMessage, EventHandler, EventPayload, EventListener } from '../fromRimori/EventBus';
9
9
  import { ActivePlugin, MainPanelAction, Plugin, Tool } from '../fromRimori/PluginTypes';
10
10
  import { AccomplishmentPayload } from '../controller/AccomplishmentController';
11
11
  import { Translator } from '../controller/TranslationController';
@@ -112,7 +112,7 @@ export declare class RimoriClient {
112
112
  * @param callback The callback to call when the event is emitted.
113
113
  * @returns An EventListener object containing an off() method to unsubscribe the listeners.
114
114
  */
115
- on: <T = EventPayload>(topic: string | string[], callback: EventHandler<T>) => import("../fromRimori/EventBus").EventListener;
115
+ on: <T = EventPayload>(topic: string | string[], callback: EventHandler<T>) => EventListener;
116
116
  /**
117
117
  * Subscribe to an event once.
118
118
  * @param topic The topic to subscribe to.
@@ -143,8 +143,31 @@ export declare class RimoriClient {
143
143
  * @param text Optional text to be used for the action like for example text that the translator would look up.
144
144
  */
145
145
  emitSidebarAction: (pluginId: string, actionKey: string, text?: string) => void;
146
- onMainPanelAction: (callback: (data: MainPanelAction) => void, actionsToListen?: string | string[]) => void;
147
- onSidePanelAction: (callback: (data: MainPanelAction) => void, actionsToListen?: string | string[]) => void;
146
+ /**
147
+ * Subscribe to main panel actions triggered by the user from the dashboard.
148
+ * @param callback Handler function that receives the action data when a matching action is triggered.
149
+ * @param actionsToListen Optional filter to listen only to specific action keys. If empty or not provided, all actions will trigger the callback.
150
+ * @returns An EventListener object with an `off()` method for cleanup.
151
+ *
152
+ * @example
153
+ * ```ts
154
+ * const listener = client.event.onMainPanelAction((data) => {
155
+ * console.log('Action received:', data.action_key);
156
+ * }, ['startSession', 'pauseSession']);
157
+ *
158
+ * // Clean up when component unmounts to prevent events from firing
159
+ * // when navigating away or returning to the page
160
+ * useEffect(() => {
161
+ * return () => listener.off();
162
+ * }, []);
163
+ * ```
164
+ *
165
+ * **Important:** Always call `listener.off()` when your component unmounts or when you no longer need to listen.
166
+ * This prevents the event handler from firing when navigating away from or returning to the page, which could
167
+ * cause unexpected behavior or duplicate event handling.
168
+ */
169
+ onMainPanelAction: (callback: (data: MainPanelAction) => void, actionsToListen?: string | string[]) => EventListener;
170
+ onSidePanelAction: (callback: (data: MainPanelAction) => void, actionsToListen?: string | string[]) => EventListener;
148
171
  };
149
172
  navigation: {
150
173
  toDashboard: () => void;
@@ -96,11 +96,34 @@ export class RimoriClient {
96
96
  emitSidebarAction: (pluginId, actionKey, text) => {
97
97
  this.event.emit('global.sidebar.triggerAction', { plugin_id: pluginId, action_key: actionKey, text });
98
98
  },
99
+ /**
100
+ * Subscribe to main panel actions triggered by the user from the dashboard.
101
+ * @param callback Handler function that receives the action data when a matching action is triggered.
102
+ * @param actionsToListen Optional filter to listen only to specific action keys. If empty or not provided, all actions will trigger the callback.
103
+ * @returns An EventListener object with an `off()` method for cleanup.
104
+ *
105
+ * @example
106
+ * ```ts
107
+ * const listener = client.event.onMainPanelAction((data) => {
108
+ * console.log('Action received:', data.action_key);
109
+ * }, ['startSession', 'pauseSession']);
110
+ *
111
+ * // Clean up when component unmounts to prevent events from firing
112
+ * // when navigating away or returning to the page
113
+ * useEffect(() => {
114
+ * return () => listener.off();
115
+ * }, []);
116
+ * ```
117
+ *
118
+ * **Important:** Always call `listener.off()` when your component unmounts or when you no longer need to listen.
119
+ * This prevents the event handler from firing when navigating away from or returning to the page, which could
120
+ * cause unexpected behavior or duplicate event handling.
121
+ */
99
122
  onMainPanelAction: (callback, actionsToListen = []) => {
100
123
  const listeningActions = Array.isArray(actionsToListen) ? actionsToListen : [actionsToListen];
101
124
  // this needs to be a emit and on because the main panel action is triggered by the user and not by the plugin
102
125
  this.event.emit('action.requestMain');
103
- this.event.on('action.requestMain', ({ data }) => {
126
+ return this.event.on('action.requestMain', ({ data }) => {
104
127
  // console.log('Received action for main panel ' + data.action_key);
105
128
  // console.log('Listening to actions', listeningActions);
106
129
  if (listeningActions.length === 0 || listeningActions.includes(data.action_key)) {
@@ -112,7 +135,7 @@ export class RimoriClient {
112
135
  const listeningActions = Array.isArray(actionsToListen) ? actionsToListen : [actionsToListen];
113
136
  // this needs to be a emit and on because the main panel action is triggered by the user and not by the plugin
114
137
  this.event.emit('action.requestSidebar');
115
- this.event.on('action.requestSidebar', ({ data }) => {
138
+ return this.event.on('action.requestSidebar', ({ data }) => {
116
139
  // console.log("eventHandler .onSidePanelAction", data);
117
140
  // console.log('Received action for sidebar ' + data.action);
118
141
  // console.log('Listening to actions', listeningActions);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rimori/client",
3
- "version": "2.3.0-next.6",
3
+ "version": "2.3.0-next.8",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "repository": {
@@ -12,7 +12,7 @@ import {
12
12
  } from '../controller/SharedContentController';
13
13
  import { getSTTResponse, getTTSResponse } from '../controller/VoiceController';
14
14
  import { ExerciseController, CreateExerciseParams } from '../controller/ExerciseController';
15
- import { EventBus, EventBusMessage, EventHandler, EventPayload } from '../fromRimori/EventBus';
15
+ import { EventBus, EventBusMessage, EventHandler, EventPayload, EventListener } from '../fromRimori/EventBus';
16
16
  import { ActivePlugin, MainPanelAction, Plugin, Tool } from '../fromRimori/PluginTypes';
17
17
  import { AccomplishmentController, AccomplishmentPayload } from '../controller/AccomplishmentController';
18
18
  import { RimoriCommunicationHandler, RimoriInfo } from './CommunicationHandler';
@@ -201,7 +201,7 @@ export class RimoriClient {
201
201
  * @param callback The callback to call when the event is emitted.
202
202
  * @returns An EventListener object containing an off() method to unsubscribe the listeners.
203
203
  */
204
- on: <T = EventPayload>(topic: string | string[], callback: EventHandler<T>) => {
204
+ on: <T = EventPayload>(topic: string | string[], callback: EventHandler<T>): EventListener => {
205
205
  const topics = Array.isArray(topic) ? topic : [topic];
206
206
  return EventBus.on<T>(
207
207
  topics.map((t) => this.pluginController.getGlobalEventTopic(t)),
@@ -260,11 +260,37 @@ export class RimoriClient {
260
260
  this.event.emit('global.sidebar.triggerAction', { plugin_id: pluginId, action_key: actionKey, text });
261
261
  },
262
262
 
263
- onMainPanelAction: (callback: (data: MainPanelAction) => void, actionsToListen: string | string[] = []) => {
263
+ /**
264
+ * Subscribe to main panel actions triggered by the user from the dashboard.
265
+ * @param callback Handler function that receives the action data when a matching action is triggered.
266
+ * @param actionsToListen Optional filter to listen only to specific action keys. If empty or not provided, all actions will trigger the callback.
267
+ * @returns An EventListener object with an `off()` method for cleanup.
268
+ *
269
+ * @example
270
+ * ```ts
271
+ * const listener = client.event.onMainPanelAction((data) => {
272
+ * console.log('Action received:', data.action_key);
273
+ * }, ['startSession', 'pauseSession']);
274
+ *
275
+ * // Clean up when component unmounts to prevent events from firing
276
+ * // when navigating away or returning to the page
277
+ * useEffect(() => {
278
+ * return () => listener.off();
279
+ * }, []);
280
+ * ```
281
+ *
282
+ * **Important:** Always call `listener.off()` when your component unmounts or when you no longer need to listen.
283
+ * This prevents the event handler from firing when navigating away from or returning to the page, which could
284
+ * cause unexpected behavior or duplicate event handling.
285
+ */
286
+ onMainPanelAction: (
287
+ callback: (data: MainPanelAction) => void,
288
+ actionsToListen: string | string[] = [],
289
+ ): EventListener => {
264
290
  const listeningActions = Array.isArray(actionsToListen) ? actionsToListen : [actionsToListen];
265
291
  // this needs to be a emit and on because the main panel action is triggered by the user and not by the plugin
266
292
  this.event.emit('action.requestMain');
267
- this.event.on<MainPanelAction>('action.requestMain', ({ data }) => {
293
+ return this.event.on<MainPanelAction>('action.requestMain', ({ data }) => {
268
294
  // console.log('Received action for main panel ' + data.action_key);
269
295
  // console.log('Listening to actions', listeningActions);
270
296
  if (listeningActions.length === 0 || listeningActions.includes(data.action_key)) {
@@ -273,11 +299,14 @@ export class RimoriClient {
273
299
  });
274
300
  },
275
301
 
276
- onSidePanelAction: (callback: (data: MainPanelAction) => void, actionsToListen: string | string[] = []) => {
302
+ onSidePanelAction: (
303
+ callback: (data: MainPanelAction) => void,
304
+ actionsToListen: string | string[] = [],
305
+ ): EventListener => {
277
306
  const listeningActions = Array.isArray(actionsToListen) ? actionsToListen : [actionsToListen];
278
307
  // this needs to be a emit and on because the main panel action is triggered by the user and not by the plugin
279
308
  this.event.emit('action.requestSidebar');
280
- this.event.on<MainPanelAction>('action.requestSidebar', ({ data }) => {
309
+ return this.event.on<MainPanelAction>('action.requestSidebar', ({ data }) => {
281
310
  // console.log("eventHandler .onSidePanelAction", data);
282
311
  // console.log('Received action for sidebar ' + data.action);
283
312
  // console.log('Listening to actions', listeningActions);