@rimori/client 1.3.1 → 1.4.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.
Files changed (148) hide show
  1. package/.prettierignore +35 -0
  2. package/README.md +77 -71
  3. package/dist/cli/scripts/init/dev-registration.d.ts +1 -1
  4. package/dist/cli/scripts/init/dev-registration.js +4 -4
  5. package/dist/cli/scripts/init/main.js +1 -1
  6. package/dist/cli/scripts/init/package-setup.d.ts +1 -1
  7. package/dist/cli/scripts/init/package-setup.js +3 -3
  8. package/dist/cli/scripts/init/router-transformer.js +19 -12
  9. package/dist/cli/scripts/init/vite-config.d.ts +2 -2
  10. package/dist/cli/scripts/init/vite-config.js +2 -2
  11. package/dist/cli/scripts/release/release-config-upload.js +9 -9
  12. package/dist/cli/scripts/release/release-db-update.d.ts +1 -1
  13. package/dist/cli/scripts/release/release-db-update.js +9 -9
  14. package/dist/cli/scripts/release/release-file-upload.js +2 -2
  15. package/dist/cli/scripts/release/release.js +2 -2
  16. package/dist/cli/types/DatabaseTypes.d.ts +2 -2
  17. package/dist/components/CRUDModal.d.ts +1 -1
  18. package/dist/components/CRUDModal.js +3 -3
  19. package/dist/components/MarkdownEditor.js +16 -16
  20. package/dist/components/Spinner.js +2 -2
  21. package/dist/components/ai/Assistant.js +7 -8
  22. package/dist/components/ai/Avatar.d.ts +2 -2
  23. package/dist/components/ai/Avatar.js +14 -7
  24. package/dist/components/ai/EmbeddedAssistent/AudioInputField.js +5 -6
  25. package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.d.ts +1 -1
  26. package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.js +1 -2
  27. package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.d.ts +1 -2
  28. package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.js +4 -2
  29. package/dist/components/ai/EmbeddedAssistent/TTS/Player.js +1 -1
  30. package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.js +2 -3
  31. package/dist/components/audio/Playbutton.js +10 -7
  32. package/dist/components/components/ContextMenu.d.ts +1 -1
  33. package/dist/components/components/ContextMenu.js +19 -16
  34. package/dist/components.d.ts +10 -10
  35. package/dist/components.js +10 -10
  36. package/dist/core/controller/AIController.d.ts +2 -2
  37. package/dist/core/controller/AIController.js +20 -18
  38. package/dist/core/controller/ExerciseController.d.ts +52 -0
  39. package/dist/core/controller/ExerciseController.js +73 -0
  40. package/dist/core/controller/ObjectController.js +5 -5
  41. package/dist/core/controller/SettingsController.d.ts +22 -7
  42. package/dist/core/controller/SettingsController.js +73 -8
  43. package/dist/core/controller/SharedContentController.d.ts +3 -3
  44. package/dist/core/controller/SharedContentController.js +38 -20
  45. package/dist/core/controller/VoiceController.js +6 -4
  46. package/dist/core/core.d.ts +15 -14
  47. package/dist/core/core.js +7 -7
  48. package/dist/fromRimori/EventBus.js +23 -23
  49. package/dist/fromRimori/PluginTypes.d.ts +4 -4
  50. package/dist/hooks/UseChatHook.d.ts +3 -3
  51. package/dist/hooks/UseChatHook.js +9 -3
  52. package/dist/index.d.ts +10 -10
  53. package/dist/index.js +9 -9
  54. package/dist/plugin/AccomplishmentHandler.d.ts +5 -5
  55. package/dist/plugin/AccomplishmentHandler.js +31 -27
  56. package/dist/plugin/AudioController.d.ts +1 -1
  57. package/dist/plugin/AudioController.js +6 -6
  58. package/dist/plugin/Logger.d.ts +5 -0
  59. package/dist/plugin/Logger.js +65 -13
  60. package/dist/plugin/PluginController.d.ts +7 -1
  61. package/dist/plugin/PluginController.js +32 -27
  62. package/dist/plugin/RimoriClient.d.ts +39 -14
  63. package/dist/plugin/RimoriClient.js +60 -31
  64. package/dist/plugin/StandaloneClient.d.ts +1 -1
  65. package/dist/plugin/StandaloneClient.js +35 -16
  66. package/dist/plugin/ThemeSetter.js +4 -4
  67. package/dist/providers/PluginProvider.js +44 -14
  68. package/dist/utils/Language.js +57 -57
  69. package/dist/utils/PluginUtils.js +3 -3
  70. package/dist/utils/difficultyConverter.d.ts +1 -1
  71. package/dist/utils/difficultyConverter.js +1 -1
  72. package/dist/utils/endpoint.js +2 -2
  73. package/dist/worker/WorkerSetup.d.ts +1 -1
  74. package/dist/worker/WorkerSetup.js +6 -6
  75. package/eslint.config.js +53 -0
  76. package/example/docs/devdocs.md +50 -40
  77. package/example/docs/overview.md +1 -1
  78. package/example/docs/userdocs.md +4 -1
  79. package/example/rimori.config.ts +51 -49
  80. package/example/worker/vite.config.ts +3 -3
  81. package/example/worker/worker.ts +2 -2
  82. package/package.json +17 -4
  83. package/prettier.config.js +8 -0
  84. package/src/cli/scripts/init/dev-registration.ts +5 -8
  85. package/src/cli/scripts/init/env-setup.ts +1 -1
  86. package/src/cli/scripts/init/file-operations.ts +1 -1
  87. package/src/cli/scripts/init/html-cleaner.ts +2 -5
  88. package/src/cli/scripts/init/main.ts +16 -13
  89. package/src/cli/scripts/init/package-setup.ts +11 -15
  90. package/src/cli/scripts/init/router-transformer.ts +40 -37
  91. package/src/cli/scripts/init/tailwind-config.ts +17 -26
  92. package/src/cli/scripts/init/vite-config.ts +3 -3
  93. package/src/cli/scripts/release/release-config-upload.ts +11 -11
  94. package/src/cli/scripts/release/release-db-update.ts +12 -12
  95. package/src/cli/scripts/release/release-file-upload.ts +3 -3
  96. package/src/cli/scripts/release/release.ts +4 -4
  97. package/src/cli/types/DatabaseTypes.ts +7 -8
  98. package/src/components/CRUDModal.tsx +64 -48
  99. package/src/components/MarkdownEditor.tsx +58 -27
  100. package/src/components/Spinner.tsx +24 -17
  101. package/src/components/ai/Assistant.tsx +70 -70
  102. package/src/components/ai/Avatar.tsx +20 -16
  103. package/src/components/ai/EmbeddedAssistent/AudioInputField.tsx +63 -54
  104. package/src/components/ai/EmbeddedAssistent/CircleAudioAvatar.tsx +14 -5
  105. package/src/components/ai/EmbeddedAssistent/TTS/MessageSender.ts +75 -74
  106. package/src/components/ai/EmbeddedAssistent/TTS/Player.ts +177 -178
  107. package/src/components/ai/EmbeddedAssistent/VoiceRecoder.tsx +109 -94
  108. package/src/components/ai/utils.ts +4 -4
  109. package/src/components/audio/Playbutton.tsx +101 -93
  110. package/src/components/components/ContextMenu.tsx +47 -35
  111. package/src/components.ts +10 -10
  112. package/src/core/controller/AIController.ts +62 -50
  113. package/src/core/controller/ExerciseController.ts +98 -0
  114. package/src/core/controller/ObjectController.ts +15 -10
  115. package/src/core/controller/SettingsController.ts +89 -16
  116. package/src/core/controller/SharedContentController.ts +80 -44
  117. package/src/core/controller/VoiceController.ts +10 -8
  118. package/src/core/core.ts +15 -15
  119. package/src/fromRimori/EventBus.ts +76 -47
  120. package/src/fromRimori/PluginTypes.ts +26 -17
  121. package/src/fromRimori/readme.md +2 -2
  122. package/src/hooks/UseChatHook.ts +25 -15
  123. package/src/index.ts +10 -10
  124. package/src/plugin/AccomplishmentHandler.ts +53 -35
  125. package/src/plugin/AudioController.ts +18 -12
  126. package/src/plugin/Logger.ts +77 -19
  127. package/src/plugin/PluginController.ts +60 -44
  128. package/src/plugin/RimoriClient.ts +133 -69
  129. package/src/plugin/StandaloneClient.ts +51 -24
  130. package/src/plugin/ThemeSetter.ts +5 -5
  131. package/src/providers/PluginProvider.tsx +90 -36
  132. package/src/style.scss +3 -3
  133. package/src/utils/Language.ts +58 -58
  134. package/src/utils/PluginUtils.ts +16 -20
  135. package/src/utils/difficultyConverter.ts +2 -2
  136. package/src/utils/endpoint.ts +3 -2
  137. package/src/worker/WorkerSetup.ts +8 -9
  138. package/tsconfig.json +2 -4
  139. package/dist/components/LoggerExample.d.ts +0 -6
  140. package/dist/components/LoggerExample.js +0 -79
  141. package/dist/core/controller/AudioController.d.ts +0 -0
  142. package/dist/core/controller/AudioController.js +0 -1
  143. package/dist/hooks/UseLogger.d.ts +0 -30
  144. package/dist/hooks/UseLogger.js +0 -122
  145. package/dist/plugin/LoggerExample.d.ts +0 -16
  146. package/dist/plugin/LoggerExample.js +0 -140
  147. package/dist/utils/audioFormats.d.ts +0 -26
  148. package/dist/utils/audioFormats.js +0 -67
@@ -7,13 +7,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { generateText, streamChatGPT } from "../core/controller/AIController";
11
- import { generateObject } from "../core/controller/ObjectController";
12
- import { SettingsController } from "../core/controller/SettingsController";
13
- import { SharedContentController } from "../core/controller/SharedContentController";
14
- import { getSTTResponse, getTTSResponse } from "../core/controller/VoiceController";
15
- import { EventBus } from "../fromRimori/EventBus";
16
- import { AccomplishmentHandler } from "./AccomplishmentHandler";
10
+ import { generateText, streamChatGPT } from '../core/controller/AIController';
11
+ import { generateObject } from '../core/controller/ObjectController';
12
+ import { SettingsController } from '../core/controller/SettingsController';
13
+ import { SharedContentController, } from '../core/controller/SharedContentController';
14
+ import { getSTTResponse, getTTSResponse } from '../core/controller/VoiceController';
15
+ import { ExerciseController } from '../core/controller/ExerciseController';
16
+ import { EventBus } from '../fromRimori/EventBus';
17
+ import { AccomplishmentHandler } from './AccomplishmentHandler';
17
18
  export class RimoriClient {
18
19
  constructor(supabase, info, pluginController) {
19
20
  this.event = {
@@ -49,7 +50,7 @@ export class RimoriClient {
49
50
  */
50
51
  on: (topic, callback) => {
51
52
  const topics = Array.isArray(topic) ? topic : [topic];
52
- return EventBus.on(topics.map(t => this.pluginController.getGlobalEventTopic(t)), callback);
53
+ return EventBus.on(topics.map((t) => this.pluginController.getGlobalEventTopic(t)), callback);
53
54
  },
54
55
  /**
55
56
  * Subscribe to an event once.
@@ -66,7 +67,7 @@ export class RimoriClient {
66
67
  */
67
68
  respond: (topic, data) => {
68
69
  const topics = Array.isArray(topic) ? topic : [topic];
69
- EventBus.respond(this.plugin.pluginId, topics.map(t => this.pluginController.getGlobalEventTopic(t)), data);
70
+ EventBus.respond(this.plugin.pluginId, topics.map((t) => this.pluginController.getGlobalEventTopic(t)), data);
70
71
  },
71
72
  /**
72
73
  * Emit an accomplishment.
@@ -90,18 +91,18 @@ export class RimoriClient {
90
91
  * @param text Optional text to be used for the action like for example text that the translator would look up.
91
92
  */
92
93
  emitSidebarAction: (pluginId, actionKey, text) => {
93
- this.event.emit("global.sidebar.triggerAction", { plugin_id: pluginId, action_key: actionKey, text });
94
+ this.event.emit('global.sidebar.triggerAction', { plugin_id: pluginId, action_key: actionKey, text });
94
95
  },
95
96
  onMainPanelAction: (callback) => {
96
97
  // this needs to be a emit and on because the main panel action is triggered by the user and not by the plugin
97
- this.event.emit("action.requestMain");
98
- this.event.on("action.requestMain", ({ data }) => callback(data));
99
- }
98
+ this.event.emit('action.requestMain');
99
+ this.event.on('action.requestMain', ({ data }) => callback(data));
100
+ },
100
101
  };
101
102
  this.navigation = {
102
103
  toDashboard: () => {
103
- this.event.emit("global.navigation.triggerToDashboard");
104
- }
104
+ this.event.emit('global.navigation.triggerToDashboard');
105
+ },
105
106
  };
106
107
  this.ai = {
107
108
  getText: (messages, tools) => __awaiter(this, void 0, void 0, function* () {
@@ -112,7 +113,7 @@ export class RimoriClient {
112
113
  const token = yield this.pluginController.getToken();
113
114
  streamChatGPT(this.pluginController.getBackendUrl(), messages, tools || [], onMessage, token);
114
115
  }),
115
- getVoice: (text_1, ...args_1) => __awaiter(this, [text_1, ...args_1], void 0, function* (text, voice = "alloy", speed = 1, language) {
116
+ getVoice: (text_1, ...args_1) => __awaiter(this, [text_1, ...args_1], void 0, function* (text, voice = 'alloy', speed = 1, language) {
116
117
  const token = yield this.pluginController.getToken();
117
118
  return getTTSResponse(this.pluginController.getBackendUrl(), { input: text, voice, speed, language }, token);
118
119
  }),
@@ -129,8 +130,8 @@ export class RimoriClient {
129
130
  this.runtime = {
130
131
  fetchBackend: (url, options) => __awaiter(this, void 0, void 0, function* () {
131
132
  const token = yield this.pluginController.getToken();
132
- return fetch(this.pluginController.getBackendUrl() + url, Object.assign(Object.assign({}, options), { headers: Object.assign(Object.assign({}, options.headers), { 'Authorization': `Bearer ${token}` }) }));
133
- })
133
+ return fetch(this.pluginController.getBackendUrl() + url, Object.assign(Object.assign({}, options), { headers: Object.assign(Object.assign({}, options.headers), { Authorization: `Bearer ${token}` }) }));
134
+ }),
134
135
  };
135
136
  this.community = {
136
137
  /**
@@ -191,10 +192,10 @@ export class RimoriClient {
191
192
  return yield this.sharedContentController.updateSharedContent(id, content);
192
193
  }),
193
194
  /**
194
- * Complete a shared content item.
195
- * @param contentType The type of shared content to complete. E.g. assignments, exercises, etc.
196
- * @param assignmentId The id of the shared content item to complete.
197
- */
195
+ * Complete a shared content item.
196
+ * @param contentType The type of shared content to complete. E.g. assignments, exercises, etc.
197
+ * @param assignmentId The id of the shared content item to complete.
198
+ */
198
199
  complete: (contentType, assignmentId) => __awaiter(this, void 0, void 0, function* () {
199
200
  return yield this.sharedContentController.completeSharedContent(contentType, assignmentId);
200
201
  }),
@@ -213,22 +214,50 @@ export class RimoriClient {
213
214
  */
214
215
  remove: (id) => __awaiter(this, void 0, void 0, function* () {
215
216
  return yield this.sharedContentController.removeSharedContent(id);
216
- })
217
- }
217
+ }),
218
+ },
219
+ };
220
+ this.exercise = {
221
+ /**
222
+ * Fetches weekly exercises from the weekly_exercises view.
223
+ * Shows exercises for the current week that haven't expired.
224
+ * @returns Array of exercise objects.
225
+ */
226
+ view: () => __awaiter(this, void 0, void 0, function* () {
227
+ return this.exerciseController.viewWeeklyExercises();
228
+ }),
229
+ /**
230
+ * Creates a new exercise via the backend API.
231
+ * @param params Exercise creation parameters.
232
+ * @returns Created exercise object.
233
+ */
234
+ add: (params) => __awaiter(this, void 0, void 0, function* () {
235
+ return this.exerciseController.addExercise(params);
236
+ }),
237
+ /**
238
+ * Deletes an exercise via the backend API.
239
+ * @param id The exercise ID to delete.
240
+ * @returns Success status.
241
+ */
242
+ delete: (id) => __awaiter(this, void 0, void 0, function* () {
243
+ return this.exerciseController.deleteExercise(id);
244
+ }),
218
245
  };
219
246
  this.rimoriInfo = info;
220
247
  this.superbase = supabase;
221
248
  this.pluginController = pluginController;
222
- this.settingsController = new SettingsController(supabase, info.pluginId);
249
+ this.settingsController = new SettingsController(supabase, info.pluginId, info.guild);
223
250
  this.sharedContentController = new SharedContentController(this.superbase, this);
251
+ this.exerciseController = new ExerciseController(supabase, pluginController);
224
252
  this.accomplishmentHandler = new AccomplishmentHandler(info.pluginId);
225
253
  this.from = this.from.bind(this);
254
+ this.getTableName = this.getTableName.bind(this);
226
255
  this.db = {
227
256
  from: this.from,
228
257
  // storage: this.superbase.storage,
229
258
  // functions: this.superbase.functions,
230
259
  tablePrefix: info.tablePrefix,
231
- getTableName: this.getTableName.bind(this),
260
+ getTableName: this.getTableName,
232
261
  };
233
262
  this.plugin = {
234
263
  pluginId: info.pluginId,
@@ -247,7 +276,7 @@ export class RimoriClient {
247
276
  mainPanelPlugin: this.rimoriInfo.mainPanelPlugin,
248
277
  sidePanelPlugin: this.rimoriInfo.sidePanelPlugin,
249
278
  };
250
- }
279
+ },
251
280
  };
252
281
  }
253
282
  /**
@@ -272,11 +301,11 @@ export class RimoriClient {
272
301
  }
273
302
  getTableName(table) {
274
303
  if (/[A-Z]/.test(table)) {
275
- throw new Error("Table name cannot include uppercase letters. Please use snake_case for table names.");
304
+ throw new Error('Table name cannot include uppercase letters. Please use snake_case for table names.');
276
305
  }
277
- if (table.startsWith("global_")) {
278
- return table.replace("global_", "");
306
+ if (table.startsWith('global_')) {
307
+ return table.replace('global_', '');
279
308
  }
280
- return this.db.tablePrefix + "_" + table;
309
+ return this.db.tablePrefix + '_' + table;
281
310
  }
282
311
  }
@@ -1,4 +1,4 @@
1
- import { SupabaseClient } from "@supabase/supabase-js";
1
+ import { SupabaseClient } from '@supabase/supabase-js';
2
2
  export interface StandaloneConfig {
3
3
  url: string;
4
4
  key: string;
@@ -7,9 +7,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { createClient } from "@supabase/supabase-js";
11
- import { EventBus } from "../fromRimori/EventBus";
12
- import { DEFAULT_ANON_KEY, DEFAULT_ENDPOINT } from "../utils/endpoint";
10
+ import { createClient } from '@supabase/supabase-js';
11
+ import { EventBus } from '../fromRimori/EventBus';
12
+ import { DEFAULT_ANON_KEY, DEFAULT_ENDPOINT } from '../utils/endpoint';
13
13
  export class StandaloneClient {
14
14
  constructor(config) {
15
15
  this.supabase = createClient(config.url, config.key);
@@ -18,8 +18,10 @@ export class StandaloneClient {
18
18
  static getInstance() {
19
19
  return __awaiter(this, void 0, void 0, function* () {
20
20
  if (!StandaloneClient.instance) {
21
- const config = yield fetch("https://app.rimori.se/config.json").then(res => res.json()).catch(err => {
22
- console.warn("Error fetching config.json, using default values", err);
21
+ const config = yield fetch('https://app.rimori.se/config.json')
22
+ .then((res) => res.json())
23
+ .catch((err) => {
24
+ console.warn('Error fetching config.json, using default values', err);
23
25
  });
24
26
  StandaloneClient.instance = new StandaloneClient({
25
27
  url: (config === null || config === void 0 ? void 0 : config.SUPABASE_URL) || DEFAULT_ENDPOINT,
@@ -45,33 +47,50 @@ export class StandaloneClient {
45
47
  return __awaiter(this, void 0, void 0, function* () {
46
48
  const { error } = yield this.supabase.auth.signInWithPassword({ email, password });
47
49
  if (error) {
48
- console.error("Login failed:", error);
50
+ console.error('Login failed:', error);
49
51
  return false;
50
52
  }
51
- console.log("Successfully logged in");
53
+ console.log('Successfully logged in');
52
54
  return true;
53
55
  });
54
56
  }
55
57
  static initListeners(pluginId) {
56
58
  return __awaiter(this, void 0, void 0, function* () {
57
- console.warn("The plugin seams to not be running inside the Rimori platform. Switching to development standalone mode.");
59
+ console.warn('The plugin seams to not be running inside the Rimori platform. Switching to development standalone mode.');
58
60
  // console.log("event that needs to be handled", event);
59
61
  const { supabase, config } = yield StandaloneClient.getInstance();
60
62
  // EventBus.on("*", async (event) => {
61
- EventBus.respond("standalone", "global.supabase.requestAccess", () => __awaiter(this, void 0, void 0, function* () {
63
+ EventBus.respond('standalone', 'global.supabase.requestAccess', () => __awaiter(this, void 0, void 0, function* () {
62
64
  var _a;
63
65
  const session = yield supabase.auth.getSession();
64
- console.log("session", session);
66
+ console.log('session', session);
65
67
  // Call the NestJS backend endpoint instead of the Supabase edge function
68
+ // get current guild id if any
69
+ let guildId = null;
70
+ try {
71
+ const { data: { user }, } = yield supabase.auth.getUser();
72
+ if (user) {
73
+ const { data: profile } = yield supabase
74
+ .from('profiles')
75
+ .select('current_guild_id')
76
+ .eq('user_id', user.id)
77
+ .maybeSingle();
78
+ guildId = (profile === null || profile === void 0 ? void 0 : profile.current_guild_id) || null;
79
+ }
80
+ }
81
+ catch (_) {
82
+ guildId = null;
83
+ }
66
84
  const response = yield fetch(`${config.backendUrl}/plugin/token`, {
67
85
  method: 'POST',
68
86
  headers: {
69
87
  'Content-Type': 'application/json',
70
- 'Authorization': `Bearer ${(_a = session.data.session) === null || _a === void 0 ? void 0 : _a.access_token}`
88
+ Authorization: `Bearer ${(_a = session.data.session) === null || _a === void 0 ? void 0 : _a.access_token}`,
71
89
  },
72
90
  body: JSON.stringify({
73
- pluginId: pluginId
74
- })
91
+ pluginId: pluginId,
92
+ guildId: guildId,
93
+ }),
75
94
  });
76
95
  if (!response.ok) {
77
96
  const errorText = yield response.text();
@@ -88,9 +107,9 @@ export class StandaloneClient {
88
107
  expiration: new Date(Date.now() + 1000 * 60 * 60 * 1.5), // 1.5 hours
89
108
  };
90
109
  }));
91
- EventBus.on("*", (event) => __awaiter(this, void 0, void 0, function* () {
92
- console.log("[standalone] would send event to parent", event);
93
- }), ["standalone"]);
110
+ EventBus.on('*', (event) => __awaiter(this, void 0, void 0, function* () {
111
+ console.log('[standalone] would send event to parent', event);
112
+ }), ['standalone']);
94
113
  });
95
114
  }
96
115
  }
@@ -1,9 +1,9 @@
1
1
  export function setTheme(theme) {
2
- document.documentElement.classList.add("dark:text-gray-200");
2
+ document.documentElement.classList.add('dark:text-gray-200');
3
3
  if (isDarkTheme(theme)) {
4
- document.documentElement.setAttribute("data-theme", "dark");
5
- document.documentElement.classList.add('dark', "dark:bg-gray-950");
6
- document.documentElement.style.background = "hsl(var(--background))";
4
+ document.documentElement.setAttribute('data-theme', 'dark');
5
+ document.documentElement.classList.add('dark', 'dark:bg-gray-950');
6
+ document.documentElement.style.background = 'hsl(var(--background))';
7
7
  }
8
8
  }
9
9
  export function isDarkTheme(theme) {
@@ -19,24 +19,24 @@ export const PluginProvider = ({ children, pluginId, settings }) => {
19
19
  const [standaloneClient, setStandaloneClient] = useState(false);
20
20
  const [applicationMode, setApplicationMode] = useState(null);
21
21
  const [theme, setTheme] = useState(null);
22
- const isSidebar = applicationMode === "sidebar";
23
- const isSettings = applicationMode === "settings";
22
+ const isSidebar = applicationMode === 'sidebar';
23
+ const isSettings = applicationMode === 'settings';
24
24
  useEffect(() => {
25
25
  initEventBus(pluginId);
26
26
  // Check if we're in an iframe context - if not, we're standalone
27
27
  const standaloneDetected = window === window.parent;
28
28
  if (standaloneDetected && !standaloneClient) {
29
- StandaloneClient.getInstance().then(client => {
29
+ StandaloneClient.getInstance().then((client) => {
30
30
  client.needsLogin().then((needLogin) => setStandaloneClient(needLogin ? client : true));
31
31
  });
32
32
  }
33
33
  if ((!standaloneDetected && !plugin) || (standaloneDetected && standaloneClient === true)) {
34
- PluginController.getInstance(pluginId, standaloneDetected).then(client => {
34
+ PluginController.getInstance(pluginId, standaloneDetected).then((client) => {
35
35
  setPlugin(client);
36
36
  // Get applicationMode and theme from MessageChannel query params
37
37
  if (!standaloneDetected) {
38
- const mode = client.getQueryParam("applicationMode");
39
- const themeParam = client.getQueryParam("rm_theme");
38
+ const mode = client.getQueryParam('applicationMode');
39
+ const themeParam = client.getQueryParam('rm_theme');
40
40
  setApplicationMode(mode);
41
41
  setTheme(themeParam);
42
42
  }
@@ -71,13 +71,13 @@ export const PluginProvider = ({ children, pluginId, settings }) => {
71
71
  return () => body.removeEventListener('resize', handleResize);
72
72
  }, [plugin]);
73
73
  if (standaloneClient instanceof StandaloneClient) {
74
- return _jsx(StandaloneAuth, { onLogin: (email, password) => __awaiter(void 0, void 0, void 0, function* () {
74
+ return (_jsx(StandaloneAuth, { onLogin: (email, password) => __awaiter(void 0, void 0, void 0, function* () {
75
75
  if (yield standaloneClient.login(email, password))
76
76
  setStandaloneClient(true);
77
- }) });
77
+ }) }));
78
78
  }
79
79
  if (!plugin) {
80
- return "";
80
+ return '';
81
81
  }
82
82
  return (_jsxs(PluginContext.Provider, { value: plugin, children: [!(settings === null || settings === void 0 ? void 0 : settings.disableContextMenu) && !isSidebar && !isSettings && _jsx(ContextMenu, { client: plugin }), children] }));
83
83
  };
@@ -103,12 +103,12 @@ function getUrlParam(name) {
103
103
  }
104
104
  function initEventBus(pluginId) {
105
105
  // For now, use URL fallback for EventBus naming - this will be updated once MessageChannel is ready
106
- const isSidebar = getUrlParam("applicationMode") === "sidebar";
107
- EventBusHandler.getInstance("Plugin EventBus " + pluginId + " " + (isSidebar ? "sidebar" : "main"));
106
+ const isSidebar = getUrlParam('applicationMode') === 'sidebar';
107
+ EventBusHandler.getInstance('Plugin EventBus ' + pluginId + ' ' + (isSidebar ? 'sidebar' : 'main'));
108
108
  }
109
109
  function StandaloneAuth({ onLogin }) {
110
- const [user, setUser] = useState("");
111
- const [password, setPassword] = useState("");
110
+ const [user, setUser] = useState('');
111
+ const [password, setPassword] = useState('');
112
112
  return (_jsx("div", { style: {
113
113
  position: 'fixed',
114
114
  inset: 0,
@@ -116,7 +116,37 @@ function StandaloneAuth({ onLogin }) {
116
116
  alignItems: 'center',
117
117
  justifyContent: 'center',
118
118
  backgroundColor: 'rgba(0, 0, 0, 0.5)',
119
- }, children: _jsxs("div", { style: { backgroundColor: '#343534', padding: '1rem', borderRadius: '0.5rem', width: '500px', flexDirection: 'column', display: 'flex', alignItems: 'center', justifyContent: 'center' }, children: [_jsx("p", { style: { fontSize: '2rem', fontWeight: 'bold', marginBottom: '1rem', textAlign: 'center' }, children: "Rimori Login" }), _jsx("p", { style: { marginBottom: '1rem', textAlign: 'center' }, children: "Please login with your Rimori developer account for this plugin to be able to access the Rimori platform the same it will operate in the Rimori platform." }), _jsx("input", { style: { marginBottom: '1rem', width: '100%', padding: '0.5rem', borderRadius: '0.5rem', border: 'none', backgroundColor: '#444444' }, type: "email", placeholder: "Email", onChange: (e) => setUser(e.target.value) }), _jsx("input", { style: { marginBottom: '1rem', width: '100%', padding: '0.5rem', borderRadius: '0.5rem', border: 'none', backgroundColor: '#444444' }, type: "password", placeholder: "Password", onChange: (e) => setPassword(e.target.value) }), _jsx("button", { style: { marginBottom: '1rem', width: '100%', padding: '0.5rem', borderRadius: '0.5rem', border: 'none', backgroundColor: '#928358' }, onClick: () => {
119
+ }, children: _jsxs("div", { style: {
120
+ backgroundColor: '#343534',
121
+ padding: '1rem',
122
+ borderRadius: '0.5rem',
123
+ width: '500px',
124
+ flexDirection: 'column',
125
+ display: 'flex',
126
+ alignItems: 'center',
127
+ justifyContent: 'center',
128
+ }, children: [_jsx("p", { style: { fontSize: '2rem', fontWeight: 'bold', marginBottom: '1rem', textAlign: 'center' }, children: "Rimori Login" }), _jsx("p", { style: { marginBottom: '1rem', textAlign: 'center' }, children: "Please login with your Rimori developer account for this plugin to be able to access the Rimori platform the same it will operate in the Rimori platform." }), _jsx("input", { style: {
129
+ marginBottom: '1rem',
130
+ width: '100%',
131
+ padding: '0.5rem',
132
+ borderRadius: '0.5rem',
133
+ border: 'none',
134
+ backgroundColor: '#444444',
135
+ }, type: "email", placeholder: "Email", onChange: (e) => setUser(e.target.value) }), _jsx("input", { style: {
136
+ marginBottom: '1rem',
137
+ width: '100%',
138
+ padding: '0.5rem',
139
+ borderRadius: '0.5rem',
140
+ border: 'none',
141
+ backgroundColor: '#444444',
142
+ }, type: "password", placeholder: "Password", onChange: (e) => setPassword(e.target.value) }), _jsx("button", { style: {
143
+ marginBottom: '1rem',
144
+ width: '100%',
145
+ padding: '0.5rem',
146
+ borderRadius: '0.5rem',
147
+ border: 'none',
148
+ backgroundColor: '#928358',
149
+ }, onClick: () => {
120
150
  onLogin(user, password);
121
151
  }, children: "Login" })] }) }));
122
152
  }
@@ -1,61 +1,61 @@
1
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"
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
59
  };
60
60
  /**
61
61
  * Get the language name from the language code
@@ -2,11 +2,11 @@ export function isFullscreen() {
2
2
  return !!document.fullscreenElement;
3
3
  }
4
4
  export function triggerFullscreen(onStateChange, selector) {
5
- document.addEventListener("fullscreenchange", () => {
5
+ document.addEventListener('fullscreenchange', () => {
6
6
  onStateChange(isFullscreen());
7
7
  });
8
8
  try {
9
- const ref = document.querySelector(selector || "#root");
9
+ const ref = document.querySelector(selector || '#root');
10
10
  if (!isFullscreen()) {
11
11
  // @ts-ignore
12
12
  ref.requestFullscreen() || ref.webkitRequestFullscreen();
@@ -17,7 +17,7 @@ export function triggerFullscreen(onStateChange, selector) {
17
17
  }
18
18
  }
19
19
  catch (error) {
20
- console.error("Failed to enter fullscreen", error.message);
20
+ console.error('Failed to enter fullscreen', error.message);
21
21
  }
22
22
  onStateChange(isFullscreen());
23
23
  }
@@ -1,4 +1,4 @@
1
- export type LanguageLevel = "Pre-A1" | "A1" | "A2" | "B1" | "B2" | "C1" | "C2" | "Post-C2";
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
4
  export declare function getNeighborDifficultyLevel(difficulty: LanguageLevel, difficultyAdjustment: number): LanguageLevel;
@@ -1,4 +1,4 @@
1
- const codes = ["Pre-A1", "A1", "A2", "B1", "B2", "C1", "C2", "Post-C2"];
1
+ const codes = ['Pre-A1', 'A1', 'A2', 'B1', 'B2', 'C1', 'C2', 'Post-C2'];
2
2
  export function getDifficultyLevel(difficulty) {
3
3
  return codes.indexOf(difficulty) + 1;
4
4
  }
@@ -1,2 +1,2 @@
1
- export const DEFAULT_ENDPOINT = "https://pheptqdoqsdnadgoihvr.supabase.co";
2
- export const DEFAULT_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBoZXB0cWRvcXNkbmFkZ29paHZyIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzE2OTY2ODcsImV4cCI6MjA0NzI3MjY4N30.4GPFAXTF8685FaXISdAPNCIM-H3RGLo8GbyhQpu1mP0";
1
+ export const DEFAULT_ENDPOINT = 'https://pheptqdoqsdnadgoihvr.supabase.co';
2
+ export const DEFAULT_ANON_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBoZXB0cWRvcXNkbmFkZ29paHZyIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzE2OTY2ODcsImV4cCI6MjA0NzI3MjY4N30.4GPFAXTF8685FaXISdAPNCIM-H3RGLo8GbyhQpu1mP0';
@@ -1,4 +1,4 @@
1
- import { RimoriClient } from "../plugin/RimoriClient";
1
+ import { RimoriClient } from '../plugin/RimoriClient';
2
2
  /**
3
3
  * Sets up the web worker for the plugin to be able receive and send messages to Rimori.
4
4
  * @param pluginId - The id of the plugin to setup the worker for.
@@ -7,8 +7,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { EventBusHandler } from "../fromRimori/EventBus";
11
- import { PluginController } from "../plugin/PluginController";
10
+ import { EventBusHandler } from '../fromRimori/EventBus';
11
+ import { PluginController } from '../plugin/PluginController';
12
12
  /**
13
13
  * Sets up the web worker for the plugin to be able receive and send messages to Rimori.
14
14
  * @param pluginId - The id of the plugin to setup the worker for.
@@ -21,17 +21,17 @@ export function setupWorker(pluginId, init) {
21
21
  isWorker: true,
22
22
  location: {},
23
23
  parent: {
24
- postMessage: () => { }
24
+ postMessage: () => { },
25
25
  },
26
- addEventListener: () => { }
26
+ addEventListener: () => { },
27
27
  };
28
28
  // Assign the mock to globalThis.
29
29
  Object.assign(globalThis, { window: mockWindow });
30
- EventBusHandler.getInstance("Worker EventBus");
30
+ EventBusHandler.getInstance('Worker EventBus');
31
31
  const rimoriClient = yield PluginController.getInstance(pluginId);
32
32
  console.debug('[Worker] RimoriClient initialized.');
33
33
  yield init(rimoriClient);
34
34
  console.debug('[Worker] Worker initialized.');
35
- self.postMessage({ type: "rimori:acknowledged", pluginId: pluginId });
35
+ self.postMessage({ type: 'rimori:acknowledged', pluginId: pluginId });
36
36
  });
37
37
  }