@rimori/client 1.0.5 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/README.md +955 -28
  2. package/dist/components/MarkdownEditor.js +6 -4
  3. package/dist/components/PluginController.d.ts +21 -0
  4. package/dist/components/PluginController.js +116 -0
  5. package/dist/components/ai/Assistant.js +1 -1
  6. package/dist/components/ai/Avatar.d.ts +6 -4
  7. package/dist/components/ai/Avatar.js +14 -6
  8. package/dist/components/ai/EmbeddedAssistent/AudioInputField.js +1 -1
  9. package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.d.ts +2 -1
  10. package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.js +36 -15
  11. package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.d.ts +1 -0
  12. package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.js +3 -0
  13. package/dist/components/ai/EmbeddedAssistent/TTS/Player.d.ts +2 -0
  14. package/dist/components/ai/EmbeddedAssistent/TTS/Player.js +5 -0
  15. package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.d.ts +3 -0
  16. package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.js +41 -5
  17. package/dist/components/ai/utils.d.ts +1 -1
  18. package/dist/components.d.ts +1 -0
  19. package/dist/components.js +1 -0
  20. package/dist/controller/AIController.js +2 -1
  21. package/dist/controller/SettingsController.d.ts +15 -15
  22. package/dist/controller/SettingsController.js +15 -16
  23. package/dist/controller/SharedContentController.d.ts +58 -11
  24. package/dist/controller/SharedContentController.js +161 -26
  25. package/dist/controller/SidePluginController.d.ts +1 -12
  26. package/dist/controller/SidePluginController.js +2 -1
  27. package/dist/core/components/ContextMenu.d.ts +10 -0
  28. package/dist/core/components/ContextMenu.js +93 -0
  29. package/dist/core.d.ts +1 -4
  30. package/dist/core.js +1 -4
  31. package/dist/hooks/UseChatHook.d.ts +1 -1
  32. package/dist/index.d.ts +0 -8
  33. package/dist/index.js +0 -8
  34. package/dist/plugin/AccomplishmentHandler.d.ts +38 -0
  35. package/dist/plugin/AccomplishmentHandler.js +108 -0
  36. package/dist/plugin/ContextMenu.d.ts +17 -0
  37. package/dist/plugin/ContextMenu.js +45 -0
  38. package/dist/plugin/PluginController.js +6 -3
  39. package/dist/plugin/RimoriClient.d.ts +92 -65
  40. package/dist/plugin/RimoriClient.js +105 -75
  41. package/dist/plugin/ThemeSetter.js +2 -2
  42. package/dist/plugin/fromRimori/EventBus.d.ts +6 -3
  43. package/dist/plugin/fromRimori/EventBus.js +15 -9
  44. package/dist/plugin/fromRimori/PluginTypes.d.ts +48 -0
  45. package/dist/plugin/fromRimori/PluginTypes.js +1 -0
  46. package/dist/providers/PluginController.d.ts +21 -0
  47. package/dist/providers/PluginController.js +116 -0
  48. package/dist/providers/PluginProvider.js +26 -73
  49. package/dist/types/Actions.d.ts +4 -0
  50. package/dist/types/Actions.js +1 -0
  51. package/dist/utils/Language.d.ts +66 -0
  52. package/dist/utils/Language.js +67 -0
  53. package/dist/utils/difficultyConverter.d.ts +1 -0
  54. package/dist/utils/difficultyConverter.js +3 -0
  55. package/dist/worker/WorkerSetup.js +4 -4
  56. package/package.json +2 -3
  57. package/src/components/MarkdownEditor.tsx +78 -76
  58. package/src/components/ai/Assistant.tsx +1 -1
  59. package/src/components/ai/Avatar.tsx +66 -49
  60. package/src/components/ai/EmbeddedAssistent/AudioInputField.tsx +1 -1
  61. package/src/components/ai/EmbeddedAssistent/CircleAudioAvatar.tsx +82 -59
  62. package/src/components/ai/EmbeddedAssistent/TTS/MessageSender.ts +4 -0
  63. package/src/components/ai/EmbeddedAssistent/TTS/Player.ts +6 -0
  64. package/src/components/ai/EmbeddedAssistent/VoiceRecoder.tsx +51 -8
  65. package/src/components/ai/utils.ts +1 -1
  66. package/src/components.ts +2 -1
  67. package/src/controller/AIController.ts +2 -1
  68. package/src/controller/SettingsController.ts +83 -84
  69. package/src/controller/SharedContentController.ts +214 -53
  70. package/src/controller/SidePluginController.ts +3 -14
  71. package/src/core/components/ContextMenu.tsx +123 -0
  72. package/src/core.ts +1 -4
  73. package/src/hooks/UseChatHook.ts +17 -17
  74. package/src/index.ts +0 -8
  75. package/src/plugin/AccomplishmentHandler.ts +165 -0
  76. package/src/plugin/PluginController.ts +105 -103
  77. package/src/plugin/RimoriClient.ts +267 -250
  78. package/src/plugin/ThemeSetter.ts +2 -2
  79. package/src/plugin/fromRimori/EventBus.ts +23 -12
  80. package/src/plugin/fromRimori/PluginTypes.ts +64 -0
  81. package/src/providers/PluginProvider.tsx +63 -110
  82. package/src/types/Actions.ts +6 -0
  83. package/src/utils/Language.ts +70 -0
  84. package/src/utils/difficultyConverter.ts +4 -0
  85. package/src/worker/WorkerSetup.ts +4 -4
  86. package/dist/components/avatar/Assistant.d.ts +0 -9
  87. package/dist/components/avatar/Assistant.js +0 -59
  88. package/dist/components/avatar/Avatar.d.ts +0 -12
  89. package/dist/components/avatar/Avatar.js +0 -42
  90. package/dist/components/avatar/EmbeddedAssistent/AudioInputField.d.ts +0 -7
  91. package/dist/components/avatar/EmbeddedAssistent/AudioInputField.js +0 -38
  92. package/dist/components/avatar/EmbeddedAssistent/CircleAudioAvatar.d.ts +0 -7
  93. package/dist/components/avatar/EmbeddedAssistent/CircleAudioAvatar.js +0 -59
  94. package/dist/components/avatar/EmbeddedAssistent/TTS/MessageSender.d.ts +0 -19
  95. package/dist/components/avatar/EmbeddedAssistent/TTS/MessageSender.js +0 -84
  96. package/dist/components/avatar/EmbeddedAssistent/TTS/Player.d.ts +0 -25
  97. package/dist/components/avatar/EmbeddedAssistent/TTS/Player.js +0 -180
  98. package/dist/components/avatar/EmbeddedAssistent/VoiceRecoder.d.ts +0 -7
  99. package/dist/components/avatar/EmbeddedAssistent/VoiceRecoder.js +0 -45
  100. package/dist/components/avatar/utils.d.ts +0 -6
  101. package/dist/components/avatar/utils.js +0 -14
@@ -11,7 +11,7 @@ export class EventBusHandler {
11
11
  constructor() {
12
12
  this.listeners = new Map();
13
13
  this.responseResolvers = new Map();
14
- this.debugEnabled = false;
14
+ this.debugEnabled = true;
15
15
  this.evName = "";
16
16
  //private constructor
17
17
  }
@@ -93,7 +93,8 @@ export class EventBusHandler {
93
93
  * @returns The ids of the listeners.
94
94
  */
95
95
  on(topics, handler, ignoreSender = []) {
96
- return this.toArray(topics).map(topic => {
96
+ const ids = this.toArray(topics).map(topic => {
97
+ this.logIfDebug(`Subscribing to ` + topic, { ignoreSender });
97
98
  if (!this.validateTopic(topic)) {
98
99
  this.logAndThrowError(true, `Invalid topic: ` + topic);
99
100
  }
@@ -107,6 +108,9 @@ export class EventBusHandler {
107
108
  this.logIfDebug(`Subscribed to ` + topic, { listenerId: id, ignoreSender });
108
109
  return btoa(JSON.stringify({ topic, id }));
109
110
  });
111
+ return {
112
+ off: () => this.off(ids)
113
+ };
110
114
  }
111
115
  /**
112
116
  * Subscribes to an event, processes the data and emits a response on the event bus.
@@ -116,12 +120,14 @@ export class EventBusHandler {
116
120
  * @returns The ids of the listeners.
117
121
  */
118
122
  respond(sender, topic, handler) {
119
- const ids = this.on(topic, (data) => __awaiter(this, void 0, void 0, function* () {
123
+ const listener = this.on(topic, (data) => __awaiter(this, void 0, void 0, function* () {
120
124
  const response = typeof handler === "function" ? yield handler(data) : handler;
121
125
  this.emit(sender, topic, response, data.eventId);
122
126
  }), [sender]);
123
- this.logIfDebug(`Added respond listener ` + sender + " to topic " + topic, { listenerIds: ids, sender });
124
- return ids;
127
+ this.logIfDebug(`Added respond listener ` + sender + " to topic " + topic, { listener, sender });
128
+ return {
129
+ off: () => listener.off()
130
+ };
125
131
  }
126
132
  /**
127
133
  * Subscribes to an event on the event bus. The handler will be called once and then removed.
@@ -133,13 +139,13 @@ export class EventBusHandler {
133
139
  this.logAndThrowError(false, `Invalid topic: ` + topic);
134
140
  return;
135
141
  }
136
- let ids = [];
142
+ let listener;
137
143
  const wrapper = (event) => {
138
144
  handler(event);
139
- this.off(ids);
145
+ listener === null || listener === void 0 ? void 0 : listener.off();
140
146
  };
141
- ids = this.on(topic, wrapper);
142
- this.logIfDebug(`Added once listener ` + topic, { listenerIds: ids, topic });
147
+ listener = this.on(topic, wrapper);
148
+ this.logIfDebug(`Added once listener ` + topic, { listener, topic });
143
149
  }
144
150
  /**
145
151
  * Unsubscribes from an event on the event bus.
@@ -0,0 +1,48 @@
1
+ export interface Plugin {
2
+ id: string;
3
+ title: string;
4
+ description: string;
5
+ icon_url: string;
6
+ version: string;
7
+ endpoint: string;
8
+ context_menu_actions: MenuEntry[];
9
+ plugin_pages: PluginPage[];
10
+ sidebar_pages: SidebarPage[];
11
+ settings_page: string;
12
+ worker?: {
13
+ url: string;
14
+ topics?: string[];
15
+ };
16
+ }
17
+ export interface PluginPage {
18
+ name: string;
19
+ url: string;
20
+ show: boolean;
21
+ description: string;
22
+ root: string;
23
+ action?: (Record<string, string> & {
24
+ key: string;
25
+ });
26
+ }
27
+ export interface SidebarPage {
28
+ name: string;
29
+ url: string;
30
+ iconUrl: string;
31
+ description: string;
32
+ actionKey: string;
33
+ }
34
+ export interface MenuEntry {
35
+ text: string;
36
+ pluginId: string;
37
+ actionKey: string;
38
+ icon?: React.ReactNode;
39
+ }
40
+ export type MainPanelAction = {
41
+ pluginId: string;
42
+ actionKey: string;
43
+ } & Record<string, string>;
44
+ export interface ContextMenuAction {
45
+ text: string;
46
+ pluginId: string;
47
+ actionKey: string;
48
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,21 @@
1
+ import { SupabaseClient } from '@supabase/supabase-js';
2
+ import { RimoriClient } from "../plugin/RimoriClient";
3
+ export declare class PluginController {
4
+ private static client;
5
+ private static instance;
6
+ private communicationSecret;
7
+ private supabase;
8
+ private supabaseInfo;
9
+ private pluginId;
10
+ private constructor();
11
+ static getInstance(sender: string): Promise<RimoriClient>;
12
+ private getSecret;
13
+ getClient(): Promise<{
14
+ supabase: SupabaseClient;
15
+ tablePrefix: string;
16
+ pluginId: string;
17
+ }>;
18
+ getToken(): Promise<string>;
19
+ getSupabaseUrl(): string;
20
+ getGlobalEventTopic(preliminaryTopic: string): string;
21
+ }
@@ -0,0 +1,116 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { createClient } from '@supabase/supabase-js';
11
+ import { EventBus } from '../plugin/fromRimori/EventBus';
12
+ import { RimoriClient } from "../plugin/RimoriClient";
13
+ import { setTheme } from '../plugin/ThemeSetter';
14
+ export class PluginController {
15
+ constructor(pluginId) {
16
+ this.communicationSecret = null;
17
+ this.supabase = null;
18
+ this.supabaseInfo = null;
19
+ this.pluginId = pluginId;
20
+ this.getClient = this.getClient.bind(this);
21
+ if (typeof WorkerGlobalScope === 'undefined') {
22
+ setTheme();
23
+ }
24
+ window.addEventListener("message", (event) => {
25
+ // console.log("client: message received", event);
26
+ const { topic, sender, data, eventId } = event.data.event;
27
+ // skip forwarding messages from own plugin
28
+ if (sender === pluginId)
29
+ return;
30
+ EventBus.emit(sender, topic, data, eventId);
31
+ });
32
+ EventBus.on("*", (event) => {
33
+ // skip messages which are not from the own plugin
34
+ if (event.sender !== this.pluginId)
35
+ return;
36
+ if (event.topic.startsWith("self."))
37
+ return;
38
+ window.parent.postMessage({ event, secret: this.getSecret() }, "*");
39
+ });
40
+ }
41
+ static getInstance(sender) {
42
+ return __awaiter(this, void 0, void 0, function* () {
43
+ if (!PluginController.instance) {
44
+ PluginController.instance = new PluginController(sender);
45
+ PluginController.client = yield RimoriClient.getInstance(PluginController.instance);
46
+ }
47
+ return PluginController.client;
48
+ });
49
+ }
50
+ getSecret() {
51
+ if (!this.communicationSecret) {
52
+ const secret = new URLSearchParams(window.location.search).get("secret");
53
+ if (!secret) {
54
+ throw new Error("Communication secret not found in URL as query parameter");
55
+ }
56
+ this.communicationSecret = secret;
57
+ }
58
+ return this.communicationSecret;
59
+ }
60
+ getClient() {
61
+ return __awaiter(this, void 0, void 0, function* () {
62
+ if (this.supabase &&
63
+ this.supabaseInfo &&
64
+ this.supabaseInfo.expiration > new Date()) {
65
+ return { supabase: this.supabase, tablePrefix: this.supabaseInfo.tablePrefix, pluginId: this.supabaseInfo.pluginId };
66
+ }
67
+ const { data } = yield EventBus.request(this.pluginId, "global.supabase.requestAccess");
68
+ this.supabaseInfo = data;
69
+ this.supabase = createClient(this.supabaseInfo.url, this.supabaseInfo.key, {
70
+ accessToken: () => Promise.resolve(this.getToken())
71
+ });
72
+ return { supabase: this.supabase, tablePrefix: this.supabaseInfo.tablePrefix, pluginId: this.supabaseInfo.pluginId };
73
+ });
74
+ }
75
+ getToken() {
76
+ return __awaiter(this, void 0, void 0, function* () {
77
+ if (this.supabaseInfo && this.supabaseInfo.expiration && this.supabaseInfo.expiration > new Date()) {
78
+ return this.supabaseInfo.token;
79
+ }
80
+ const { data } = yield EventBus.request(this.pluginId, "global.supabase.requestAccess");
81
+ if (!this.supabaseInfo) {
82
+ throw new Error("Supabase info not found");
83
+ }
84
+ this.supabaseInfo.token = data.token;
85
+ this.supabaseInfo.expiration = data.expiration;
86
+ return this.supabaseInfo.token;
87
+ });
88
+ }
89
+ getSupabaseUrl() {
90
+ if (!this.supabaseInfo) {
91
+ throw new Error("Supabase info not found");
92
+ }
93
+ return this.supabaseInfo.url;
94
+ }
95
+ getGlobalEventTopic(preliminaryTopic) {
96
+ var _a, _b;
97
+ if (preliminaryTopic.startsWith("global.")) {
98
+ return preliminaryTopic;
99
+ }
100
+ if (preliminaryTopic.startsWith("self.")) {
101
+ return preliminaryTopic;
102
+ }
103
+ const topicParts = preliminaryTopic.split(".");
104
+ if (topicParts.length === 3) {
105
+ if (!topicParts[0].startsWith("pl") && topicParts[0] !== "global") {
106
+ throw new Error("The event topic must start with the plugin id or 'global'.");
107
+ }
108
+ return preliminaryTopic;
109
+ }
110
+ else if (topicParts.length > 3) {
111
+ throw new Error(`The event topic must consist of 3 parts. <pluginId>.<topic area>.<action>. Received: ${preliminaryTopic}`);
112
+ }
113
+ const topicRoot = (_b = (_a = this.supabaseInfo) === null || _a === void 0 ? void 0 : _a.pluginId) !== null && _b !== void 0 ? _b : "global";
114
+ return `${topicRoot}.${preliminaryTopic}`;
115
+ }
116
+ }
@@ -1,33 +1,34 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { createContext, useContext, useEffect, useState } from 'react';
3
3
  import { PluginController } from '../plugin/PluginController';
4
4
  import { EventBusHandler } from '../plugin/fromRimori/EventBus';
5
- EventBusHandler.getInstance("Plugin EventBus");
5
+ import ContextMenu from '../core/components/ContextMenu';
6
6
  const PluginContext = createContext(null);
7
7
  export const PluginProvider = ({ children, pluginId }) => {
8
8
  const [plugin, setPlugin] = useState(null);
9
- const [contextMenuOnSelect, setContextMenuOnTextSelection] = useState(false);
10
- //route change
9
+ initEventBus(pluginId);
11
10
  useEffect(() => {
12
- let lastHash = window.location.hash;
13
- setInterval(() => {
14
- if (lastHash !== window.location.hash) {
15
- lastHash = window.location.hash;
16
- console.log('url changed:', lastHash);
17
- plugin === null || plugin === void 0 ? void 0 : plugin.event.emit('session.triggerUrlChange', window.location.hash);
18
- }
19
- }, 100);
20
11
  PluginController.getInstance(pluginId).then(setPlugin);
21
- }, []);
22
- //check if context menu opens on text selection
12
+ }, [pluginId]);
13
+ //route change
23
14
  useEffect(() => {
24
15
  if (!plugin)
25
16
  return;
26
- plugin.plugin.getUserInfo().then((userInfo) => {
27
- setContextMenuOnTextSelection(userInfo.contextMenuOnSelect);
28
- }).catch(error => {
29
- console.error('Error fetching settings:', error);
30
- });
17
+ const url = new URL(window.location.href);
18
+ //sidebar pages should not report url changes
19
+ if (url.searchParams.get("applicationMode") === "sidebar")
20
+ return;
21
+ let lastHash = url.hash;
22
+ const emitUrlChange = (url) => plugin.event.emit('session.triggerUrlChange', { url });
23
+ const interval = setInterval(() => {
24
+ if (lastHash === window.location.hash)
25
+ return;
26
+ lastHash = window.location.hash;
27
+ // console.log('url changed:', lastHash);
28
+ emitUrlChange(lastHash);
29
+ }, 1000);
30
+ emitUrlChange(lastHash);
31
+ return () => clearInterval(interval);
31
32
  }, [plugin]);
32
33
  //detect page height change
33
34
  useEffect(() => {
@@ -37,63 +38,10 @@ export const PluginProvider = ({ children, pluginId }) => {
37
38
  handleResize();
38
39
  return () => body.removeEventListener('resize', handleResize);
39
40
  }, [plugin]);
40
- //context menu
41
- useEffect(() => {
42
- let lastMouseX = 0;
43
- let lastMouseY = 0;
44
- let isSelecting = false;
45
- // Track mouse position
46
- const handleMouseMove = (e) => {
47
- lastMouseX = e.clientX;
48
- lastMouseY = e.clientY;
49
- };
50
- const handleContextMenu = (e) => {
51
- var _a;
52
- const selection = (_a = window.getSelection()) === null || _a === void 0 ? void 0 : _a.toString().trim();
53
- if (selection) {
54
- e.preventDefault();
55
- // console.log('context menu handled', selection);
56
- plugin === null || plugin === void 0 ? void 0 : plugin.event.emit('global.contextMenu.trigger', { text: selection, x: e.clientX, y: e.clientY, open: true });
57
- }
58
- };
59
- const handleSelectionChange = () => {
60
- var _a;
61
- // if (triggerOnTextSelection) {
62
- const selection = (_a = window.getSelection()) === null || _a === void 0 ? void 0 : _a.toString().trim();
63
- const open = !!selection && isSelecting;
64
- // console.log('Selection change, contextMenuOnSelect:', contextMenuOnSelect);
65
- plugin === null || plugin === void 0 ? void 0 : plugin.event.emit('global.contextMenu.trigger', { text: selection, x: lastMouseX, y: lastMouseY, open });
66
- // }
67
- };
68
- const handleMouseUpDown = (e) => {
69
- if (e.type === 'mousedown') {
70
- isSelecting = false;
71
- }
72
- else if (e.type === 'mouseup') {
73
- isSelecting = true;
74
- // console.log('mouseup, contextMenuOnSelect:', contextMenuOnSelect);
75
- if (contextMenuOnSelect) {
76
- handleSelectionChange();
77
- }
78
- }
79
- };
80
- document.addEventListener('contextmenu', handleContextMenu);
81
- document.addEventListener('selectionchange', handleSelectionChange);
82
- document.addEventListener("mousemove", handleMouseMove);
83
- document.addEventListener('mousedown', handleMouseUpDown);
84
- document.addEventListener('mouseup', handleMouseUpDown);
85
- return () => {
86
- document.removeEventListener("mousemove", handleMouseMove);
87
- document.removeEventListener('contextmenu', handleContextMenu);
88
- document.removeEventListener('selectionchange', handleSelectionChange);
89
- document.removeEventListener('mousedown', handleMouseUpDown);
90
- document.removeEventListener('mouseup', handleMouseUpDown);
91
- };
92
- }, [plugin, contextMenuOnSelect]);
93
41
  if (!plugin) {
94
42
  return "";
95
43
  }
96
- return (_jsx(PluginContext.Provider, { value: plugin, children: children }));
44
+ return (_jsxs(PluginContext.Provider, { value: plugin, children: [_jsx(ContextMenu, { client: plugin }), children] }));
97
45
  };
98
46
  export const usePlugin = () => {
99
47
  const context = useContext(PluginContext);
@@ -102,3 +50,8 @@ export const usePlugin = () => {
102
50
  }
103
51
  return context;
104
52
  };
53
+ function initEventBus(pluginId) {
54
+ const url = new URL(window.location.href);
55
+ const isSidebar = url.searchParams.get("applicationMode") === "sidebar";
56
+ EventBusHandler.getInstance("Plugin EventBus " + pluginId + " " + (isSidebar ? "sidebar" : "main"));
57
+ }
@@ -0,0 +1,4 @@
1
+ export type MainPanelAction = {
2
+ pluginId: string;
3
+ actionKey: string;
4
+ } & Record<string, string>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,66 @@
1
+ export declare const languageKeys: {
2
+ readonly sq: "albanian";
3
+ readonly ar: "arabic";
4
+ readonly hy: "armenian";
5
+ readonly az: "azerbaijani";
6
+ readonly bn: "bengali";
7
+ readonly bs: "bosnian";
8
+ readonly bg: "bulgarian";
9
+ readonly ca: "catalan";
10
+ readonly zh: "chinese";
11
+ readonly hr: "croatian";
12
+ readonly cs: "czech";
13
+ readonly da: "danish";
14
+ readonly nl: "dutch";
15
+ readonly en: "english";
16
+ readonly et: "estonian";
17
+ readonly fi: "finnish";
18
+ readonly fr: "french";
19
+ readonly gl: "galician";
20
+ readonly de: "german";
21
+ readonly el: "greek";
22
+ readonly he: "hebrew";
23
+ readonly hi: "hindi";
24
+ readonly hu: "hungarian";
25
+ readonly is: "icelandic";
26
+ readonly id: "indonesian";
27
+ readonly it: "italian";
28
+ readonly ja: "japanese";
29
+ readonly kn: "kannada";
30
+ readonly kk: "kazakh";
31
+ readonly ko: "korean";
32
+ readonly lv: "latvian";
33
+ readonly lt: "lithuanian";
34
+ readonly mk: "macedonian";
35
+ readonly ms: "malay";
36
+ readonly mr: "marathi";
37
+ readonly mi: "maori";
38
+ readonly ne: "nepali";
39
+ readonly no: "norwegian";
40
+ readonly fa: "persian";
41
+ readonly pl: "polish";
42
+ readonly pt: "portuguese";
43
+ readonly ro: "romanian";
44
+ readonly ru: "russian";
45
+ readonly sr: "serbian";
46
+ readonly sk: "slovak";
47
+ readonly sl: "slovenian";
48
+ readonly es: "spanish";
49
+ readonly sw: "swahili";
50
+ readonly sv: "swedish";
51
+ readonly tl: "filipino";
52
+ readonly ta: "tamil";
53
+ readonly th: "thai";
54
+ readonly tr: "turkish";
55
+ readonly uk: "ukrainian";
56
+ readonly ur: "urdu";
57
+ readonly vi: "vietnamese";
58
+ readonly cy: "welsh";
59
+ };
60
+ export type Language = keyof typeof languageKeys;
61
+ /**
62
+ * Get the language name from the language code
63
+ * @param languageCode The code of the language
64
+ * @returns The language name
65
+ */
66
+ export declare function getLanguageName(languageCode: Language): string;
@@ -0,0 +1,67 @@
1
+ export const languageKeys = {
2
+ sq: "albanian",
3
+ ar: "arabic",
4
+ hy: "armenian",
5
+ az: "azerbaijani",
6
+ bn: "bengali",
7
+ bs: "bosnian",
8
+ bg: "bulgarian",
9
+ ca: "catalan",
10
+ zh: "chinese",
11
+ hr: "croatian",
12
+ cs: "czech",
13
+ da: "danish",
14
+ nl: "dutch",
15
+ en: "english",
16
+ et: "estonian",
17
+ fi: "finnish",
18
+ fr: "french",
19
+ gl: "galician",
20
+ de: "german",
21
+ el: "greek",
22
+ he: "hebrew",
23
+ hi: "hindi",
24
+ hu: "hungarian",
25
+ is: "icelandic",
26
+ id: "indonesian",
27
+ it: "italian",
28
+ ja: "japanese",
29
+ kn: "kannada",
30
+ kk: "kazakh",
31
+ ko: "korean",
32
+ lv: "latvian",
33
+ lt: "lithuanian",
34
+ mk: "macedonian",
35
+ ms: "malay",
36
+ mr: "marathi",
37
+ mi: "maori",
38
+ ne: "nepali",
39
+ no: "norwegian",
40
+ fa: "persian",
41
+ pl: "polish",
42
+ pt: "portuguese",
43
+ ro: "romanian",
44
+ ru: "russian",
45
+ sr: "serbian",
46
+ sk: "slovak",
47
+ sl: "slovenian",
48
+ es: "spanish",
49
+ sw: "swahili",
50
+ sv: "swedish",
51
+ tl: "filipino",
52
+ ta: "tamil",
53
+ th: "thai",
54
+ tr: "turkish",
55
+ uk: "ukrainian",
56
+ ur: "urdu",
57
+ vi: "vietnamese",
58
+ cy: "welsh"
59
+ };
60
+ /**
61
+ * Get the language name from the language code
62
+ * @param languageCode The code of the language
63
+ * @returns The language name
64
+ */
65
+ export function getLanguageName(languageCode) {
66
+ return languageKeys[languageCode];
67
+ }
@@ -1,3 +1,4 @@
1
1
  export type LanguageLevel = "Pre-A1" | "A1" | "A2" | "B1" | "B2" | "C1" | "C2" | "Post-C2";
2
2
  export declare function getDifficultyLevel(difficulty: LanguageLevel): number;
3
3
  export declare function getDifficultyLabel(difficulty: number): LanguageLevel;
4
+ export declare function getNeighborDifficultyLevel(difficulty: LanguageLevel, difficultyAdjustment: number): LanguageLevel;
@@ -5,3 +5,6 @@ export function getDifficultyLevel(difficulty) {
5
5
  export function getDifficultyLabel(difficulty) {
6
6
  return codes[difficulty];
7
7
  }
8
+ export function getNeighborDifficultyLevel(difficulty, difficultyAdjustment) {
9
+ return getDifficultyLabel(getDifficultyLevel(difficulty) + difficultyAdjustment);
10
+ }
@@ -25,7 +25,7 @@ export function setupWorker(init) {
25
25
  postMessage: (message) => {
26
26
  message.event.sender = "worker." + message.event.sender;
27
27
  checkDebugMode(message.event);
28
- logIfDebug('[Worker] sending event to Rimori', message.event);
28
+ logIfDebug('sending event to Rimori', message.event);
29
29
  self.postMessage(message);
30
30
  }
31
31
  },
@@ -43,16 +43,16 @@ export function setupWorker(init) {
43
43
  // Handle init message from Rimori.
44
44
  self.onmessage = (response) => __awaiter(this, void 0, void 0, function* () {
45
45
  checkDebugMode(response.data);
46
- logIfDebug('[Worker] message received', response.data);
46
+ logIfDebug('Message received', response.data);
47
47
  const event = response.data;
48
48
  if (event.topic === 'global.worker.requestInit') {
49
49
  if (!controller) {
50
50
  mockWindow.APP_CONFIG.SUPABASE_URL = event.data.supabaseUrl;
51
51
  mockWindow.APP_CONFIG.SUPABASE_ANON_KEY = event.data.supabaseAnonKey;
52
52
  controller = yield PluginController.getInstance(event.data.pluginId);
53
- logIfDebug('[Worker] Worker initialized.');
53
+ logIfDebug('Worker initialized.');
54
54
  yield init(controller);
55
- logIfDebug('[Worker] Plugin listeners initialized.');
55
+ logIfDebug('Plugin listeners initialized.');
56
56
  }
57
57
  const initEvent = {
58
58
  timestamp: new Date().toISOString(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rimori/client",
3
- "version": "1.0.5",
3
+ "version": "1.1.1",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "exports": {
@@ -19,7 +19,7 @@
19
19
  },
20
20
  "scripts": {
21
21
  "build": "tsc && sass src/style.scss:dist/style.css",
22
- "dev": "tsc -w",
22
+ "dev": "tsc -w --preserveWatchOutput",
23
23
  "css-dev": "sass --watch src/style.scss:dist/style.css"
24
24
  },
25
25
  "peerDependencies": {
@@ -30,7 +30,6 @@
30
30
  "@supabase/supabase-js": "^2.48.1",
31
31
  "@tiptap/react": "2.10.3",
32
32
  "@tiptap/starter-kit": "2.10.3",
33
- "uuid": "11.1.0",
34
33
  "react-icons": "^5.4.0",
35
34
  "react-markdown": "^10.1.0",
36
35
  "tiptap-markdown": "^0.8.10",