@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.
- package/.prettierignore +35 -0
- package/README.md +77 -71
- package/dist/cli/scripts/init/dev-registration.d.ts +1 -1
- package/dist/cli/scripts/init/dev-registration.js +4 -4
- package/dist/cli/scripts/init/main.js +1 -1
- package/dist/cli/scripts/init/package-setup.d.ts +1 -1
- package/dist/cli/scripts/init/package-setup.js +3 -3
- package/dist/cli/scripts/init/router-transformer.js +19 -12
- package/dist/cli/scripts/init/vite-config.d.ts +2 -2
- package/dist/cli/scripts/init/vite-config.js +2 -2
- package/dist/cli/scripts/release/release-config-upload.js +9 -9
- package/dist/cli/scripts/release/release-db-update.d.ts +1 -1
- package/dist/cli/scripts/release/release-db-update.js +9 -9
- package/dist/cli/scripts/release/release-file-upload.js +2 -2
- package/dist/cli/scripts/release/release.js +2 -2
- package/dist/cli/types/DatabaseTypes.d.ts +2 -2
- package/dist/components/CRUDModal.d.ts +1 -1
- package/dist/components/CRUDModal.js +3 -3
- package/dist/components/MarkdownEditor.js +16 -16
- package/dist/components/Spinner.js +2 -2
- package/dist/components/ai/Assistant.js +7 -8
- package/dist/components/ai/Avatar.d.ts +2 -2
- package/dist/components/ai/Avatar.js +14 -7
- package/dist/components/ai/EmbeddedAssistent/AudioInputField.js +5 -6
- package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.d.ts +1 -1
- package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.js +1 -2
- package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.d.ts +1 -2
- package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.js +4 -2
- package/dist/components/ai/EmbeddedAssistent/TTS/Player.js +1 -1
- package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.js +2 -3
- package/dist/components/audio/Playbutton.js +10 -7
- package/dist/components/components/ContextMenu.d.ts +1 -1
- package/dist/components/components/ContextMenu.js +19 -16
- package/dist/components.d.ts +10 -10
- package/dist/components.js +10 -10
- package/dist/core/controller/AIController.d.ts +2 -2
- package/dist/core/controller/AIController.js +20 -18
- package/dist/core/controller/ExerciseController.d.ts +52 -0
- package/dist/core/controller/ExerciseController.js +73 -0
- package/dist/core/controller/ObjectController.js +5 -5
- package/dist/core/controller/SettingsController.d.ts +22 -7
- package/dist/core/controller/SettingsController.js +73 -8
- package/dist/core/controller/SharedContentController.d.ts +3 -3
- package/dist/core/controller/SharedContentController.js +38 -20
- package/dist/core/controller/VoiceController.js +6 -4
- package/dist/core/core.d.ts +15 -14
- package/dist/core/core.js +7 -7
- package/dist/fromRimori/EventBus.js +23 -23
- package/dist/fromRimori/PluginTypes.d.ts +4 -4
- package/dist/hooks/UseChatHook.d.ts +3 -3
- package/dist/hooks/UseChatHook.js +9 -3
- package/dist/index.d.ts +10 -10
- package/dist/index.js +9 -9
- package/dist/plugin/AccomplishmentHandler.d.ts +5 -5
- package/dist/plugin/AccomplishmentHandler.js +31 -27
- package/dist/plugin/AudioController.d.ts +1 -1
- package/dist/plugin/AudioController.js +6 -6
- package/dist/plugin/Logger.d.ts +5 -0
- package/dist/plugin/Logger.js +65 -13
- package/dist/plugin/PluginController.d.ts +7 -1
- package/dist/plugin/PluginController.js +32 -27
- package/dist/plugin/RimoriClient.d.ts +39 -14
- package/dist/plugin/RimoriClient.js +60 -31
- package/dist/plugin/StandaloneClient.d.ts +1 -1
- package/dist/plugin/StandaloneClient.js +35 -16
- package/dist/plugin/ThemeSetter.js +4 -4
- package/dist/providers/PluginProvider.js +44 -14
- package/dist/utils/Language.js +57 -57
- package/dist/utils/PluginUtils.js +3 -3
- package/dist/utils/difficultyConverter.d.ts +1 -1
- package/dist/utils/difficultyConverter.js +1 -1
- package/dist/utils/endpoint.js +2 -2
- package/dist/worker/WorkerSetup.d.ts +1 -1
- package/dist/worker/WorkerSetup.js +6 -6
- package/eslint.config.js +53 -0
- package/example/docs/devdocs.md +50 -40
- package/example/docs/overview.md +1 -1
- package/example/docs/userdocs.md +4 -1
- package/example/rimori.config.ts +51 -49
- package/example/worker/vite.config.ts +3 -3
- package/example/worker/worker.ts +2 -2
- package/package.json +17 -4
- package/prettier.config.js +8 -0
- package/src/cli/scripts/init/dev-registration.ts +5 -8
- package/src/cli/scripts/init/env-setup.ts +1 -1
- package/src/cli/scripts/init/file-operations.ts +1 -1
- package/src/cli/scripts/init/html-cleaner.ts +2 -5
- package/src/cli/scripts/init/main.ts +16 -13
- package/src/cli/scripts/init/package-setup.ts +11 -15
- package/src/cli/scripts/init/router-transformer.ts +40 -37
- package/src/cli/scripts/init/tailwind-config.ts +17 -26
- package/src/cli/scripts/init/vite-config.ts +3 -3
- package/src/cli/scripts/release/release-config-upload.ts +11 -11
- package/src/cli/scripts/release/release-db-update.ts +12 -12
- package/src/cli/scripts/release/release-file-upload.ts +3 -3
- package/src/cli/scripts/release/release.ts +4 -4
- package/src/cli/types/DatabaseTypes.ts +7 -8
- package/src/components/CRUDModal.tsx +64 -48
- package/src/components/MarkdownEditor.tsx +58 -27
- package/src/components/Spinner.tsx +24 -17
- package/src/components/ai/Assistant.tsx +70 -70
- package/src/components/ai/Avatar.tsx +20 -16
- package/src/components/ai/EmbeddedAssistent/AudioInputField.tsx +63 -54
- package/src/components/ai/EmbeddedAssistent/CircleAudioAvatar.tsx +14 -5
- package/src/components/ai/EmbeddedAssistent/TTS/MessageSender.ts +75 -74
- package/src/components/ai/EmbeddedAssistent/TTS/Player.ts +177 -178
- package/src/components/ai/EmbeddedAssistent/VoiceRecoder.tsx +109 -94
- package/src/components/ai/utils.ts +4 -4
- package/src/components/audio/Playbutton.tsx +101 -93
- package/src/components/components/ContextMenu.tsx +47 -35
- package/src/components.ts +10 -10
- package/src/core/controller/AIController.ts +62 -50
- package/src/core/controller/ExerciseController.ts +98 -0
- package/src/core/controller/ObjectController.ts +15 -10
- package/src/core/controller/SettingsController.ts +89 -16
- package/src/core/controller/SharedContentController.ts +80 -44
- package/src/core/controller/VoiceController.ts +10 -8
- package/src/core/core.ts +15 -15
- package/src/fromRimori/EventBus.ts +76 -47
- package/src/fromRimori/PluginTypes.ts +26 -17
- package/src/fromRimori/readme.md +2 -2
- package/src/hooks/UseChatHook.ts +25 -15
- package/src/index.ts +10 -10
- package/src/plugin/AccomplishmentHandler.ts +53 -35
- package/src/plugin/AudioController.ts +18 -12
- package/src/plugin/Logger.ts +77 -19
- package/src/plugin/PluginController.ts +60 -44
- package/src/plugin/RimoriClient.ts +133 -69
- package/src/plugin/StandaloneClient.ts +51 -24
- package/src/plugin/ThemeSetter.ts +5 -5
- package/src/providers/PluginProvider.tsx +90 -36
- package/src/style.scss +3 -3
- package/src/utils/Language.ts +58 -58
- package/src/utils/PluginUtils.ts +16 -20
- package/src/utils/difficultyConverter.ts +2 -2
- package/src/utils/endpoint.ts +3 -2
- package/src/worker/WorkerSetup.ts +8 -9
- package/tsconfig.json +2 -4
- package/dist/components/LoggerExample.d.ts +0 -6
- package/dist/components/LoggerExample.js +0 -79
- package/dist/core/controller/AudioController.d.ts +0 -0
- package/dist/core/controller/AudioController.js +0 -1
- package/dist/hooks/UseLogger.d.ts +0 -30
- package/dist/hooks/UseLogger.js +0 -122
- package/dist/plugin/LoggerExample.d.ts +0 -16
- package/dist/plugin/LoggerExample.js +0 -140
- package/dist/utils/audioFormats.d.ts +0 -26
- package/dist/utils/audioFormats.js +0 -67
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { createClient, SupabaseClient } from
|
|
2
|
-
import { EventBus } from
|
|
3
|
-
import { DEFAULT_ANON_KEY, DEFAULT_ENDPOINT } from
|
|
1
|
+
import { createClient, SupabaseClient } from '@supabase/supabase-js';
|
|
2
|
+
import { EventBus } from '../fromRimori/EventBus';
|
|
3
|
+
import { DEFAULT_ANON_KEY, DEFAULT_ENDPOINT } from '../utils/endpoint';
|
|
4
4
|
|
|
5
5
|
export interface StandaloneConfig {
|
|
6
|
-
url: string
|
|
7
|
-
key: string
|
|
8
|
-
backendUrl?: string
|
|
6
|
+
url: string;
|
|
7
|
+
key: string;
|
|
8
|
+
backendUrl?: string;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export class StandaloneClient {
|
|
@@ -20,9 +20,11 @@ export class StandaloneClient {
|
|
|
20
20
|
|
|
21
21
|
public static async getInstance(): Promise<StandaloneClient> {
|
|
22
22
|
if (!StandaloneClient.instance) {
|
|
23
|
-
const config = await fetch(
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
const config = await fetch('https://app.rimori.se/config.json')
|
|
24
|
+
.then((res) => res.json())
|
|
25
|
+
.catch((err) => {
|
|
26
|
+
console.warn('Error fetching config.json, using default values', err);
|
|
27
|
+
});
|
|
26
28
|
StandaloneClient.instance = new StandaloneClient({
|
|
27
29
|
url: config?.SUPABASE_URL || DEFAULT_ENDPOINT,
|
|
28
30
|
key: config?.SUPABASE_ANON_KEY || DEFAULT_ANON_KEY,
|
|
@@ -44,33 +46,54 @@ export class StandaloneClient {
|
|
|
44
46
|
public async login(email: string, password: string) {
|
|
45
47
|
const { error } = await this.supabase.auth.signInWithPassword({ email, password });
|
|
46
48
|
if (error) {
|
|
47
|
-
console.error(
|
|
49
|
+
console.error('Login failed:', error);
|
|
48
50
|
return false;
|
|
49
51
|
}
|
|
50
|
-
console.log(
|
|
52
|
+
console.log('Successfully logged in');
|
|
51
53
|
return true;
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
public static async initListeners(pluginId: string) {
|
|
55
|
-
console.warn(
|
|
57
|
+
console.warn(
|
|
58
|
+
'The plugin seams to not be running inside the Rimori platform. Switching to development standalone mode.',
|
|
59
|
+
);
|
|
56
60
|
// console.log("event that needs to be handled", event);
|
|
57
61
|
const { supabase, config } = await StandaloneClient.getInstance();
|
|
58
62
|
|
|
59
63
|
// EventBus.on("*", async (event) => {
|
|
60
|
-
EventBus.respond(
|
|
64
|
+
EventBus.respond('standalone', 'global.supabase.requestAccess', async () => {
|
|
61
65
|
const session = await supabase.auth.getSession();
|
|
62
|
-
console.log(
|
|
63
|
-
|
|
66
|
+
console.log('session', session);
|
|
67
|
+
|
|
64
68
|
// Call the NestJS backend endpoint instead of the Supabase edge function
|
|
69
|
+
// get current guild id if any
|
|
70
|
+
let guildId: string | null = null;
|
|
71
|
+
try {
|
|
72
|
+
const {
|
|
73
|
+
data: { user },
|
|
74
|
+
} = await supabase.auth.getUser();
|
|
75
|
+
if (user) {
|
|
76
|
+
const { data: profile } = await supabase
|
|
77
|
+
.from('profiles')
|
|
78
|
+
.select('current_guild_id')
|
|
79
|
+
.eq('user_id', user.id)
|
|
80
|
+
.maybeSingle();
|
|
81
|
+
guildId = (profile as { current_guild_id?: string | null } | null)?.current_guild_id || null;
|
|
82
|
+
}
|
|
83
|
+
} catch (_) {
|
|
84
|
+
guildId = null;
|
|
85
|
+
}
|
|
86
|
+
|
|
65
87
|
const response = await fetch(`${config.backendUrl}/plugin/token`, {
|
|
66
88
|
method: 'POST',
|
|
67
89
|
headers: {
|
|
68
90
|
'Content-Type': 'application/json',
|
|
69
|
-
|
|
91
|
+
Authorization: `Bearer ${session.data.session?.access_token}`,
|
|
70
92
|
},
|
|
71
93
|
body: JSON.stringify({
|
|
72
|
-
pluginId: pluginId
|
|
73
|
-
|
|
94
|
+
pluginId: pluginId,
|
|
95
|
+
guildId: guildId,
|
|
96
|
+
}),
|
|
74
97
|
});
|
|
75
98
|
|
|
76
99
|
if (!response.ok) {
|
|
@@ -79,7 +102,7 @@ export class StandaloneClient {
|
|
|
79
102
|
}
|
|
80
103
|
|
|
81
104
|
const data = await response.json();
|
|
82
|
-
|
|
105
|
+
|
|
83
106
|
return {
|
|
84
107
|
token: data.token,
|
|
85
108
|
pluginId: pluginId,
|
|
@@ -88,11 +111,15 @@ export class StandaloneClient {
|
|
|
88
111
|
backendUrl: config.backendUrl,
|
|
89
112
|
tablePrefix: pluginId,
|
|
90
113
|
expiration: new Date(Date.now() + 1000 * 60 * 60 * 1.5), // 1.5 hours
|
|
91
|
-
}
|
|
114
|
+
};
|
|
92
115
|
});
|
|
93
116
|
|
|
94
|
-
EventBus.on(
|
|
95
|
-
|
|
96
|
-
|
|
117
|
+
EventBus.on(
|
|
118
|
+
'*',
|
|
119
|
+
async (event) => {
|
|
120
|
+
console.log('[standalone] would send event to parent', event);
|
|
121
|
+
},
|
|
122
|
+
['standalone'],
|
|
123
|
+
);
|
|
97
124
|
}
|
|
98
|
-
}
|
|
125
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export function setTheme(theme?: string | null) {
|
|
2
|
-
document.documentElement.classList.add(
|
|
2
|
+
document.documentElement.classList.add('dark:text-gray-200');
|
|
3
3
|
|
|
4
4
|
if (isDarkTheme(theme)) {
|
|
5
|
-
document.documentElement.setAttribute(
|
|
6
|
-
document.documentElement.classList.add('dark',
|
|
7
|
-
document.documentElement.style.background =
|
|
5
|
+
document.documentElement.setAttribute('data-theme', 'dark');
|
|
6
|
+
document.documentElement.classList.add('dark', 'dark:bg-gray-950');
|
|
7
|
+
document.documentElement.style.background = 'hsl(var(--background))';
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
10
|
|
|
@@ -20,4 +20,4 @@ export function isDarkTheme(theme?: string | null): boolean {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
return theme === 'dark';
|
|
23
|
-
}
|
|
23
|
+
}
|
|
@@ -10,7 +10,7 @@ interface PluginProviderProps {
|
|
|
10
10
|
pluginId: string;
|
|
11
11
|
settings?: {
|
|
12
12
|
disableContextMenu?: boolean;
|
|
13
|
-
}
|
|
13
|
+
};
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
const PluginContext = createContext<RimoriClient | null>(null);
|
|
@@ -20,29 +20,29 @@ export const PluginProvider: React.FC<PluginProviderProps> = ({ children, plugin
|
|
|
20
20
|
const [standaloneClient, setStandaloneClient] = useState<StandaloneClient | boolean>(false);
|
|
21
21
|
const [applicationMode, setApplicationMode] = useState<string | null>(null);
|
|
22
22
|
const [theme, setTheme] = useState<string | null>(null);
|
|
23
|
-
|
|
24
|
-
const isSidebar = applicationMode ===
|
|
25
|
-
const isSettings = applicationMode ===
|
|
23
|
+
|
|
24
|
+
const isSidebar = applicationMode === 'sidebar';
|
|
25
|
+
const isSettings = applicationMode === 'settings';
|
|
26
26
|
|
|
27
27
|
useEffect(() => {
|
|
28
28
|
initEventBus(pluginId);
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
// Check if we're in an iframe context - if not, we're standalone
|
|
31
31
|
const standaloneDetected = window === window.parent;
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
if (standaloneDetected && !standaloneClient) {
|
|
34
|
-
StandaloneClient.getInstance().then(client => {
|
|
34
|
+
StandaloneClient.getInstance().then((client) => {
|
|
35
35
|
client.needsLogin().then((needLogin) => setStandaloneClient(needLogin ? client : true));
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
if ((!standaloneDetected && !plugin) || (standaloneDetected && standaloneClient === true)) {
|
|
40
|
-
PluginController.getInstance(pluginId, standaloneDetected).then(client => {
|
|
40
|
+
PluginController.getInstance(pluginId, standaloneDetected).then((client) => {
|
|
41
41
|
setPlugin(client);
|
|
42
42
|
// Get applicationMode and theme from MessageChannel query params
|
|
43
43
|
if (!standaloneDetected) {
|
|
44
|
-
const mode = client.getQueryParam(
|
|
45
|
-
const themeParam = client.getQueryParam(
|
|
44
|
+
const mode = client.getQueryParam('applicationMode');
|
|
45
|
+
const themeParam = client.getQueryParam('rm_theme');
|
|
46
46
|
setApplicationMode(mode);
|
|
47
47
|
setTheme(themeParam);
|
|
48
48
|
}
|
|
@@ -81,13 +81,17 @@ export const PluginProvider: React.FC<PluginProviderProps> = ({ children, plugin
|
|
|
81
81
|
}, [plugin]);
|
|
82
82
|
|
|
83
83
|
if (standaloneClient instanceof StandaloneClient) {
|
|
84
|
-
return
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
return (
|
|
85
|
+
<StandaloneAuth
|
|
86
|
+
onLogin={async (email, password) => {
|
|
87
|
+
if (await standaloneClient.login(email, password)) setStandaloneClient(true);
|
|
88
|
+
}}
|
|
89
|
+
/>
|
|
90
|
+
);
|
|
87
91
|
}
|
|
88
92
|
|
|
89
93
|
if (!plugin) {
|
|
90
|
-
return
|
|
94
|
+
return '';
|
|
91
95
|
}
|
|
92
96
|
|
|
93
97
|
return (
|
|
@@ -114,7 +118,7 @@ function getUrlParam(name: string) {
|
|
|
114
118
|
const hashValue = hashParams.get(name);
|
|
115
119
|
if (hashValue) return hashValue;
|
|
116
120
|
}
|
|
117
|
-
|
|
121
|
+
|
|
118
122
|
// Fallback to regular URL search params
|
|
119
123
|
const url = new URL(window.location.href);
|
|
120
124
|
return url.searchParams.get(name);
|
|
@@ -122,34 +126,84 @@ function getUrlParam(name: string) {
|
|
|
122
126
|
|
|
123
127
|
function initEventBus(pluginId: string) {
|
|
124
128
|
// For now, use URL fallback for EventBus naming - this will be updated once MessageChannel is ready
|
|
125
|
-
const isSidebar = getUrlParam(
|
|
126
|
-
EventBusHandler.getInstance(
|
|
129
|
+
const isSidebar = getUrlParam('applicationMode') === 'sidebar';
|
|
130
|
+
EventBusHandler.getInstance('Plugin EventBus ' + pluginId + ' ' + (isSidebar ? 'sidebar' : 'main'));
|
|
127
131
|
}
|
|
128
132
|
|
|
129
133
|
function StandaloneAuth({ onLogin }: { onLogin: (user: string, password: string) => void }) {
|
|
130
|
-
const [user, setUser] = useState(
|
|
131
|
-
const [password, setPassword] = useState(
|
|
134
|
+
const [user, setUser] = useState('');
|
|
135
|
+
const [password, setPassword] = useState('');
|
|
132
136
|
return (
|
|
133
|
-
<div
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
137
|
+
<div
|
|
138
|
+
style={{
|
|
139
|
+
position: 'fixed',
|
|
140
|
+
inset: 0,
|
|
141
|
+
display: 'flex',
|
|
142
|
+
alignItems: 'center',
|
|
143
|
+
justifyContent: 'center',
|
|
144
|
+
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
145
|
+
}}
|
|
146
|
+
>
|
|
147
|
+
<div
|
|
148
|
+
style={{
|
|
149
|
+
backgroundColor: '#343534',
|
|
150
|
+
padding: '1rem',
|
|
151
|
+
borderRadius: '0.5rem',
|
|
152
|
+
width: '500px',
|
|
153
|
+
flexDirection: 'column',
|
|
154
|
+
display: 'flex',
|
|
155
|
+
alignItems: 'center',
|
|
156
|
+
justifyContent: 'center',
|
|
157
|
+
}}
|
|
158
|
+
>
|
|
142
159
|
<p style={{ fontSize: '2rem', fontWeight: 'bold', marginBottom: '1rem', textAlign: 'center' }}>Rimori Login</p>
|
|
143
160
|
<p style={{ marginBottom: '1rem', textAlign: 'center' }}>
|
|
144
|
-
Please login with your Rimori developer account for this plugin to be able to access the Rimori platform the
|
|
161
|
+
Please login with your Rimori developer account for this plugin to be able to access the Rimori platform the
|
|
162
|
+
same it will operate in the Rimori platform.
|
|
145
163
|
</p>
|
|
146
164
|
{/* email and password input */}
|
|
147
|
-
<input
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
165
|
+
<input
|
|
166
|
+
style={{
|
|
167
|
+
marginBottom: '1rem',
|
|
168
|
+
width: '100%',
|
|
169
|
+
padding: '0.5rem',
|
|
170
|
+
borderRadius: '0.5rem',
|
|
171
|
+
border: 'none',
|
|
172
|
+
backgroundColor: '#444444',
|
|
173
|
+
}}
|
|
174
|
+
type="email"
|
|
175
|
+
placeholder="Email"
|
|
176
|
+
onChange={(e) => setUser(e.target.value)}
|
|
177
|
+
/>
|
|
178
|
+
<input
|
|
179
|
+
style={{
|
|
180
|
+
marginBottom: '1rem',
|
|
181
|
+
width: '100%',
|
|
182
|
+
padding: '0.5rem',
|
|
183
|
+
borderRadius: '0.5rem',
|
|
184
|
+
border: 'none',
|
|
185
|
+
backgroundColor: '#444444',
|
|
186
|
+
}}
|
|
187
|
+
type="password"
|
|
188
|
+
placeholder="Password"
|
|
189
|
+
onChange={(e) => setPassword(e.target.value)}
|
|
190
|
+
/>
|
|
191
|
+
<button
|
|
192
|
+
style={{
|
|
193
|
+
marginBottom: '1rem',
|
|
194
|
+
width: '100%',
|
|
195
|
+
padding: '0.5rem',
|
|
196
|
+
borderRadius: '0.5rem',
|
|
197
|
+
border: 'none',
|
|
198
|
+
backgroundColor: '#928358',
|
|
199
|
+
}}
|
|
200
|
+
onClick={() => {
|
|
201
|
+
onLogin(user, password);
|
|
202
|
+
}}
|
|
203
|
+
>
|
|
204
|
+
Login
|
|
205
|
+
</button>
|
|
152
206
|
</div>
|
|
153
207
|
</div>
|
|
154
|
-
)
|
|
155
|
-
}
|
|
208
|
+
);
|
|
209
|
+
}
|
package/src/style.scss
CHANGED
|
@@ -66,7 +66,7 @@ dialog::backdrop {
|
|
|
66
66
|
ul {
|
|
67
67
|
@apply list-disc pl-8;
|
|
68
68
|
|
|
69
|
-
li>p {
|
|
69
|
+
li > p {
|
|
70
70
|
@apply mb-1;
|
|
71
71
|
}
|
|
72
72
|
}
|
|
@@ -74,7 +74,7 @@ dialog::backdrop {
|
|
|
74
74
|
ol {
|
|
75
75
|
@apply list-decimal pl-7;
|
|
76
76
|
|
|
77
|
-
li>p {
|
|
77
|
+
li > p {
|
|
78
78
|
@apply mb-1;
|
|
79
79
|
}
|
|
80
80
|
}
|
|
@@ -133,4 +133,4 @@ dialog::backdrop {
|
|
|
133
133
|
@apply max-w-full;
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
|
-
}
|
|
136
|
+
}
|
package/src/utils/Language.ts
CHANGED
|
@@ -1,61 +1,61 @@
|
|
|
1
1
|
export const languageKeys = {
|
|
2
|
-
sq:
|
|
3
|
-
ar:
|
|
4
|
-
hy:
|
|
5
|
-
az:
|
|
6
|
-
bn:
|
|
7
|
-
bs:
|
|
8
|
-
bg:
|
|
9
|
-
ca:
|
|
10
|
-
zh:
|
|
11
|
-
hr:
|
|
12
|
-
cs:
|
|
13
|
-
da:
|
|
14
|
-
nl:
|
|
15
|
-
en:
|
|
16
|
-
et:
|
|
17
|
-
fi:
|
|
18
|
-
fr:
|
|
19
|
-
gl:
|
|
20
|
-
de:
|
|
21
|
-
el:
|
|
22
|
-
he:
|
|
23
|
-
hi:
|
|
24
|
-
hu:
|
|
25
|
-
is:
|
|
26
|
-
id:
|
|
27
|
-
it:
|
|
28
|
-
ja:
|
|
29
|
-
kn:
|
|
30
|
-
kk:
|
|
31
|
-
ko:
|
|
32
|
-
lv:
|
|
33
|
-
lt:
|
|
34
|
-
mk:
|
|
35
|
-
ms:
|
|
36
|
-
mr:
|
|
37
|
-
mi:
|
|
38
|
-
ne:
|
|
39
|
-
no:
|
|
40
|
-
fa:
|
|
41
|
-
pl:
|
|
42
|
-
pt:
|
|
43
|
-
ro:
|
|
44
|
-
ru:
|
|
45
|
-
sr:
|
|
46
|
-
sk:
|
|
47
|
-
sl:
|
|
48
|
-
es:
|
|
49
|
-
sw:
|
|
50
|
-
sv:
|
|
51
|
-
tl:
|
|
52
|
-
ta:
|
|
53
|
-
th:
|
|
54
|
-
tr:
|
|
55
|
-
uk:
|
|
56
|
-
ur:
|
|
57
|
-
vi:
|
|
58
|
-
cy:
|
|
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
|
} as const;
|
|
60
60
|
|
|
61
61
|
export type Language = keyof typeof languageKeys;
|
|
@@ -69,4 +69,4 @@ export type Language = keyof typeof languageKeys;
|
|
|
69
69
|
export function getLanguageName(languageCode: Language, capitalize: boolean = false): string {
|
|
70
70
|
const lang = languageKeys[languageCode];
|
|
71
71
|
return capitalize ? lang.charAt(0).toUpperCase() + lang.slice(1) : lang;
|
|
72
|
-
}
|
|
72
|
+
}
|
package/src/utils/PluginUtils.ts
CHANGED
|
@@ -1,26 +1,22 @@
|
|
|
1
1
|
export function isFullscreen() {
|
|
2
|
-
|
|
2
|
+
return !!document.fullscreenElement;
|
|
3
3
|
}
|
|
4
4
|
|
|
5
5
|
export function triggerFullscreen(onStateChange: (isFullscreen: boolean) => void, selector?: string) {
|
|
6
|
-
|
|
7
|
-
onStateChange(isFullscreen());
|
|
8
|
-
});
|
|
9
|
-
try {
|
|
10
|
-
const ref = document.querySelector(selector || "#root")!
|
|
11
|
-
if (!isFullscreen()) {
|
|
12
|
-
// @ts-ignore
|
|
13
|
-
ref.requestFullscreen() || ref.webkitRequestFullscreen()
|
|
14
|
-
} else {
|
|
15
|
-
// @ts-ignore
|
|
16
|
-
document.exitFullscreen() || document.webkitExitFullscreen()
|
|
17
|
-
}
|
|
18
|
-
} catch (error: any) {
|
|
19
|
-
console.error("Failed to enter fullscreen", error.message);
|
|
20
|
-
}
|
|
6
|
+
document.addEventListener('fullscreenchange', () => {
|
|
21
7
|
onStateChange(isFullscreen());
|
|
8
|
+
});
|
|
9
|
+
try {
|
|
10
|
+
const ref = document.querySelector(selector || '#root')!;
|
|
11
|
+
if (!isFullscreen()) {
|
|
12
|
+
// @ts-ignore
|
|
13
|
+
ref.requestFullscreen() || ref.webkitRequestFullscreen();
|
|
14
|
+
} else {
|
|
15
|
+
// @ts-ignore
|
|
16
|
+
document.exitFullscreen() || document.webkitExitFullscreen();
|
|
17
|
+
}
|
|
18
|
+
} catch (error: any) {
|
|
19
|
+
console.error('Failed to enter fullscreen', error.message);
|
|
20
|
+
}
|
|
21
|
+
onStateChange(isFullscreen());
|
|
22
22
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const codes = [
|
|
1
|
+
const codes = ['Pre-A1', 'A1', 'A2', 'B1', 'B2', 'C1', 'C2', 'Post-C2'];
|
|
2
2
|
|
|
3
|
-
export type LanguageLevel =
|
|
3
|
+
export type LanguageLevel = 'Pre-A1' | 'A1' | 'A2' | 'B1' | 'B2' | 'C1' | 'C2' | 'Post-C2';
|
|
4
4
|
|
|
5
5
|
export function getDifficultyLevel(difficulty: LanguageLevel): number {
|
|
6
6
|
return codes.indexOf(difficulty) + 1;
|
package/src/utils/endpoint.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
export const DEFAULT_ENDPOINT =
|
|
2
|
-
export const DEFAULT_ANON_KEY =
|
|
1
|
+
export const DEFAULT_ENDPOINT = 'https://pheptqdoqsdnadgoihvr.supabase.co';
|
|
2
|
+
export const DEFAULT_ANON_KEY =
|
|
3
|
+
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBoZXB0cWRvcXNkbmFkZ29paHZyIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzE2OTY2ODcsImV4cCI6MjA0NzI3MjY4N30.4GPFAXTF8685FaXISdAPNCIM-H3RGLo8GbyhQpu1mP0';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { RimoriClient } from
|
|
2
|
-
import { EventBusHandler } from
|
|
3
|
-
import { PluginController } from
|
|
1
|
+
import { RimoriClient } from '../plugin/RimoriClient';
|
|
2
|
+
import { EventBusHandler } from '../fromRimori/EventBus';
|
|
3
|
+
import { PluginController } from '../plugin/PluginController';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Sets up the web worker for the plugin to be able receive and send messages to Rimori.
|
|
@@ -8,21 +8,20 @@ import { PluginController } from "../plugin/PluginController";
|
|
|
8
8
|
* @param init - The function containing the initialization logic.
|
|
9
9
|
*/
|
|
10
10
|
export async function setupWorker(pluginId: string, init: (client: RimoriClient) => void | Promise<void>) {
|
|
11
|
-
|
|
12
11
|
// Mock of the window object for the worker context to be able to use the PluginController.
|
|
13
12
|
const mockWindow = {
|
|
14
13
|
isWorker: true,
|
|
15
14
|
location: {},
|
|
16
15
|
parent: {
|
|
17
|
-
postMessage: () => {
|
|
16
|
+
postMessage: () => {},
|
|
18
17
|
},
|
|
19
|
-
addEventListener: () => {
|
|
18
|
+
addEventListener: () => {},
|
|
20
19
|
};
|
|
21
20
|
|
|
22
21
|
// Assign the mock to globalThis.
|
|
23
22
|
Object.assign(globalThis, { window: mockWindow });
|
|
24
23
|
|
|
25
|
-
EventBusHandler.getInstance(
|
|
24
|
+
EventBusHandler.getInstance('Worker EventBus');
|
|
26
25
|
|
|
27
26
|
const rimoriClient = await PluginController.getInstance(pluginId);
|
|
28
27
|
console.debug('[Worker] RimoriClient initialized.');
|
|
@@ -30,5 +29,5 @@ export async function setupWorker(pluginId: string, init: (client: RimoriClient)
|
|
|
30
29
|
await init(rimoriClient);
|
|
31
30
|
console.debug('[Worker] Worker initialized.');
|
|
32
31
|
|
|
33
|
-
self.postMessage({ type:
|
|
34
|
-
}
|
|
32
|
+
self.postMessage({ type: 'rimori:acknowledged', pluginId: pluginId });
|
|
33
|
+
}
|
package/tsconfig.json
CHANGED