@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.
- package/README.md +955 -28
- package/dist/components/MarkdownEditor.js +6 -4
- package/dist/components/PluginController.d.ts +21 -0
- package/dist/components/PluginController.js +116 -0
- package/dist/components/ai/Assistant.js +1 -1
- package/dist/components/ai/Avatar.d.ts +6 -4
- package/dist/components/ai/Avatar.js +14 -6
- package/dist/components/ai/EmbeddedAssistent/AudioInputField.js +1 -1
- package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.d.ts +2 -1
- package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.js +36 -15
- package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.d.ts +1 -0
- package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.js +3 -0
- package/dist/components/ai/EmbeddedAssistent/TTS/Player.d.ts +2 -0
- package/dist/components/ai/EmbeddedAssistent/TTS/Player.js +5 -0
- package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.d.ts +3 -0
- package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.js +41 -5
- package/dist/components/ai/utils.d.ts +1 -1
- package/dist/components.d.ts +1 -0
- package/dist/components.js +1 -0
- package/dist/controller/AIController.js +2 -1
- package/dist/controller/SettingsController.d.ts +15 -15
- package/dist/controller/SettingsController.js +15 -16
- package/dist/controller/SharedContentController.d.ts +58 -11
- package/dist/controller/SharedContentController.js +161 -26
- package/dist/controller/SidePluginController.d.ts +1 -12
- package/dist/controller/SidePluginController.js +2 -1
- package/dist/core/components/ContextMenu.d.ts +10 -0
- package/dist/core/components/ContextMenu.js +93 -0
- package/dist/core.d.ts +1 -4
- package/dist/core.js +1 -4
- package/dist/hooks/UseChatHook.d.ts +1 -1
- package/dist/index.d.ts +0 -8
- package/dist/index.js +0 -8
- package/dist/plugin/AccomplishmentHandler.d.ts +38 -0
- package/dist/plugin/AccomplishmentHandler.js +108 -0
- package/dist/plugin/ContextMenu.d.ts +17 -0
- package/dist/plugin/ContextMenu.js +45 -0
- package/dist/plugin/PluginController.js +6 -3
- package/dist/plugin/RimoriClient.d.ts +92 -65
- package/dist/plugin/RimoriClient.js +105 -75
- package/dist/plugin/ThemeSetter.js +2 -2
- package/dist/plugin/fromRimori/EventBus.d.ts +6 -3
- package/dist/plugin/fromRimori/EventBus.js +15 -9
- package/dist/plugin/fromRimori/PluginTypes.d.ts +48 -0
- package/dist/plugin/fromRimori/PluginTypes.js +1 -0
- package/dist/providers/PluginController.d.ts +21 -0
- package/dist/providers/PluginController.js +116 -0
- package/dist/providers/PluginProvider.js +26 -73
- package/dist/types/Actions.d.ts +4 -0
- package/dist/types/Actions.js +1 -0
- package/dist/utils/Language.d.ts +66 -0
- package/dist/utils/Language.js +67 -0
- package/dist/utils/difficultyConverter.d.ts +1 -0
- package/dist/utils/difficultyConverter.js +3 -0
- package/dist/worker/WorkerSetup.js +4 -4
- package/package.json +2 -3
- package/src/components/MarkdownEditor.tsx +78 -76
- package/src/components/ai/Assistant.tsx +1 -1
- package/src/components/ai/Avatar.tsx +66 -49
- package/src/components/ai/EmbeddedAssistent/AudioInputField.tsx +1 -1
- package/src/components/ai/EmbeddedAssistent/CircleAudioAvatar.tsx +82 -59
- package/src/components/ai/EmbeddedAssistent/TTS/MessageSender.ts +4 -0
- package/src/components/ai/EmbeddedAssistent/TTS/Player.ts +6 -0
- package/src/components/ai/EmbeddedAssistent/VoiceRecoder.tsx +51 -8
- package/src/components/ai/utils.ts +1 -1
- package/src/components.ts +2 -1
- package/src/controller/AIController.ts +2 -1
- package/src/controller/SettingsController.ts +83 -84
- package/src/controller/SharedContentController.ts +214 -53
- package/src/controller/SidePluginController.ts +3 -14
- package/src/core/components/ContextMenu.tsx +123 -0
- package/src/core.ts +1 -4
- package/src/hooks/UseChatHook.ts +17 -17
- package/src/index.ts +0 -8
- package/src/plugin/AccomplishmentHandler.ts +165 -0
- package/src/plugin/PluginController.ts +105 -103
- package/src/plugin/RimoriClient.ts +267 -250
- package/src/plugin/ThemeSetter.ts +2 -2
- package/src/plugin/fromRimori/EventBus.ts +23 -12
- package/src/plugin/fromRimori/PluginTypes.ts +64 -0
- package/src/providers/PluginProvider.tsx +63 -110
- package/src/types/Actions.ts +6 -0
- package/src/utils/Language.ts +70 -0
- package/src/utils/difficultyConverter.ts +4 -0
- package/src/worker/WorkerSetup.ts +4 -4
- package/dist/components/avatar/Assistant.d.ts +0 -9
- package/dist/components/avatar/Assistant.js +0 -59
- package/dist/components/avatar/Avatar.d.ts +0 -12
- package/dist/components/avatar/Avatar.js +0 -42
- package/dist/components/avatar/EmbeddedAssistent/AudioInputField.d.ts +0 -7
- package/dist/components/avatar/EmbeddedAssistent/AudioInputField.js +0 -38
- package/dist/components/avatar/EmbeddedAssistent/CircleAudioAvatar.d.ts +0 -7
- package/dist/components/avatar/EmbeddedAssistent/CircleAudioAvatar.js +0 -59
- package/dist/components/avatar/EmbeddedAssistent/TTS/MessageSender.d.ts +0 -19
- package/dist/components/avatar/EmbeddedAssistent/TTS/MessageSender.js +0 -84
- package/dist/components/avatar/EmbeddedAssistent/TTS/Player.d.ts +0 -25
- package/dist/components/avatar/EmbeddedAssistent/TTS/Player.js +0 -180
- package/dist/components/avatar/EmbeddedAssistent/VoiceRecoder.d.ts +0 -7
- package/dist/components/avatar/EmbeddedAssistent/VoiceRecoder.js +0 -45
- package/dist/components/avatar/utils.d.ts +0 -6
- 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 =
|
|
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
|
-
|
|
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
|
|
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, {
|
|
124
|
-
return
|
|
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
|
|
142
|
+
let listener;
|
|
137
143
|
const wrapper = (event) => {
|
|
138
144
|
handler(event);
|
|
139
|
-
|
|
145
|
+
listener === null || listener === void 0 ? void 0 : listener.off();
|
|
140
146
|
};
|
|
141
|
-
|
|
142
|
-
this.logIfDebug(`Added once listener ` + 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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
12
|
+
}, [pluginId]);
|
|
13
|
+
//route change
|
|
23
14
|
useEffect(() => {
|
|
24
15
|
if (!plugin)
|
|
25
16
|
return;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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 (
|
|
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 @@
|
|
|
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('
|
|
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('
|
|
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('
|
|
53
|
+
logIfDebug('Worker initialized.');
|
|
54
54
|
yield init(controller);
|
|
55
|
-
logIfDebug('
|
|
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.
|
|
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",
|